From 6ab6c1cc3b39ff03a414105317c3bfc9f03bf29a Mon Sep 17 00:00:00 2001 From: dd84ai Date: Sat, 25 Nov 2023 21:04:09 +0100 Subject: [PATCH] feat: u can order bases by different columns --- app/configurator/alerts.go | 22 ++++++----- app/configurator/configurators.go | 11 +++++- app/configurator/connection.go | 1 + app/configurator/models/model_templates.go | 6 +-- app/configurator/models/models.go | 34 +++++++++++++---- app/configurator/ping.go | 3 +- app/consoler/commands/alerts.go | 24 +++++++++++- app/consoler/commands/root.go | 28 ++++++++++++-- app/consoler/consoler_test.go | 2 +- app/settings/types/types.go | 2 + app/viewer/views/baseview/base.go | 43 +++++++++++++++++++++- 11 files changed, 142 insertions(+), 34 deletions(-) diff --git a/app/configurator/alerts.go b/app/configurator/alerts.go index 9da5f320..5dceb2b9 100644 --- a/app/configurator/alerts.go +++ b/app/configurator/alerts.go @@ -21,8 +21,8 @@ type AlertBoolType interface { } type AlertStringType interface { - models.AlertPingMessage - + models.AlertPingMessage | + models.ConfigBaseOrderingKey GetValue() string } @@ -79,10 +79,14 @@ type CfgAlertPingMessage = IConfiguratorAlertString[models.AlertPingMessage] var NewCfgAlertPingMessage = NewConfiguratorAlertString[models.AlertPingMessage] +type CfgBaseOrderingKey = IConfiguratorAlertString[models.ConfigBaseOrderingKey] + +var NewCfgBaseOrderingKey = NewConfiguratorAlertString[models.ConfigBaseOrderingKey] + func (c IConfiguratorAlertThreshold[T]) Set(channelID types.DiscordChannelID, value int) error { c.Unset(channelID) obj := T{ - AlertTemplate: models.AlertTemplate{ChannelID: channelID}, + OneValueTemplate: models.OneValueTemplate{ChannelID: channelID}, AlertTresholdShared: models.AlertTresholdShared{Threshold: value}, } result2 := c.db.Create(&obj) @@ -120,9 +124,7 @@ func (c IConfiguratorAlertThreshold[T]) Status(channelID types.DiscordChannelID) /////////////////////////// func (c IConfiguratorAlertBool[T]) Enable(channelID types.DiscordChannelID) error { - obj := T{ - AlertTemplate: models.AlertTemplate{ChannelID: channelID}, - } + obj := T{OneValueTemplate: models.OneValueTemplate{ChannelID: channelID}} result := c.db.Create(&obj) return result.Error } @@ -157,8 +159,8 @@ func (c IConfiguratorAlertBool[T]) Status(channelID types.DiscordChannelID) (boo func (c IConfiguratorAlertString[T]) Set(channelID types.DiscordChannelID, value string) error { c.Unset(channelID) obj := T{ - AlertTemplate: models.AlertTemplate{ChannelID: channelID}, - Value: value, + OneValueTemplate: models.OneValueTemplate{ChannelID: channelID}, + Value: value, } result2 := c.db.Create(&obj) return result2.Error @@ -172,7 +174,7 @@ func (c IConfiguratorAlertString[T]) Unset(channelID types.DiscordChannelID) err return result.Error } -func (c IConfiguratorAlertString[T]) Status(channelID types.DiscordChannelID) (types.PingMessage, error) { +func (c IConfiguratorAlertString[T]) Status(channelID types.DiscordChannelID) (string, error) { var obj T result := c.db.Where("channel_id = ?", channelID).Limit(1).Find(&obj) if result.Error != nil { @@ -184,5 +186,5 @@ func (c IConfiguratorAlertString[T]) Status(channelID types.DiscordChannelID) (t } str := obj.GetValue() - return types.PingMessage(str), result.Error + return str, result.Error } diff --git a/app/configurator/configurators.go b/app/configurator/configurators.go index e9befa3f..0e99c879 100644 --- a/app/configurator/configurators.go +++ b/app/configurator/configurators.go @@ -33,8 +33,12 @@ type Forum struct { Thread ForumThread Subforum ForumSubforum } +type Base struct { + Tags ConfiguratorBase + OrderBy CfgBaseOrderingKey +} type Configurators struct { - Bases ConfiguratorBase + Bases Base Players Players Alerts Alerts Forum Forum @@ -49,7 +53,10 @@ func NewConfigugurators(dbpath types.Dbpath) *Configurators { return &Configurators{ Configur: configur, Channels: NewConfiguratorChannel(configur), - Bases: NewConfiguratorBase(configur), + Bases: Base{ + Tags: NewConfiguratorBase(configur), + OrderBy: NewCfgBaseOrderingKey(configur), + }, Players: Players{ Systems: NewConfiguratorSystem(configur), Regions: NewConfiguratorRegion(configur), diff --git a/app/configurator/connection.go b/app/configurator/connection.go index ff97ec1c..fe1cd62b 100644 --- a/app/configurator/connection.go +++ b/app/configurator/connection.go @@ -55,6 +55,7 @@ func (cg *Configurator) AutoMigrateSchema() *Configurator { &models.AlertBaseIfHealthDecreasing{}, &models.AlertBaseIfUnderAttack{}, &models.AlertPingMessage{}, + &models.ConfigBaseOrderingKey{}, ) if !logus.CheckWarn(err, "AutoMigrateSchema was executed with problems", logus.OptError(err)) { logus.Info("AutoMigrateSchema was executed fine") diff --git a/app/configurator/models/model_templates.go b/app/configurator/models/model_templates.go index bd85e31a..66a00b91 100644 --- a/app/configurator/models/model_templates.go +++ b/app/configurator/models/model_templates.go @@ -17,11 +17,7 @@ func (t TagTemplate) GetTag() types.Tag { return types.Tag(t.Tag) } -type AlertPlayerMoreThan struct { - PlayersMoreThan int -} - -type AlertTemplate struct { +type OneValueTemplate struct { gorm.Model ChannelID types.DiscordChannelID Channel Channel `gorm:"references:ChannelID,unique"` diff --git a/app/configurator/models/models.go b/app/configurator/models/models.go index e9e6f5dd..f11074b7 100644 --- a/app/configurator/models/models.go +++ b/app/configurator/models/models.go @@ -64,38 +64,58 @@ func (t AlertTresholdShared) GetThreshold() int { } type AlertNeutralPlayersEqualOrGreater struct { - AlertTemplate + OneValueTemplate AlertTresholdShared } type AlertEnemiesEqualOrGreater struct { - AlertTemplate + OneValueTemplate AlertTresholdShared } type AlertFriendsEqualOrGreater struct { - AlertTemplate + OneValueTemplate AlertTresholdShared } // ====== Shared alerts for all bases ========= type AlertBaseHealthLowerThan struct { - AlertTemplate + OneValueTemplate AlertTresholdShared } type AlertBaseIfHealthDecreasing struct { - AlertTemplate + OneValueTemplate } type AlertBaseIfUnderAttack struct { - AlertTemplate + OneValueTemplate } type AlertPingMessage struct { - AlertTemplate + OneValueTemplate Value string } func (a AlertPingMessage) GetValue() string { return a.Value } + +// ====== Configs ========= + +type ConfigBaseOrderingKey struct { + OneValueTemplate + Value string +} + +// i know it can be Constraint. But if i add it as `struct tag` it breaks typing +// and kind of hard to figure out how to fix nicely +const ( + BaseKeyName types.OrderKey = "name" + BaseKeyAffiliation types.OrderKey = "affiliation" +) + +var ConfigBaseOrderingKeyAllowedTags = []types.OrderKey{BaseKeyName, BaseKeyAffiliation} + +func (a ConfigBaseOrderingKey) GetValue() string { + return a.Value +} diff --git a/app/configurator/ping.go b/app/configurator/ping.go index aeeb47b8..08e42a4a 100644 --- a/app/configurator/ping.go +++ b/app/configurator/ping.go @@ -8,7 +8,8 @@ import ( ) func GetPingingMessage(ChannelID types.DiscordChannelID, configurator *Configurators, Discorder *discorder.Discorder) types.PingMessage { - pingMessage, err := configurator.Alerts.PingMessage.Status(ChannelID) + pingMessageStr, err := configurator.Alerts.PingMessage.Status(ChannelID) + pingMessage := types.PingMessage(pingMessageStr) logus.Debug("RenderAlertTemplate.PingMessage.Status", logus.OptError(err), logus.PingMessage(pingMessage)) if err != nil { ownerID, err := Discorder.GetOwnerID(ChannelID) diff --git a/app/consoler/commands/alerts.go b/app/consoler/commands/alerts.go index 9a181df2..0f9d77f1 100644 --- a/app/consoler/commands/alerts.go +++ b/app/consoler/commands/alerts.go @@ -5,7 +5,10 @@ import ( "darkbot/app/consoler/commands/cmdgroup" "darkbot/app/consoler/printer" "darkbot/app/settings/logus" + "darkbot/app/settings/types" + "darkbot/app/settings/utils" "strconv" + "strings" "github.com/spf13/cobra" ) @@ -225,15 +228,16 @@ func NewAlertSetStringCommand[T configurator.AlertStringType]( cmdGroup *cmdgroup.CmdGroup, cfgTags configurator.IConfiguratorAlertString[T], channels configurator.ConfiguratorChannel, + allowed_order_keys []types.OrderKey, ) *AlertSetStringCommand[T] { t := &AlertSetStringCommand[T]{CmdGroup: cmdGroup, cfgTags: cfgTags, channels: channels} - t.CreateSetCmd() + t.CreateSetCmd(allowed_order_keys) t.CreateUnsetCmd() t.CreateStatusCmd() return t } -func (t *AlertSetStringCommand[T]) CreateSetCmd() { +func (t *AlertSetStringCommand[T]) CreateSetCmd(allowed_order_keys []types.OrderKey) { command := &cobra.Command{ Use: "set", Short: "Set Value (provide 'set StringValue')", @@ -245,6 +249,22 @@ func (t *AlertSetStringCommand[T]) CreateSetCmd() { } str := args[0] + + if len(allowed_order_keys) > 0 { + is_allowed_tag := false + for _, tag := range allowed_order_keys { + if string(tag) == str { + is_allowed_tag = true + } + } + + if !is_allowed_tag { + printer.Println(cmd, "ERR only next values are allowed: "+strings.Join(utils.CompL(allowed_order_keys, + func(x types.OrderKey) string { return string(x) }), ", ")) + return + } + } + err := t.cfgTags.Set(t.GetChannelID(), str) if err != nil { printer.Println(cmd, "ERR msg="+err.Error()) diff --git a/app/consoler/commands/root.go b/app/consoler/commands/root.go index 0c28fe79..b6887dc5 100644 --- a/app/consoler/commands/root.go +++ b/app/consoler/commands/root.go @@ -8,6 +8,8 @@ import ( "darkbot/app/consoler/printer" "darkbot/app/settings" "darkbot/app/settings/logus" + "darkbot/app/settings/types" + "fmt" "github.com/spf13/cobra" ) @@ -45,16 +47,33 @@ func CreateConsoler( ) root := newRootCommands(&rootGroup) + baseGroup := root.GetChild( + root.CurrentCmd, + cmdgroup.Command("base"), + cmdgroup.ShortDesc("Base commands"), + ) + NewTagCommands( - root.GetChild( - root.CurrentCmd, - cmdgroup.Command("base"), - cmdgroup.ShortDesc("Base commands"), + baseGroup.GetChild( + baseGroup.CurrentCmd, + cmdgroup.Command("tags"), + cmdgroup.ShortDesc("base tags u add for tracking"), ), configurator.NewConfiguratorBase(configur), configurator.NewConfiguratorChannel(configur), ) + NewAlertSetStringCommand[models.ConfigBaseOrderingKey]( + baseGroup.GetChild( + baseGroup.CurrentCmd, + cmdgroup.Command("order_by"), + cmdgroup.ShortDesc(fmt.Sprintf("changing ordering to one of allowed keys: %v", models.ConfigBaseOrderingKeyAllowedTags)), + ), + configurator.NewCfgBaseOrderingKey(configur), + configurator.NewConfiguratorChannel(configur), + models.ConfigBaseOrderingKeyAllowedTags, + ) + forumGroup := root.GetChild( root.CurrentCmd, cmdgroup.Command("forum"), @@ -237,6 +256,7 @@ func CreateConsoler( ), configurator.NewCfgAlertPingMessage(configur), configurator.NewConfiguratorChannel(configur), + []types.OrderKey{}, ) return consolerCmd diff --git a/app/consoler/consoler_test.go b/app/consoler/consoler_test.go index 2e629258..bb082c25 100644 --- a/app/consoler/consoler_test.go +++ b/app/consoler/consoler_test.go @@ -29,7 +29,7 @@ func TestGrabStdout(t *testing.T) { func TestAddBaseTag(t *testing.T) { configurator.FixtureMigrator(func(dbpath types.Dbpath) { channelID, _ := configurator.FixtureChannel(dbpath) - assert.Contains(t, NewConsoler(dbpath).Execute(settings.Config.ConsolerPrefix+` base add "bla bla" sdf`, channelID).String(), "OK tags are added") + assert.Contains(t, NewConsoler(dbpath).Execute(settings.Config.ConsolerPrefix+` base tags add "bla bla" sdf`, channelID).String(), "OK tags are added") }) } diff --git a/app/settings/types/types.go b/app/settings/types/types.go index 80f668db..ee3d822e 100644 --- a/app/settings/types/types.go +++ b/app/settings/types/types.go @@ -32,3 +32,5 @@ type ViewBeginning string type ViewHeader string type ViewRecord string type ViewEnd string + +type OrderKey string diff --git a/app/viewer/views/baseview/base.go b/app/viewer/views/baseview/base.go index 31c205b3..8630c4af 100644 --- a/app/viewer/views/baseview/base.go +++ b/app/viewer/views/baseview/base.go @@ -1,6 +1,7 @@ package baseview import ( + "darkbot/app/configurator/models" "darkbot/app/scrappy/base" "darkbot/app/settings/logus" "darkbot/app/settings/types" @@ -102,6 +103,33 @@ func MatchBases(bases []base.Base, tags []types.Tag) []base.Base { return result } +type ForbiddenOrderKey struct{ order_key types.OrderKey } + +func ErrorForbiddenOrderKey(order_key types.OrderKey) ForbiddenOrderKey { + return ForbiddenOrderKey{order_key: order_key} +} + +func (f ForbiddenOrderKey) Error() string { return fmt.Sprintf("Forbidden order key=%s", f.order_key) } + +func (b *TemplateBase) sortBases(bases []base.Base, order_key types.OrderKey) ([]base.Base, error) { + + switch order_key { + case models.BaseKeyName: + sort.Slice(bases, func(i, j int) bool { + return bases[i].Name < bases[j].Name + }) + case models.BaseKeyAffiliation: + sort.Slice(bases, func(i, j int) bool { + return bases[i].Affiliation < bases[j].Affiliation + }) + default: + logus.Error(fmt.Sprintf("forbidden order order_key=%s, only keys=%v are allowed", order_key, models.ConfigBaseOrderingKeyAllowedTags)) + return bases, ErrorForbiddenOrderKey(order_key) + } + + return bases, nil +} + const HealthRateDecreasingThreshold = -0.01 func (b *TemplateBase) GenerateRecords() error { @@ -117,9 +145,20 @@ func (b *TemplateBase) GenerateRecords() error { UnderAttackPhrase := "\n@underAttack;" bases := []TemplateAugmentedBase{} - tags, _ := b.api.Bases.TagsList(b.channelID) - + tags, _ := b.api.Bases.Tags.TagsList(b.channelID) matchedBases := MatchBases(record.List, tags) + + order_key, err := b.api.Bases.OrderBy.Status(b.channelID) + if !logus.CheckDebug(err, "failed to query Order by key") { + matchedBases, err = b.sortBases(matchedBases, types.OrderKey(order_key)) + + base_table_will_be_rendered := len(matchedBases) > 0 + if err != nil && base_table_will_be_rendered { + b.main.AppendRecord(types.ViewRecord(fmt.Sprintf("ERR %s", err.Error()))) + return err + } + } + healthDeritives, healthDerivativeErr := CalculateDerivates(tags, b.api) DerivativesInitializing := healthDerivativeErr != nil