|  | @ -783,3 +783,102 @@ func (s *LogService) makeCharacterMap(characters []*models.Character) map[string | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | 	return characterMap |  |  | 	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 | 
		
	
		
			
				|  |  |  |  |  | } |