/*:#localized(key: "PuttingTheOrderBack")
 # Putting the order back

 Often you *do* need results in a specific order: frame 1's pixels have to line up
 with frame 1's position in the stack. The trick you already know: have each child
 return **its index alongside its value**, then reassemble once they're all in. A
 dictionary keyed by index makes it clean.
 */
//#-editable-code
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

func loadFrame(_ index: Int) async -> (index: Int, brightness: Double) {
    let delay = Double.random(in: 0.1...0.9)
    try? await Task.sleep(for: .seconds(delay))
    return (index, Double(index) * 1.5)
}

Task {
    var byIndex: [Int: Double] = [:]

    await withTaskGroup(of: (index: Int, brightness: Double).self) { group in
        for index in 1...6 {
            group.addTask { await loadFrame(index) }
        }
        for await frame in group {
            byIndex[frame.index] = frame.brightness   // file it under its index
        }
    }

    // Now rebuild the original 1...6 order, whatever order they arrived in.
    let ordered = byIndex.keys.sorted().map { byIndex[$0]! }
    print("In submission order: \(ordered)")
    PlaygroundPage.current.finishExecution()
}
//#-end-editable-code
/*:#localized(key: "PuttingTheOrderBack-2")
 **Watch it run:** the results *arrive* scrambled, but `ordered` always prints
 `[1.5, 3.0, 4.5, 6.0, 7.5, 9.0]`. You let the tasks finish whenever they finish,
 then imposed order at the end using the index each one carried home. This "return
 `(index, value)`, then sort" move is the standard way to keep a stack's frames
 aligned.

 [Previous](@previous)  |  page 5 of 9  |  [Next: When a Child Throws: withThrowingTaskGroup](@next)
 */
