import { shuffle } from "@thi.ng/arrays/shuffle" ; import { isPlainObject } from "@thi.ng/checks" ; import type { IRandom } from "@thi.ng/random" ; import { SYSTEM } from "@thi.ng/random/system" ; import type { Reducer , Transducer } from "./api.js" ; import { __iter , iterator } from "./iterator.js" ; import { isReduced } from "./reduced.js" ; export interface StreamShuffleOpts { /**
     * Sliding window size
     */ n : number ; defaultValue max ? : number ; defaultValue rnd ? : IRandom ; } /**
 * Transducer. Creates internal sliding window of `n` values and performs
 * `maxSwaps` random shuffle operations for each new value and yields values in
 * shuffled order. By default `maxSwaps` is the same as the chosen chunk size.
 * If given a  StreamShuffleOpts options object, further configurations
 * are possible.
 *
 *  example param n param maxSwaps export function streamShuffle < T > ( n , maxSwaps ? ) ; export function streamShuffle < T > ( opts ) ; export function streamShuffle < T > ( opts , src ) ; export function streamShuffle < T > ( n , maxSwaps , src ) ; export function streamShuffle < T > ( ... args ) { return ( __iter ( streamShuffle , args , iterator ) || ( ( [ init , complete , reduce ] ) => { let n ; let maxSwaps ; let rnd = SYSTEM ; const opts = < StreamShuffleOpts > args [ 0 ] ; if ( isPlainObject ( opts ) ) { n = opts . n ; maxSwaps = opts . max || n ; opts . rnd && ( rnd = opts . rnd ) ; } else { n = args [ 0 ] ; maxSwaps = args [ 1 ] || n ; } const buf = [ ] ; return < Reducer < any , T > > [ init , ( acc ) => { if ( buf . length ) { shuffle ( buf , Math . min ( maxSwaps , buf . length ) , rnd ) ; for ( let i = 0 , n = buf . length ; i < n && ! isReduced ( acc ) ; i ++ ) { acc = reduce ( acc , buf [ i ] ) ; } } buf . length = 0 ; acc = complete ( acc ) ; return acc ; } , ( acc , x ) => { buf . push ( x ) ; if ( buf . length === n ) { shuffle ( buf , Math . min ( maxSwaps , n ) , rnd ) ; acc = reduce ( acc , buf . shift ( ) ! ) ; } return acc ; } , ] ; } ) ) ; }