Browse Source

add nextLogs and prevLogs suggestions to log.

thegreatrefactor
Gisle Aune 4 years ago
parent
commit
47b7877ab4
  1. 7
      database/mongodb/logs.go
  2. 6
      graph2/complexity.go
  3. 2
      graph2/gqlgen.yml
  4. 14
      graph2/schema/types/Log.gql
  5. 8
      graph2/types/log.go
  6. 10
      models/log.go
  7. 99
      services/logs.go

7
database/mongodb/logs.go

@ -101,6 +101,13 @@ func (r *logRepository) List(ctx context.Context, filter models.LogFilter) ([]*m
if len(filter.Events) > 0 {
query["event"] = bson.M{"$in": filter.Events}
}
if filter.MinDate != nil && filter.MaxDate != nil {
query["date"] = bson.M{"$gte": *filter.MinDate, "$lte": *filter.MaxDate}
} else if filter.MinDate != nil {
query["date"] = bson.M{"$gte": *filter.MinDate}
} else if filter.MaxDate != nil {
query["date"] = bson.M{"$lt": *filter.MaxDate}
}
logs := make([]*models.Log, 0, 32)
err := r.logs.Find(query).Sort("-date").Limit(filter.Limit).All(&logs)

6
graph2/complexity.go

@ -164,6 +164,12 @@ func complexity() (cr graphcore.ComplexityRoot) {
cr.Log.Posts = func(childComplexity int, kinds []string) int {
return childComplexity + hugeSublistComplexity
}
cr.Log.NextLogs = func(childComplexity int) int {
return childComplexity + (subListComplexity / 2)
}
cr.Log.PrevLogs = func(childComplexity int) int {
return childComplexity + (subListComplexity / 2)
}
cr.Story.Chapters = func(childComplexity int) int {
return childComplexity + bigSublistComplexity

2
graph2/gqlgen.yml

@ -37,6 +37,8 @@ models:
model: git.aiterp.net/rpdata/api/models.LogFilter
LogImporter:
model: git.aiterp.net/rpdata/api/models.LogImporter
LogSuggestion:
model: git.aiterp.net/rpdata/api/models.LogSuggestion
Comment:
model: git.aiterp.net/rpdata/api/models.Comment
ChapterCommentMode:

14
graph2/schema/types/Log.gql

@ -34,6 +34,20 @@ type Log {
# The posts of the logfile, which can be filtered by kinds.
posts(kinds:[String!]): [Post!]!
# Suggested next logs.
nextLogs: [LogSuggestion!]!
# Suggested previous logs.
prevLogs: [LogSuggestion!]!
}
# Suggested log
type LogSuggestion {
log: Log!
hasEvent: Boolean!
hasChannel: Boolean!
characters: [Character!]!
}
# Filter for logs query

8
graph2/types/log.go

@ -31,6 +31,14 @@ func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string
return r.logs.ListPosts(ctx, &models.PostFilter{LogID: &log.ShortID})
}
func (r *logResolver) NextLogs(ctx context.Context, obj *models.Log) ([]*models.LogSuggestion, error) {
return r.logs.NextLogs(ctx, obj)
}
func (r *logResolver) PrevLogs(ctx context.Context, obj *models.Log) ([]*models.LogSuggestion, error) {
return r.logs.PrevLogs(ctx, obj)
}
// LogResolver is a resolver
func LogResolver(s *services.Bundle) *logResolver {
return &logResolver{characters: s.Characters, logs: s.Logs, channels: s.Channels}

10
models/log.go

@ -15,6 +15,14 @@ type Log struct {
CharacterIDs []string `bson:"characterIds"`
}
// A LogSuggestion is a suggestion for a log.
type LogSuggestion struct {
Log *Log
Characters []*Character
HasChannel bool
HasEvent bool
}
// IsChangeObject is an interface implementation to identify it as a valid
// ChangeObject in GQL.
func (*Log) IsChangeObject() {
@ -28,6 +36,8 @@ type LogFilter struct {
Characters []string
Channels []string
Events []string
MinDate *time.Time
MaxDate *time.Time
Limit int
}

99
services/logs.go

@ -783,3 +783,102 @@ func (s *LogService) makeCharacterMap(characters []*models.Character) map[string
return characterMap
}
func (s *LogService) NextLogs(ctx context.Context, log *models.Log) ([]*models.LogSuggestion, error) {
minDate := log.Date.Add(time.Millisecond)
logs, err := s.logs.List(ctx, models.LogFilter{
MinDate: &minDate,
})
if err != nil {
return nil, err
}
sort.Slice(logs, func(i, j int) bool {
return logs[i].Date.Before(logs[j].Date)
})
return s.findSuggestions(ctx, log, logs)
}
func (s *LogService) PrevLogs(ctx context.Context, log *models.Log) ([]*models.LogSuggestion, error) {
logs, err := s.logs.List(ctx, models.LogFilter{
MaxDate: &log.Date,
})
if err != nil {
return nil, err
}
return s.findSuggestions(ctx, log, logs)
}
func (s *LogService) findSuggestions(ctx context.Context, log *models.Log, logs []*models.Log) ([]*models.LogSuggestion, error) {
characters, err := s.characterService.List(ctx, models.CharacterFilter{
IDs: log.CharacterIDs,
})
if err != nil {
return nil, err
}
charIntersect := func(l1, l2 *models.Log) []*models.Character {
results := make([]*models.Character, 0, len(l1.CharacterIDs))
for _, c1 := range characters {
for _, c2ID := range l2.CharacterIDs {
if c1.ID == c2ID {
results = append(results, c1)
break
}
}
}
return results
}
groupKey := func(characters []*models.Character) string {
if len(characters) == 0 {
return ""
} else if len(characters) == 1 {
return characters[0].ID
}
builder := strings.Builder{}
builder.WriteString(characters[0].ID)
for _, character := range characters {
builder.WriteRune(',')
builder.WriteString(character.ID)
}
return builder.String()
}
suggestions := make([]*models.LogSuggestion, 0, 16)
foundGroups := make(map[string]bool)
foundChannel := false
for _, log2 := range logs {
hasEvent := log.EventName != "" && log2.EventName == log.EventName
hasChannel := log.ChannelName == log2.ChannelName
characters := charIntersect(log, log2)
groupKey := groupKey(characters)
suggestion := &models.LogSuggestion{
Log: log2,
Characters: characters,
HasChannel: hasChannel,
HasEvent: hasEvent,
}
if hasChannel && foundChannel {
foundChannel = true
foundGroups[groupKey] = true
suggestions = append(suggestions, suggestion)
} else if hasEvent {
foundGroups[groupKey] = true
suggestions = append(suggestions, suggestion)
} else if len(suggestions) < 8 && !hasEvent && len(characters) > 1 && !foundGroups[groupKey] {
foundGroups[groupKey] = true
suggestions = append(suggestions, suggestion)
}
}
return suggestions, nil
}
Loading…
Cancel
Save