add nextLogs and prevLogs suggestions to log.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user