mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-15 00:19:29 +01:00
84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
// Copyright (c) 2021 Shivaram Lingamneni <slingamn@cs.stanford.edu>
|
|
// released under the MIT license
|
|
|
|
package history
|
|
|
|
import (
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
type TargetListing struct {
|
|
CfName string
|
|
Time time.Time
|
|
}
|
|
|
|
// Merge `base`, a paging window of targets, with `extras` (the target entries
|
|
// for all joined channels).
|
|
func MergeTargets(base []TargetListing, extra []TargetListing, start, end time.Time, limit int) (results []TargetListing) {
|
|
if len(extra) == 0 {
|
|
return base
|
|
}
|
|
SortCorrespondents(extra)
|
|
|
|
start, end, ascending := MinMaxAsc(start, end, time.Time{})
|
|
predicate := func(t time.Time) bool {
|
|
return (start.IsZero() || start.Before(t)) && (end.IsZero() || end.After(t))
|
|
}
|
|
|
|
prealloc := len(base) + len(extra)
|
|
if limit < prealloc {
|
|
prealloc = limit
|
|
}
|
|
results = make([]TargetListing, 0, prealloc)
|
|
|
|
if !ascending {
|
|
ReverseCorrespondents(base)
|
|
ReverseCorrespondents(extra)
|
|
}
|
|
|
|
for len(results) < limit {
|
|
if len(extra) != 0 {
|
|
if !predicate(extra[0].Time) {
|
|
extra = extra[1:]
|
|
continue
|
|
}
|
|
if len(base) != 0 {
|
|
if base[0].Time.Before(extra[0].Time) == ascending {
|
|
results = append(results, base[0])
|
|
base = base[1:]
|
|
} else {
|
|
results = append(results, extra[0])
|
|
extra = extra[1:]
|
|
}
|
|
} else {
|
|
results = append(results, extra[0])
|
|
extra = extra[1:]
|
|
}
|
|
} else if len(base) != 0 {
|
|
results = append(results, base[0])
|
|
base = base[1:]
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
if !ascending {
|
|
ReverseCorrespondents(results)
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReverseCorrespondents(results []TargetListing) {
|
|
// lol, generics when?
|
|
for i, j := 0, len(results)-1; i < j; i, j = i+1, j-1 {
|
|
results[i], results[j] = results[j], results[i]
|
|
}
|
|
}
|
|
|
|
func SortCorrespondents(list []TargetListing) {
|
|
sort.Slice(list, func(i, j int) bool {
|
|
return list[i].Time.Before(list[j].Time)
|
|
})
|
|
}
|