|
@@ -5,23 +5,20 @@ import (
|
|
|
"sync"
|
|
|
)
|
|
|
|
|
|
-
|
|
|
- TODO:
|
|
|
- This can be optimized by storing more than 1 element from each container,
|
|
|
- and then refilling elements of the containers in parallel.
|
|
|
-*/
|
|
|
-
|
|
|
type Splicer []struct {
|
|
|
basepoint uint
|
|
|
page pub.Container
|
|
|
- element pub.Tangible
|
|
|
+ elements []pub.Tangible
|
|
|
}
|
|
|
|
|
|
func (s Splicer) Harvest(quantity uint, startingPoint uint) ([]pub.Tangible, pub.Container, uint) {
|
|
|
+
|
|
|
clone := s.clone()
|
|
|
|
|
|
+ clone.replenish(int(quantity + startingPoint))
|
|
|
+
|
|
|
for i := 0; i < int(startingPoint); i++ {
|
|
|
- clone.microharvest()
|
|
|
+ _ = clone.microharvest()
|
|
|
}
|
|
|
|
|
|
output := make([]pub.Tangible, 0, quantity)
|
|
@@ -40,25 +37,52 @@ func (s Splicer) Harvest(quantity uint, startingPoint uint) ([]pub.Tangible, pub
|
|
|
func (s Splicer) clone() *Splicer {
|
|
|
newSplicer := make(Splicer, len(s))
|
|
|
copy(newSplicer, s)
|
|
|
+ for i := range newSplicer {
|
|
|
+ copy(newSplicer[i].elements, s[i].elements)
|
|
|
+ }
|
|
|
return &newSplicer
|
|
|
}
|
|
|
|
|
|
+func (s Splicer) replenish(amount int) {
|
|
|
+ var wg sync.WaitGroup
|
|
|
+ for i, source := range s {
|
|
|
+ i := i
|
|
|
+ source := source
|
|
|
+ wg.Add(1)
|
|
|
+ go func() {
|
|
|
+ if len(source.elements) < amount && source.page != nil {
|
|
|
+ var newElements []pub.Tangible
|
|
|
+ newElements, s[i].page, s[i].basepoint = source.page.Harvest(uint(amount - len(source.elements)), source.basepoint)
|
|
|
+ s[i].elements = append(s[i].elements, newElements...)
|
|
|
+ }
|
|
|
+ wg.Done()
|
|
|
+ }()
|
|
|
+ }
|
|
|
+ wg.Wait()
|
|
|
+}
|
|
|
+
|
|
|
func (s Splicer) microharvest() pub.Tangible {
|
|
|
var mostRecent pub.Tangible
|
|
|
var mostRecentIndex int
|
|
|
for i, candidate := range s {
|
|
|
+ if len(candidate.elements) == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ candidateElement := candidate.elements[0]
|
|
|
+
|
|
|
if mostRecent == nil {
|
|
|
- mostRecent = candidate.element
|
|
|
+ mostRecent = candidateElement
|
|
|
mostRecentIndex = i
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- if candidate.element == nil {
|
|
|
+ if candidateElement == nil {
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- if candidate.element.Timestamp().After(mostRecent.Timestamp()) {
|
|
|
- mostRecent = candidate.element
|
|
|
+ if candidateElement.Timestamp().After(mostRecent.Timestamp()) {
|
|
|
+ mostRecent = candidateElement
|
|
|
mostRecentIndex = i
|
|
|
continue
|
|
|
}
|
|
@@ -68,19 +92,8 @@ func (s Splicer) microharvest() pub.Tangible {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- if s[mostRecentIndex].page != nil {
|
|
|
- var elements []pub.Tangible
|
|
|
- elements, s[mostRecentIndex].page, s[mostRecentIndex].basepoint = s[mostRecentIndex].page.Harvest(1, s[mostRecentIndex].basepoint)
|
|
|
- if len(elements) > 1 {
|
|
|
- panic("harvest returned more that one element when I only asked for one")
|
|
|
- } else if len(elements) == 0 {
|
|
|
- s[mostRecentIndex].element = nil
|
|
|
- } else {
|
|
|
- s[mostRecentIndex].element = elements[0]
|
|
|
- }
|
|
|
- } else {
|
|
|
- s[mostRecentIndex].element = nil
|
|
|
- }
|
|
|
+
|
|
|
+ s[mostRecentIndex].elements = s[mostRecentIndex].elements[1:]
|
|
|
|
|
|
return mostRecent
|
|
|
}
|
|
@@ -94,29 +107,16 @@ func NewSplicer(inputs []string) *Splicer {
|
|
|
wg.Add(1)
|
|
|
go func() {
|
|
|
fetched := pub.FetchUserInput(input)
|
|
|
- var children pub.Container
|
|
|
switch narrowed := fetched.(type) {
|
|
|
case pub.Tangible:
|
|
|
- children = narrowed.Children()
|
|
|
+ s[i].page = narrowed.Children()
|
|
|
case *pub.Collection:
|
|
|
- children = narrowed
|
|
|
+ s[i].page = narrowed
|
|
|
default:
|
|
|
panic("cannot splice non-Tangible, non-Collection")
|
|
|
}
|
|
|
-
|
|
|
- if children != nil {
|
|
|
- var elements []pub.Tangible
|
|
|
- elements, s[i].page, s[i].basepoint = children.Harvest(1, 0)
|
|
|
- if len(elements) > 1 {
|
|
|
- panic("harvest returned more that one element when I only asked for one")
|
|
|
- } else if len(elements) == 0 {
|
|
|
- s[i].element = nil
|
|
|
- } else {
|
|
|
- s[i].element = elements[0]
|
|
|
- }
|
|
|
- } else {
|
|
|
- s[i].element = nil
|
|
|
- }
|
|
|
+ s[i].basepoint = 0
|
|
|
+ s[i].elements = []pub.Tangible{}
|
|
|
wg.Done()
|
|
|
}()
|
|
|
}
|