Compare commits
	
		
			No commits in common. "2f7a247dbd9e4c54bccd95c10bef2becbbe3f7a9" and "79aff7af3bf52e909ff8c0e99a278bc58374fcd5" have entirely different histories. 
		
	
	
		
			2f7a247dbd
			...
			79aff7af3b
		
	
		
							
								
								
									
										2
									
								
								elm.json
								
								
								
								
							
							
						
						
									
										2
									
								
								elm.json
								
								
								
								
							| 
						 | 
					@ -11,7 +11,6 @@
 | 
				
			||||||
        "Internal.Config.Default",
 | 
					        "Internal.Config.Default",
 | 
				
			||||||
        "Internal.Config.Leaks",
 | 
					        "Internal.Config.Leaks",
 | 
				
			||||||
        "Internal.Config.Text",
 | 
					        "Internal.Config.Text",
 | 
				
			||||||
        "Internal.Filter.Timeline",
 | 
					 | 
				
			||||||
        "Internal.Tools.Decode",
 | 
					        "Internal.Tools.Decode",
 | 
				
			||||||
        "Internal.Tools.Encode",
 | 
					        "Internal.Tools.Encode",
 | 
				
			||||||
        "Internal.Tools.Hashdict",
 | 
					        "Internal.Tools.Hashdict",
 | 
				
			||||||
| 
						 | 
					@ -24,7 +23,6 @@
 | 
				
			||||||
        "Internal.Values.Event",
 | 
					        "Internal.Values.Event",
 | 
				
			||||||
        "Internal.Values.Settings",
 | 
					        "Internal.Values.Settings",
 | 
				
			||||||
        "Internal.Values.StateManager",
 | 
					        "Internal.Values.StateManager",
 | 
				
			||||||
        "Internal.Values.Timeline",
 | 
					 | 
				
			||||||
        "Internal.Values.Vault",
 | 
					        "Internal.Values.Vault",
 | 
				
			||||||
        "Types"
 | 
					        "Types"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,6 @@ module Internal.Filter.Timeline exposing
 | 
				
			||||||
    , match, run
 | 
					    , match, run
 | 
				
			||||||
    , and
 | 
					    , and
 | 
				
			||||||
    , subsetOf
 | 
					    , subsetOf
 | 
				
			||||||
    , encode, decoder
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
| 
						 | 
					@ -40,16 +39,10 @@ for interacting with the Matrix API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs subsetOf
 | 
					@docs subsetOf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
## JSON coders
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@docs encode, decoder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					 | 
				
			||||||
import Set exposing (Set)
 | 
					import Set exposing (Set)
 | 
				
			||||||
 | 
					import Task exposing (fail)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Placeholder Event type so the real Event doesn't need to be imported.
 | 
					{-| Placeholder Event type so the real Event doesn't need to be imported.
 | 
				
			||||||
| 
						 | 
					@ -160,45 +153,6 @@ and (Filter f1) (Filter f2) =
 | 
				
			||||||
                stdAnd
 | 
					                stdAnd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Decode a Filter from a JSON value.
 | 
					 | 
				
			||||||
-}
 | 
					 | 
				
			||||||
decoder : D.Decoder Filter
 | 
					 | 
				
			||||||
decoder =
 | 
					 | 
				
			||||||
    D.map4
 | 
					 | 
				
			||||||
        (\s sb t tb ->
 | 
					 | 
				
			||||||
            Filter
 | 
					 | 
				
			||||||
                { senders = s
 | 
					 | 
				
			||||||
                , sendersAllowOthers = sb
 | 
					 | 
				
			||||||
                , types = t
 | 
					 | 
				
			||||||
                , typesAllowOthers = tb
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        (D.string
 | 
					 | 
				
			||||||
            |> D.list
 | 
					 | 
				
			||||||
            |> D.map Set.fromList
 | 
					 | 
				
			||||||
            |> D.field "senders"
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        (D.field "sendersAllowOthers" D.bool)
 | 
					 | 
				
			||||||
        (D.string
 | 
					 | 
				
			||||||
            |> D.list
 | 
					 | 
				
			||||||
            |> D.map Set.fromList
 | 
					 | 
				
			||||||
            |> D.field "types"
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        (D.field "typesAllowOthers" D.bool)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{-| Encode a Filter into a JSON value.
 | 
					 | 
				
			||||||
-}
 | 
					 | 
				
			||||||
encode : Filter -> E.Value
 | 
					 | 
				
			||||||
encode (Filter f) =
 | 
					 | 
				
			||||||
    E.object
 | 
					 | 
				
			||||||
        [ ( "senders", E.set E.string f.senders )
 | 
					 | 
				
			||||||
        , ( "sendersAllowOthers", E.bool f.sendersAllowOthers )
 | 
					 | 
				
			||||||
        , ( "types", E.set E.string f.types )
 | 
					 | 
				
			||||||
        , ( "typesAllowOthers", E.bool f.typesAllowOthers )
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{-| Allow no events. This filter is likely quite useless in practice, but it is
 | 
					{-| Allow no events. This filter is likely quite useless in practice, but it is
 | 
				
			||||||
used in the test environment for sanity checks and comparisons.
 | 
					used in the test environment for sanity checks and comparisons.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,9 @@
 | 
				
			||||||
module Internal.Values.Timeline exposing
 | 
					module Internal.Values.Timeline exposing
 | 
				
			||||||
    ( Batch, Timeline
 | 
					    ( Batch, fromToken, fromSlice
 | 
				
			||||||
 | 
					    , Timeline
 | 
				
			||||||
    , empty, singleton
 | 
					    , empty, singleton
 | 
				
			||||||
    , mostRecentEvents
 | 
					    , mostRecentEvents
 | 
				
			||||||
    , addSync, insert
 | 
					    , addSync, insert
 | 
				
			||||||
    , encode, decoder
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-|
 | 
					{-|
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,12 @@ and maintain this room state.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Batch
 | 
					## Batch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs Batch, Timeline
 | 
					@docs Batch, fromToken, fromSlice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Timeline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@docs Timeline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Create
 | 
					## Create
 | 
				
			||||||
| 
						 | 
					@ -36,19 +41,12 @@ and maintain this room state.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@docs addSync, insert
 | 
					@docs addSync, insert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
## JSON coder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@docs encode, decoder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import FastDict as Dict exposing (Dict)
 | 
					import FastDict as Dict exposing (Dict)
 | 
				
			||||||
import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
					import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
				
			||||||
import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
 | 
					import Internal.Tools.Hashdict as Hashdict exposing (Hashdict)
 | 
				
			||||||
import Internal.Tools.Iddict as Iddict exposing (Iddict)
 | 
					import Internal.Tools.Iddict as Iddict exposing (Iddict)
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					 | 
				
			||||||
import Set exposing (Set)
 | 
					import Set exposing (Set)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -144,16 +142,8 @@ type alias TokenValue =
 | 
				
			||||||
batch to the front of the Timeline.
 | 
					batch to the front of the Timeline.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
addSync : Batch -> Timeline -> Timeline
 | 
					addSync : Batch -> Timeline -> Timeline
 | 
				
			||||||
addSync batch timeline =
 | 
					addSync _ timeline =
 | 
				
			||||||
    case insertBatch batch timeline of
 | 
					    timeline
 | 
				
			||||||
        ( Timeline tl, { start, end } ) ->
 | 
					 | 
				
			||||||
            let
 | 
					 | 
				
			||||||
                oldSync : ITokenPTR
 | 
					 | 
				
			||||||
                oldSync =
 | 
					 | 
				
			||||||
                    tl.mostRecentSync
 | 
					 | 
				
			||||||
            in
 | 
					 | 
				
			||||||
            Timeline { tl | mostRecentSync = end }
 | 
					 | 
				
			||||||
                |> connectITokenToIToken oldSync start
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Append a token at the end of a batch.
 | 
					{-| Append a token at the end of a batch.
 | 
				
			||||||
| 
						 | 
					@ -206,23 +196,19 @@ connectITokenToIToken : ITokenPTR -> ITokenPTR -> Timeline -> Timeline
 | 
				
			||||||
connectITokenToIToken pointer1 pointer2 (Timeline tl) =
 | 
					connectITokenToIToken pointer1 pointer2 (Timeline tl) =
 | 
				
			||||||
    case ( pointer1, pointer2 ) of
 | 
					    case ( pointer1, pointer2 ) of
 | 
				
			||||||
        ( ITokenPTR early, ITokenPTR late ) ->
 | 
					        ( ITokenPTR early, ITokenPTR late ) ->
 | 
				
			||||||
            if early == late then
 | 
					            Timeline
 | 
				
			||||||
                Timeline tl
 | 
					                { tl
 | 
				
			||||||
 | 
					                    | tokens =
 | 
				
			||||||
            else
 | 
					                        tl.tokens
 | 
				
			||||||
                Timeline
 | 
					                            |> Hashdict.map early
 | 
				
			||||||
                    { tl
 | 
					                                (\data ->
 | 
				
			||||||
                        | tokens =
 | 
					                                    { data | behind = Set.insert late data.behind }
 | 
				
			||||||
                            tl.tokens
 | 
					                                )
 | 
				
			||||||
                                |> Hashdict.map early
 | 
					                            |> Hashdict.map late
 | 
				
			||||||
                                    (\data ->
 | 
					                                (\data ->
 | 
				
			||||||
                                        { data | behind = Set.insert late data.behind }
 | 
					                                    { data | inFrontOf = Set.insert early data.inFrontOf }
 | 
				
			||||||
                                    )
 | 
					                                )
 | 
				
			||||||
                                |> Hashdict.map late
 | 
					                }
 | 
				
			||||||
                                    (\data ->
 | 
					 | 
				
			||||||
                                        { data | inFrontOf = Set.insert early data.inFrontOf }
 | 
					 | 
				
			||||||
                                    )
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ( _, _ ) ->
 | 
					        ( _, _ ) ->
 | 
				
			||||||
            Timeline tl
 | 
					            Timeline tl
 | 
				
			||||||
| 
						 | 
					@ -241,153 +227,6 @@ empty =
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Decode a Timeline from a JSON value.
 | 
					 | 
				
			||||||
-}
 | 
					 | 
				
			||||||
decoder : D.Decoder Timeline
 | 
					 | 
				
			||||||
decoder =
 | 
					 | 
				
			||||||
    D.map5
 | 
					 | 
				
			||||||
        (\batches events filled sync tokens ->
 | 
					 | 
				
			||||||
            Timeline
 | 
					 | 
				
			||||||
                { batches = batches
 | 
					 | 
				
			||||||
                , events = events
 | 
					 | 
				
			||||||
                , filledBatches = filled
 | 
					 | 
				
			||||||
                , mostRecentSync = sync
 | 
					 | 
				
			||||||
                , tokens = tokens
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        (D.field "batches" <| Iddict.decoder decoderIBatch)
 | 
					 | 
				
			||||||
        (D.map2 Tuple.pair
 | 
					 | 
				
			||||||
            (D.field "head" decoderIBatchPTR)
 | 
					 | 
				
			||||||
            (D.field "tail" <| D.list decoderIBatchPTR)
 | 
					 | 
				
			||||||
            |> D.keyValuePairs
 | 
					 | 
				
			||||||
            |> D.map Dict.fromList
 | 
					 | 
				
			||||||
            |> D.field "events"
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        (D.succeed 0)
 | 
					 | 
				
			||||||
        (D.field "mostRecentSync" decoderITokenPTR)
 | 
					 | 
				
			||||||
        (D.field "tokens" <| Hashdict.decoder .name decoderIToken)
 | 
					 | 
				
			||||||
        |> D.map recountFilledBatches
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderIBatch : D.Decoder IBatch
 | 
					 | 
				
			||||||
decoderIBatch =
 | 
					 | 
				
			||||||
    D.map4 IBatch
 | 
					 | 
				
			||||||
        (D.field "events" <| D.list D.string)
 | 
					 | 
				
			||||||
        (D.field "filter" Filter.decoder)
 | 
					 | 
				
			||||||
        (D.field "start" decoderITokenPTR)
 | 
					 | 
				
			||||||
        (D.field "end" decoderITokenPTR)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderIBatchPTR : D.Decoder IBatchPTR
 | 
					 | 
				
			||||||
decoderIBatchPTR =
 | 
					 | 
				
			||||||
    D.map IBatchPTR decoderIBatchPTRValue
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderIBatchPTRValue : D.Decoder IBatchPTRValue
 | 
					 | 
				
			||||||
decoderIBatchPTRValue =
 | 
					 | 
				
			||||||
    D.int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderIToken : D.Decoder IToken
 | 
					 | 
				
			||||||
decoderIToken =
 | 
					 | 
				
			||||||
    D.map5 IToken
 | 
					 | 
				
			||||||
        (D.field "name" decoderTokenValue)
 | 
					 | 
				
			||||||
        (D.field "starts" <| D.map Set.fromList <| D.list decoderIBatchPTRValue)
 | 
					 | 
				
			||||||
        (D.field "ends" <| D.map Set.fromList <| D.list decoderIBatchPTRValue)
 | 
					 | 
				
			||||||
        (D.field "inFrontOf" <| D.map Set.fromList <| D.list decoderITokenPTRValue)
 | 
					 | 
				
			||||||
        (D.field "behind" <| D.map Set.fromList <| D.list decoderITokenPTRValue)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderITokenPTR : D.Decoder ITokenPTR
 | 
					 | 
				
			||||||
decoderITokenPTR =
 | 
					 | 
				
			||||||
    D.oneOf
 | 
					 | 
				
			||||||
        [ D.map ITokenPTR decoderITokenPTRValue
 | 
					 | 
				
			||||||
        , D.null StartOfTimeline
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderITokenPTRValue : D.Decoder ITokenPTRValue
 | 
					 | 
				
			||||||
decoderITokenPTRValue =
 | 
					 | 
				
			||||||
    D.string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
decoderTokenValue : D.Decoder TokenValue
 | 
					 | 
				
			||||||
decoderTokenValue =
 | 
					 | 
				
			||||||
    D.string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{-| Encode a Timeline to a JSON value.
 | 
					 | 
				
			||||||
-}
 | 
					 | 
				
			||||||
encode : Timeline -> E.Value
 | 
					 | 
				
			||||||
encode (Timeline tl) =
 | 
					 | 
				
			||||||
    E.object
 | 
					 | 
				
			||||||
        [ ( "batches", Iddict.encode encodeIBatch tl.batches )
 | 
					 | 
				
			||||||
        , ( "events"
 | 
					 | 
				
			||||||
          , E.dict identity
 | 
					 | 
				
			||||||
                (\( head, tail ) ->
 | 
					 | 
				
			||||||
                    E.object
 | 
					 | 
				
			||||||
                        [ ( "head", encodeIBatchPTR head )
 | 
					 | 
				
			||||||
                        , ( "tail", E.list encodeIBatchPTR tail )
 | 
					 | 
				
			||||||
                        ]
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                (Dict.toCoreDict tl.events)
 | 
					 | 
				
			||||||
          )
 | 
					 | 
				
			||||||
        , ( "mostRecentSync", encodeITokenPTR tl.mostRecentSync )
 | 
					 | 
				
			||||||
        , ( "tokens", Hashdict.encode encodeIToken tl.tokens )
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeIBatch : IBatch -> E.Value
 | 
					 | 
				
			||||||
encodeIBatch batch =
 | 
					 | 
				
			||||||
    E.object
 | 
					 | 
				
			||||||
        [ ( "events", E.list E.string batch.events )
 | 
					 | 
				
			||||||
        , ( "filter", Filter.encode batch.filter )
 | 
					 | 
				
			||||||
        , ( "start", encodeITokenPTR batch.start )
 | 
					 | 
				
			||||||
        , ( "end", encodeITokenPTR batch.end )
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeIBatchPTR : IBatchPTR -> E.Value
 | 
					 | 
				
			||||||
encodeIBatchPTR (IBatchPTR value) =
 | 
					 | 
				
			||||||
    encodeIBatchPTRValue value
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeIBatchPTRValue : IBatchPTRValue -> E.Value
 | 
					 | 
				
			||||||
encodeIBatchPTRValue =
 | 
					 | 
				
			||||||
    E.int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeIToken : IToken -> E.Value
 | 
					 | 
				
			||||||
encodeIToken itoken =
 | 
					 | 
				
			||||||
    E.object
 | 
					 | 
				
			||||||
        [ ( "name", encodeTokenValue itoken.name )
 | 
					 | 
				
			||||||
        , ( "starts", E.set encodeIBatchPTRValue itoken.starts )
 | 
					 | 
				
			||||||
        , ( "ends", E.set encodeIBatchPTRValue itoken.ends )
 | 
					 | 
				
			||||||
        , ( "inFrontOf", E.set encodeITokenPTRValue itoken.inFrontOf )
 | 
					 | 
				
			||||||
        , ( "behind", E.set encodeITokenPTRValue itoken.behind )
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeITokenPTR : ITokenPTR -> E.Value
 | 
					 | 
				
			||||||
encodeITokenPTR token =
 | 
					 | 
				
			||||||
    case token of
 | 
					 | 
				
			||||||
        ITokenPTR value ->
 | 
					 | 
				
			||||||
            encodeITokenPTRValue value
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        StartOfTimeline ->
 | 
					 | 
				
			||||||
            E.null
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeITokenPTRValue : ITokenPTRValue -> E.Value
 | 
					 | 
				
			||||||
encodeITokenPTRValue =
 | 
					 | 
				
			||||||
    E.string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
encodeTokenValue : TokenValue -> E.Value
 | 
					 | 
				
			||||||
encodeTokenValue =
 | 
					 | 
				
			||||||
    E.string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
{-| Get an IBatch from the Timeline.
 | 
					{-| Get an IBatch from the Timeline.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
getIBatch : IBatchPTR -> Timeline -> Maybe IBatch
 | 
					getIBatch : IBatchPTR -> Timeline -> Maybe IBatch
 | 
				
			||||||
| 
						 | 
					@ -395,8 +234,6 @@ getIBatch (IBatchPTR ptr) (Timeline { batches }) =
 | 
				
			||||||
    Iddict.get ptr batches
 | 
					    Iddict.get ptr batches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Get an IToken from the Timeline.
 | 
					 | 
				
			||||||
-}
 | 
					 | 
				
			||||||
getITokenFromPTR : ITokenPTR -> Timeline -> Maybe IToken
 | 
					getITokenFromPTR : ITokenPTR -> Timeline -> Maybe IToken
 | 
				
			||||||
getITokenFromPTR pointer (Timeline { tokens }) =
 | 
					getITokenFromPTR pointer (Timeline { tokens }) =
 | 
				
			||||||
    case pointer of
 | 
					    case pointer of
 | 
				
			||||||
| 
						 | 
					@ -410,15 +247,13 @@ getITokenFromPTR pointer (Timeline { tokens }) =
 | 
				
			||||||
{-| Insert a batch anywhere else in the timeline.
 | 
					{-| Insert a batch anywhere else in the timeline.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
insert : Batch -> Timeline -> Timeline
 | 
					insert : Batch -> Timeline -> Timeline
 | 
				
			||||||
insert batch timeline =
 | 
					insert batch (Timeline tl) =
 | 
				
			||||||
    timeline
 | 
					    Timeline tl
 | 
				
			||||||
        |> insertBatch batch
 | 
					 | 
				
			||||||
        |> Tuple.first
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Insert a batch into the timeline.
 | 
					{-| Insert a batch into the timeline.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
insertBatch : Batch -> Timeline -> ( Timeline, { start : ITokenPTR, end : ITokenPTR } )
 | 
					insertBatch : Batch -> Timeline -> Timeline
 | 
				
			||||||
insertBatch batch timeline =
 | 
					insertBatch batch timeline =
 | 
				
			||||||
    case batch.start of
 | 
					    case batch.start of
 | 
				
			||||||
        Just start ->
 | 
					        Just start ->
 | 
				
			||||||
| 
						 | 
					@ -426,30 +261,26 @@ insertBatch batch timeline =
 | 
				
			||||||
                |> invokeIToken start
 | 
					                |> invokeIToken start
 | 
				
			||||||
                |> Tuple.mapSecond (invokeIToken batch.end)
 | 
					                |> Tuple.mapSecond (invokeIToken batch.end)
 | 
				
			||||||
                |> (\( startPTR, ( endPTR, newTimeline ) ) ->
 | 
					                |> (\( startPTR, ( endPTR, newTimeline ) ) ->
 | 
				
			||||||
                        ( insertIBatch
 | 
					                        insertIBatch
 | 
				
			||||||
                            { events = batch.events
 | 
					                            { events = batch.events
 | 
				
			||||||
                            , filter = batch.filter
 | 
					                            , filter = batch.filter
 | 
				
			||||||
                            , start = startPTR
 | 
					                            , start = startPTR
 | 
				
			||||||
                            , end = endPTR
 | 
					                            , end = endPTR
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            newTimeline
 | 
					                            newTimeline
 | 
				
			||||||
                        , { start = startPTR, end = endPTR }
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                   )
 | 
					                   )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Nothing ->
 | 
					        Nothing ->
 | 
				
			||||||
            timeline
 | 
					            timeline
 | 
				
			||||||
                |> invokeIToken batch.end
 | 
					                |> invokeIToken batch.end
 | 
				
			||||||
                |> (\( endPTR, newTimeline ) ->
 | 
					                |> (\( endPTR, newTimeline ) ->
 | 
				
			||||||
                        ( insertIBatch
 | 
					                        insertIBatch
 | 
				
			||||||
                            { events = batch.events
 | 
					                            { events = batch.events
 | 
				
			||||||
                            , filter = batch.filter
 | 
					                            , filter = batch.filter
 | 
				
			||||||
                            , start = StartOfTimeline
 | 
					                            , start = StartOfTimeline
 | 
				
			||||||
                            , end = endPTR
 | 
					                            , end = endPTR
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            newTimeline
 | 
					                            newTimeline
 | 
				
			||||||
                        , { start = StartOfTimeline, end = endPTR }
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                   )
 | 
					                   )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -459,31 +290,7 @@ insertIBatch : IBatch -> Timeline -> Timeline
 | 
				
			||||||
insertIBatch ibatch (Timeline tl) =
 | 
					insertIBatch ibatch (Timeline tl) =
 | 
				
			||||||
    case Iddict.insert ibatch tl.batches of
 | 
					    case Iddict.insert ibatch tl.batches of
 | 
				
			||||||
        ( batchPTR, newBatches ) ->
 | 
					        ( batchPTR, newBatches ) ->
 | 
				
			||||||
            { tl
 | 
					            { tl | batches = newBatches }
 | 
				
			||||||
                | batches = newBatches
 | 
					 | 
				
			||||||
                , events =
 | 
					 | 
				
			||||||
                    List.foldl
 | 
					 | 
				
			||||||
                        (\event dict ->
 | 
					 | 
				
			||||||
                            Dict.update event
 | 
					 | 
				
			||||||
                                (\value ->
 | 
					 | 
				
			||||||
                                    case value of
 | 
					 | 
				
			||||||
                                        Nothing ->
 | 
					 | 
				
			||||||
                                            Just ( IBatchPTR batchPTR, [] )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        Just ( head, tail ) ->
 | 
					 | 
				
			||||||
                                            Just ( IBatchPTR batchPTR, head :: tail )
 | 
					 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                                dict
 | 
					 | 
				
			||||||
                        )
 | 
					 | 
				
			||||||
                        tl.events
 | 
					 | 
				
			||||||
                        ibatch.events
 | 
					 | 
				
			||||||
                , filledBatches =
 | 
					 | 
				
			||||||
                    if List.isEmpty ibatch.events then
 | 
					 | 
				
			||||||
                        tl.filledBatches
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    else
 | 
					 | 
				
			||||||
                        tl.filledBatches + 1
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
                |> Timeline
 | 
					                |> Timeline
 | 
				
			||||||
                |> connectITokenToIBatch ibatch.start (IBatchPTR batchPTR)
 | 
					                |> connectITokenToIBatch ibatch.start (IBatchPTR batchPTR)
 | 
				
			||||||
                |> connectIBatchToIToken (IBatchPTR batchPTR) ibatch.end
 | 
					                |> connectIBatchToIToken (IBatchPTR batchPTR) ibatch.end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,6 @@ import Expect
 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
					import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
				
			||||||
import Internal.Values.Event as Event
 | 
					import Internal.Values.Event as Event
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					 | 
				
			||||||
import Set
 | 
					import Set
 | 
				
			||||||
import Test exposing (..)
 | 
					import Test exposing (..)
 | 
				
			||||||
import Test.Values.Event as TestEvent
 | 
					import Test.Values.Event as TestEvent
 | 
				
			||||||
| 
						 | 
					@ -420,15 +418,4 @@ suite =
 | 
				
			||||||
                        ()
 | 
					                        ()
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        , describe "JSON"
 | 
					 | 
				
			||||||
            [ fuzz fuzzer
 | 
					 | 
				
			||||||
                "encode -> decode is the same"
 | 
					 | 
				
			||||||
                (\filter ->
 | 
					 | 
				
			||||||
                    filter
 | 
					 | 
				
			||||||
                        |> Filter.encode
 | 
					 | 
				
			||||||
                        |> E.encode 0
 | 
					 | 
				
			||||||
                        |> D.decodeString Filter.decoder
 | 
					 | 
				
			||||||
                        |> Expect.equal (Ok filter)
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,99 +1,303 @@
 | 
				
			||||||
module Test.Values.Timeline exposing (..)
 | 
					module Test.Values.Timeline exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Expect
 | 
					 | 
				
			||||||
import Fuzz exposing (Fuzzer)
 | 
					import Fuzz exposing (Fuzzer)
 | 
				
			||||||
import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
					import Internal.Filter.Timeline as Filter exposing (Filter)
 | 
				
			||||||
import Internal.Values.Timeline as Timeline exposing (Batch, Timeline)
 | 
					import Internal.Values.Timeline as Timeline exposing (Batch, Timeline)
 | 
				
			||||||
import Json.Decode as D
 | 
					 | 
				
			||||||
import Json.Encode as E
 | 
					 | 
				
			||||||
import Test exposing (..)
 | 
					import Test exposing (..)
 | 
				
			||||||
import Test.Filter.Timeline as TestFilter
 | 
					import Test.Filter.Timeline as TestFilter
 | 
				
			||||||
 | 
					import Expect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fuzzer : Fuzzer Timeline
 | 
					fuzzer : Fuzzer Timeline
 | 
				
			||||||
fuzzer =
 | 
					fuzzer =
 | 
				
			||||||
    TestFilter.fuzzer
 | 
					    Fuzz.map2
 | 
				
			||||||
        |> Fuzz.andThen
 | 
					        (\makers filter ->
 | 
				
			||||||
            (\globalFilter ->
 | 
					            case makers of
 | 
				
			||||||
                Fuzz.oneOf
 | 
					                [] ->
 | 
				
			||||||
                    [ Fuzz.map2
 | 
					                    Timeline.empty
 | 
				
			||||||
                        (\start batches ->
 | 
					
 | 
				
			||||||
                            List.foldl
 | 
					                head :: tail ->
 | 
				
			||||||
                                (\b ( s, f ) ->
 | 
					                    List.foldl
 | 
				
			||||||
                                    ( b.end
 | 
					                        (\maker ( prevToken, timeline ) ->
 | 
				
			||||||
                                    , f >> Timeline.addSync { b | start = Just s, filter = globalFilter }
 | 
					                            case maker of
 | 
				
			||||||
 | 
					                                Sync start events end ->
 | 
				
			||||||
 | 
					                                    ( end
 | 
				
			||||||
 | 
					                                    , Timeline.addSync
 | 
				
			||||||
 | 
					                                        (Timeline.fromSlice
 | 
				
			||||||
 | 
					                                            { start =
 | 
				
			||||||
 | 
					                                                start
 | 
				
			||||||
 | 
					                                                    |> Maybe.withDefault prevToken
 | 
				
			||||||
 | 
					                                                    |> Maybe.Just
 | 
				
			||||||
 | 
					                                            , events = events
 | 
				
			||||||
 | 
					                                            , filter = filter
 | 
				
			||||||
 | 
					                                            , end = end
 | 
				
			||||||
 | 
					                                            }
 | 
				
			||||||
 | 
					                                        )
 | 
				
			||||||
 | 
					                                        timeline
 | 
				
			||||||
                                    )
 | 
					                                    )
 | 
				
			||||||
                                )
 | 
					
 | 
				
			||||||
                                ( start, identity )
 | 
					                                Get start events efilter end ->
 | 
				
			||||||
                                batches
 | 
					                                    ( prevToken
 | 
				
			||||||
                                |> Tuple.second
 | 
					                                    , Timeline.insert
 | 
				
			||||||
                        )
 | 
					                                        (Timeline.fromSlice
 | 
				
			||||||
                        Fuzz.string
 | 
					                                            { start = start
 | 
				
			||||||
                        (Fuzz.listOfLengthBetween 0 10 fuzzerBatch)
 | 
					                                            , events = events
 | 
				
			||||||
                    , Fuzz.map2
 | 
					                                            , filter = Filter.and filter efilter
 | 
				
			||||||
                        (\start batches ->
 | 
					                                            , end = end
 | 
				
			||||||
                            List.foldl
 | 
					                                            }
 | 
				
			||||||
                                (\b ( s, f ) ->
 | 
					                                        )
 | 
				
			||||||
                                    ( b.end
 | 
					                                        timeline
 | 
				
			||||||
                                    , f >> Timeline.insert { b | start = Just s, filter = Filter.and globalFilter b.filter }
 | 
					 | 
				
			||||||
                                    )
 | 
					                                    )
 | 
				
			||||||
                                )
 | 
					 | 
				
			||||||
                                ( start, identity )
 | 
					 | 
				
			||||||
                                batches
 | 
					 | 
				
			||||||
                                |> Tuple.second
 | 
					 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        Fuzz.string
 | 
					                        (case head of
 | 
				
			||||||
                        (Fuzz.listOfLengthBetween 0 4 fuzzerBatch)
 | 
					                            Sync start events end ->
 | 
				
			||||||
                    ]
 | 
					                                ( end
 | 
				
			||||||
                    |> Fuzz.listOfLengthBetween 0 10
 | 
					                                , Timeline.addSync
 | 
				
			||||||
                    |> Fuzz.map (List.foldl (<|) Timeline.empty)
 | 
					                                    (Timeline.fromSlice
 | 
				
			||||||
            )
 | 
					                                        { start = start
 | 
				
			||||||
 | 
					                                        , events = events
 | 
				
			||||||
 | 
					                                        , filter = filter
 | 
				
			||||||
 | 
					                                        , end = end
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    )
 | 
				
			||||||
 | 
					                                    Timeline.empty
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            Get start events efilter end ->
 | 
				
			||||||
 | 
					                                ( end
 | 
				
			||||||
 | 
					                                , Timeline.addSync
 | 
				
			||||||
 | 
					                                    (Timeline.fromSlice
 | 
				
			||||||
 | 
					                                        { start = start
 | 
				
			||||||
 | 
					                                        , events = events
 | 
				
			||||||
 | 
					                                        , filter = Filter.and filter efilter
 | 
				
			||||||
 | 
					                                        , end = end
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    )
 | 
				
			||||||
 | 
					                                    Timeline.empty
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        tail
 | 
				
			||||||
 | 
					                        |> Tuple.second
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        (Fuzz.list fuzzerMaker)
 | 
				
			||||||
 | 
					        TestFilter.fuzzer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fuzzerBatch : Fuzzer Batch
 | 
					fuzzerBatch : Fuzzer Batch
 | 
				
			||||||
fuzzerBatch =
 | 
					fuzzerBatch =
 | 
				
			||||||
    Fuzz.map4 Batch
 | 
					    Fuzz.oneOf
 | 
				
			||||||
 | 
					        [ Fuzz.map Timeline.fromToken Fuzz.string
 | 
				
			||||||
 | 
					        , Fuzz.map4
 | 
				
			||||||
 | 
					            (\start events filter end ->
 | 
				
			||||||
 | 
					                Timeline.fromSlice
 | 
				
			||||||
 | 
					                    { start = start
 | 
				
			||||||
 | 
					                    , events = events
 | 
				
			||||||
 | 
					                    , filter = filter
 | 
				
			||||||
 | 
					                    , end = end
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            (Fuzz.maybe Fuzz.string)
 | 
				
			||||||
 | 
					            (Fuzz.list Fuzz.string)
 | 
				
			||||||
 | 
					            TestFilter.fuzzer
 | 
				
			||||||
 | 
					            Fuzz.string
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type FuzzMaker
 | 
				
			||||||
 | 
					    = Sync (Maybe String) (List String) String
 | 
				
			||||||
 | 
					    | Get (Maybe String) (List String) Filter String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fuzzerMaker : Fuzzer FuzzMaker
 | 
				
			||||||
 | 
					fuzzerMaker =
 | 
				
			||||||
 | 
					    Fuzz.frequency
 | 
				
			||||||
 | 
					        [ ( 30, Fuzz.map (Sync Nothing []) Fuzz.string )
 | 
				
			||||||
 | 
					        , ( 10
 | 
				
			||||||
 | 
					          , Fuzz.map2 (Sync Nothing)
 | 
				
			||||||
 | 
					                (Fuzz.listOfLengthBetween 1 32 Fuzz.string)
 | 
				
			||||||
 | 
					                Fuzz.string
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        , ( 1
 | 
				
			||||||
 | 
					          , Fuzz.map3 (\start events end -> Sync (Just start) events end)
 | 
				
			||||||
 | 
					                Fuzz.string
 | 
				
			||||||
 | 
					                (Fuzz.listOfLengthBetween 1 32 Fuzz.string)
 | 
				
			||||||
 | 
					                Fuzz.string
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        , ( 1
 | 
				
			||||||
 | 
					          , Fuzz.map4 Get
 | 
				
			||||||
 | 
					                (Fuzz.maybe Fuzz.string)
 | 
				
			||||||
 | 
					                (Fuzz.list Fuzz.string)
 | 
				
			||||||
 | 
					                TestFilter.fuzzer
 | 
				
			||||||
 | 
					                Fuzz.string
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fuzzerForBatch : Fuzzer { start : String, events : List String, filter : Filter, end : String }
 | 
				
			||||||
 | 
					fuzzerForBatch =
 | 
				
			||||||
 | 
					    Fuzz.map4
 | 
				
			||||||
 | 
					        (\start events filter end ->
 | 
				
			||||||
 | 
					            { start = start, events = events, filter = filter, end = end }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        Fuzz.string
 | 
				
			||||||
        (Fuzz.list Fuzz.string)
 | 
					        (Fuzz.list Fuzz.string)
 | 
				
			||||||
        TestFilter.fuzzer
 | 
					        TestFilter.fuzzer
 | 
				
			||||||
        (Fuzz.maybe Fuzz.string)
 | 
					 | 
				
			||||||
        Fuzz.string
 | 
					        Fuzz.string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
isEqual : Timeline -> Timeline -> Expect.Expectation
 | 
					 | 
				
			||||||
isEqual t1 t2 =
 | 
					 | 
				
			||||||
    Expect.equal
 | 
					 | 
				
			||||||
        (E.encode 0 <| Timeline.encode t1)
 | 
					 | 
				
			||||||
        (E.encode 0 <| Timeline.encode t2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
suite : Test
 | 
					suite : Test
 | 
				
			||||||
suite =
 | 
					suite =
 | 
				
			||||||
    describe "Timeline"
 | 
					    describe "Timeline"
 | 
				
			||||||
        [ describe "empty"
 | 
					        [ describe "Most recent events"
 | 
				
			||||||
            [ fuzz fuzzerBatch
 | 
					            [ fuzz fuzzerForBatch "Singleton is most recent"
 | 
				
			||||||
                "singleton = empty + sync"
 | 
					 | 
				
			||||||
                (\batch ->
 | 
					                (\batch ->
 | 
				
			||||||
                    isEqual
 | 
					                    { start = Just batch.start
 | 
				
			||||||
                        (Timeline.singleton batch)
 | 
					                    , events = batch.events
 | 
				
			||||||
                        (Timeline.addSync batch Timeline.empty)
 | 
					                    , filter = batch.filter
 | 
				
			||||||
 | 
					                    , end = batch.end
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                        |> Timeline.fromSlice
 | 
				
			||||||
 | 
					                        |> Timeline.singleton
 | 
				
			||||||
 | 
					                        |> Timeline.mostRecentEvents batch.filter
 | 
				
			||||||
 | 
					                        |> Expect.equal batch.events
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ]
 | 
					            , fuzz2 fuzzerForBatch fuzzerForBatch "Double batch connects"
 | 
				
			||||||
        , describe "JSON"
 | 
					                (\batch1 batch2 ->
 | 
				
			||||||
            [ fuzz fuzzer
 | 
					                    [ { start = Just batch1.start
 | 
				
			||||||
                "encode -> decode is same"
 | 
					                      , events = batch1.events
 | 
				
			||||||
                (\timeline ->
 | 
					                      , filter = batch1.filter
 | 
				
			||||||
                    timeline
 | 
					                      , end = batch2.start
 | 
				
			||||||
                        |> Timeline.encode
 | 
					                      }
 | 
				
			||||||
                        |> E.encode 0
 | 
					                    , { start = Just batch2.start
 | 
				
			||||||
                        |> D.decodeString Timeline.decoder
 | 
					                      , events = batch2.events
 | 
				
			||||||
                        |> (\t ->
 | 
					                      , filter = batch2.filter
 | 
				
			||||||
                                case t of
 | 
					                      , end = batch2.end
 | 
				
			||||||
                                    Ok v ->
 | 
					                      }
 | 
				
			||||||
                                        isEqual v timeline
 | 
					                    ]
 | 
				
			||||||
 | 
					                        |> List.map Timeline.fromSlice
 | 
				
			||||||
                                    Err e ->
 | 
					                        |> List.foldl Timeline.addSync Timeline.empty
 | 
				
			||||||
                                        Expect.fail (D.errorToString e)
 | 
					                        |> Timeline.mostRecentEvents (Filter.and batch1.filter batch2.filter)
 | 
				
			||||||
 | 
					                        |> (\outcome ->
 | 
				
			||||||
 | 
					                                if batch2.start == batch2.end then
 | 
				
			||||||
 | 
					                                    Expect.equal [] outcome
 | 
				
			||||||
 | 
					                                else if batch1.start == batch2.start then
 | 
				
			||||||
 | 
					                                    Expect.equal batch2.events outcome
 | 
				
			||||||
 | 
					                                else
 | 
				
			||||||
 | 
					                                    Expect.equal
 | 
				
			||||||
 | 
					                                        (List.append batch1.events batch2.events)
 | 
				
			||||||
 | 
					                                        outcome
 | 
				
			||||||
                           )
 | 
					                           )
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					            , fuzz2 fuzzerForBatch fuzzerForBatch "Disconnected double batch does not connect"
 | 
				
			||||||
 | 
					                (\batch1 batch2 ->
 | 
				
			||||||
 | 
					                    [ { start = Just batch1.start
 | 
				
			||||||
 | 
					                      , events = batch1.events
 | 
				
			||||||
 | 
					                      , filter = batch1.filter
 | 
				
			||||||
 | 
					                      , end = batch1.start
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    , { start = Just batch2.start
 | 
				
			||||||
 | 
					                      , events = batch2.events
 | 
				
			||||||
 | 
					                      , filter = batch2.filter
 | 
				
			||||||
 | 
					                      , end = batch2.end
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					                        |> List.map Timeline.fromSlice
 | 
				
			||||||
 | 
					                        |> List.foldl Timeline.addSync Timeline.empty
 | 
				
			||||||
 | 
					                        |> Timeline.mostRecentEvents (Filter.and batch1.filter batch2.filter)
 | 
				
			||||||
 | 
					                        |> (\outcome ->
 | 
				
			||||||
 | 
					                                if batch2.start == batch2.end then
 | 
				
			||||||
 | 
					                                    Expect.equal [] outcome
 | 
				
			||||||
 | 
					                                else if batch1.start == batch2.start then
 | 
				
			||||||
 | 
					                                    Expect.equal batch2.events outcome
 | 
				
			||||||
 | 
					                                else if batch1.end == batch2.start then
 | 
				
			||||||
 | 
					                                    Expect.equal
 | 
				
			||||||
 | 
					                                        (List.append batch1.events batch2.events)
 | 
				
			||||||
 | 
					                                        outcome
 | 
				
			||||||
 | 
					                                else
 | 
				
			||||||
 | 
					                                    Expect.equal batch2.events outcome
 | 
				
			||||||
 | 
					                           )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            , fuzz
 | 
				
			||||||
 | 
					                ( Fuzz.pair Fuzz.int (Fuzz.list Fuzz.string)
 | 
				
			||||||
 | 
					                    |> (\f -> Fuzz.triple f f f)
 | 
				
			||||||
 | 
					                    |> (\f -> Fuzz.triple f f f)
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                "Connect 8 batches"
 | 
				
			||||||
 | 
					                (\(((i1, e1), (i2, e2), (i3, e3)), ((i4, e4), (i5, e5), (i6, e6)), ((i7, e7), (i8, e8), (_, e9))) ->
 | 
				
			||||||
 | 
					                            [ ( i1
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 1
 | 
				
			||||||
 | 
					                                , events = e1
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (1 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i2
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 2
 | 
				
			||||||
 | 
					                                , events = e2
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (2 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i3
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 3
 | 
				
			||||||
 | 
					                                , events = e3
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (3 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i4
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 4
 | 
				
			||||||
 | 
					                                , events = e4
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (4 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i5
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 5
 | 
				
			||||||
 | 
					                                , events = e5
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (5 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i6
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 6
 | 
				
			||||||
 | 
					                                , events = e6
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (6 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i7
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 7
 | 
				
			||||||
 | 
					                                , events = e7
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (7 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            , ( i8
 | 
				
			||||||
 | 
					                              , { start = Just <| String.fromInt 8
 | 
				
			||||||
 | 
					                                , events = e8
 | 
				
			||||||
 | 
					                                , filter = Filter.pass
 | 
				
			||||||
 | 
					                                , end = String.fromInt (8 + 1)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            ]
 | 
				
			||||||
 | 
					                            |> List.sortBy Tuple.first
 | 
				
			||||||
 | 
					                            |> List.map Tuple.second
 | 
				
			||||||
 | 
					                            |> List.map Timeline.fromSlice
 | 
				
			||||||
 | 
					                            |> List.foldl
 | 
				
			||||||
 | 
					                                Timeline.insert
 | 
				
			||||||
 | 
					                                (Timeline.singleton
 | 
				
			||||||
 | 
					                                    ( Timeline.fromSlice
 | 
				
			||||||
 | 
					                                        { start = Just <| String.fromInt 9
 | 
				
			||||||
 | 
					                                        , events = e9
 | 
				
			||||||
 | 
					                                        , filter = Filter.pass
 | 
				
			||||||
 | 
					                                        , end = String.fromInt (9 + 1)
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    )
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                            |> Timeline.mostRecentEvents Filter.pass
 | 
				
			||||||
 | 
					                            |> Expect.equal
 | 
				
			||||||
 | 
					                                ( e1 ++ e2 ++ e3 ++ e4 ++ e5 ++ e6 ++ e7 ++ e8 ++ e9 )
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue