/* Ċ Ġ* ĠMIT ĠLicense Ċ Ġ* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 1 . ĠM ak sym ĠO li iny k . Ċ Ġ* Ċ Ġ* ĠPermission Ġis Ġhereby Ġgranted , Ġfree Ġof Ġcharge , Ġto Ġany Ġperson Ġobtaining Ġa Ġcopy Ċ Ġ* Ġof Ġthis Ġsoftware Ġand Ġassociated Ġdocumentation Ġfiles Ġ( the Ġ" Software "), Ġto Ġdeal Ċ Ġ* Ġin Ġthe ĠSoftware Ġwithout Ġrestriction , Ġincluding Ġwithout Ġlimitation Ġthe Ġrights Ċ Ġ* Ġto Ġuse , Ġcopy , Ġmodify , Ġmerge , Ġpublish , Ġdistribute , Ġsublicense , Ġand / or Ġsell Ċ Ġ* Ġcopies Ġof Ġthe ĠSoftware , Ġand Ġto Ġpermit Ġpersons Ġto Ġwhom Ġthe ĠSoftware Ġis Ċ Ġ* Ġfurnished Ġto Ġdo Ġso , Ġsubject Ġto Ġthe Ġfollowing Ġconditions : Ċ Ġ* Ċ Ġ* ĠThe Ġabove Ġcopyright Ġnotice Ġand Ġthis Ġpermission Ġnotice Ġshall Ġbe Ġincluded Ġin Ġall Ċ Ġ* Ġcopies Ġor Ġsubstantial Ġportions Ġof Ġthe ĠSoftware . Ċ Ġ* Ċ Ġ* ĠTHE ĠSOFTWARE ĠIS ĠPROVIDED Ġ" AS ĠIS ", ĠWITHOUT ĠWARRANTY ĠOF ĠANY ĠKIND , ĠEXPRESS ĠOR Ċ Ġ* ĠIMPLIED , ĠINCLUDING ĠBUT ĠNOT ĠLIMITED ĠTO ĠTHE ĠWARRANTIES ĠOF ĠMERCHANTABILITY , Ċ Ġ* ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE ĠAND ĠNONINFRINGEMENT . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE Ċ Ġ* ĠAUTHORS ĠOR ĠCOPYRIGHT ĠHOLDERS ĠBE ĠLIABLE ĠFOR ĠANY ĠCLAIM , ĠDAMAGES ĠOR ĠOTHER Ċ Ġ* ĠLIABILITY , ĠWHETHER ĠIN ĠAN ĠACTION ĠOF ĠCONTRACT , ĠTORT ĠOR ĠOTHERWISE , ĠARISING ĠFROM , Ċ Ġ* ĠOUT ĠOF ĠOR ĠIN ĠCONNECTION ĠWITH ĠTHE ĠSOFTWARE ĠOR ĠTHE ĠUSE ĠOR ĠOTHER ĠDEALINGS ĠIN ĠTHE Ċ Ġ* ĠSOFTWARE . Ċ Ġ*/ Ċ Ċ package Ġcom . oli yn ick . max . tea . core . component Ċ Ċ import Ġcom . oli yn ick . max . tea . core . Snapshot Ċ import Ġkotlinx . coroutines . flow .* Ċ Ċ /** Ċ Ġ* Ġ** Imp ure ** Ġfunction Ġthat Ġperforms Ġsome Ġactions Ġon Ġsnapshots Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ*/ Ċ public Ġtype alias ĠInter ceptor < M , ĠS , ĠC > Ġ= Ġsuspend Ġ( snapshot : ĠSnapshot < M , ĠS , ĠC >) Ġ-> ĠUnit Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġcommand Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġcommand Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġthat Ġconsists Ġfrom Ġa Ġsingle Ġcommand Ċ Ġ*/ Ċ public Ġin fix Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġcommand : ĠC , Ċ ): ĠUpdate With < S , ĠC > Ġ= Ġthis Ġto Ġset Of ( command ) Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġa Ġsingle Ġcommand Ġprovider Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġcommand Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġthat Ġconsists Ġfrom Ġa Ġsingle Ġcommand Ċ Ġ*/ Ċ public Ġinline Ġin fix Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġcommand : ĠS . () Ġ-> ĠC , Ċ ): ĠUpdate With < S , ĠC > Ġ= Ġthis Ġto Ġset Of ( run ( command )) Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġtwo Ġcommands Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommands Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġfirst Ġthe Ġfirst Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ param Ġsecond Ġthe Ġsecond Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġof Ġcommands Ċ Ġ*/ Ċ public Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġfirst : ĠC , ĊĠĠĠ Ġsecond : ĠC , Ċ ): ĠUpdate With < S , ĠC > Ġ= Ġthis Ġto Ġset Of ( first , Ġsecond ) Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġthree Ġcommands Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommands Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġfirst Ġthe Ġfirst Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ param Ġsecond Ġthe Ġsecond Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ param Ġthird Ġthe Ġthird Ġcommand Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġof Ġcommands Ċ Ġ*/ Ċ public Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġfirst : ĠC , ĊĠĠĠ Ġsecond : ĠC , ĊĠĠĠ Ġthird : ĠC , Ċ ): ĠUpdate With < S , ĠC > Ġ= ĊĠĠĠ Ġthis Ġto Ġset Of ( first , Ġsecond , Ġthird ) Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġmultiple Ġcommands Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommands Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġcommands Ġcommands Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġof Ġcommands Ċ Ġ*/ Ċ public Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġvar arg Ġcommands : ĠC , Ċ ): ĠUpdate With < S , ĠC > Ġ= Ġthis Ġcommand Ġset Of (* commands ) Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġset Ġof Ġcommands Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommands Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param Ġcommands Ġcommands Ġto Ġcombine Ġwith Ġstate Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġset Ġof Ġcommands Ċ Ġ*/ Ċ public Ġin fix Ġfun Ġ< S , ĠC > ĠS . command ( ĊĠĠĠ Ġcommands : ĠSet < C >, Ċ ): ĠUpdate With < S , ĠC > Ġ= Ġthis Ġto Ġcommands Ċ Ċ /** Ċ Ġ* ĠExtension Ġto Ġcombine Ġstate Ġwith Ġempty Ġset Ġof Ġcommands Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġstate Ġto Ġcombine Ġwith Ġcommands Ċ Ġ* Ġ@ param ĠS Ġstate Ġto Ġcombine Ġwith Ġcommand Ċ Ġ* Ġ@ return Ġ[ Update With ] Ġinstance Ġwith Ġgiven Ġstate Ġand Ġempty Ġset Ġof Ġcommands Ċ Ġ*/ Ċ public Ġfun Ġ< S > ĠS . no Command (): ĠUpdate With < S , ĠNothing > Ġ= Ġthis Ġto Ġempty Set () Ċ Ċ /** Ċ Ġ* ĠWrapper Ġto Ġperform Ġ** only ** Ġside Ġeffect Ġusing Ġcommand Ġas Ġreceiver . ĠThis Ġfunction Ġalways Ġreturns Ċ Ġ* Ġempty Ġset Ġof Ġmessages Ċ Ġ* Ġ@ param Ġaction Ġaction Ġto Ġperform Ġthat Ġproduces Ġno Ġmessages Ġthat Ġcan Ġbe Ġconsumed Ġby Ġa Ġcomponent Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ return Ġset Ġof Ġmessages Ġto Ġbe Ġconsumed Ġby Ġa Ġcomponent , Ġalways Ġempty Ċ Ġ*/ Ċ public Ġsuspend Ġinline Ġin fix Ġfun Ġ< C , ĠM > ĠC . side Effect ( ĊĠĠĠ Ġcross inline Ġaction : Ġsuspend ĠC . () Ġ-> ĠUnit , Ċ ): ĠSet < M > Ġ{ ĊĠĠĠ Ġaction () ĊĠĠĠ Ġreturn Ġempty Set () Ċ } Ċ Ċ /** Ċ Ġ* ĠWrapper Ġto Ġperform Ġside Ġeffect Ġcomput ations Ġand Ġpossibly Ġreturn Ġa Ġnew Ġmessage Ġto Ġbe Ġconsumed Ġby Ġ[ Updater ] Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcommand Ġto Ġbe Ġused Ġto Ġexecute Ġeffect Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param Ġaction Ġaction Ġto Ġperform Ġthat Ġmight Ġproduce Ġmessage Ġto Ġbe Ġconsumed Ġby Ġa Ġcomponent Ċ Ġ* Ġ@ return Ġset Ġof Ġmessages Ġto Ġbe Ġconsumed Ġa Ġcomponent Ċ Ġ*/ Ċ public Ġsuspend Ġinline Ġin fix Ġfun Ġ< C , ĠM > ĠC . effect ( ĊĠĠĠ Ġcross inline Ġaction : Ġsuspend ĠC . () Ġ-> ĠM ?, Ċ ): ĠSet < M > Ġ= Ġaction ( this @ effect )?. let (:: set Of ) Ġ?: Ġempty Set () Ċ Ċ /** Ċ Ġ* ĠTrans forms Ġcomponent Ġinto Ġflow Ġof Ġsnapshots Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. observe Snapshots (): ĠFlow < Snapshot < M , ĠS , ĠC >> Ġ= ĊĠĠĠ Ġthis ( empty Flow ()) Ċ Ċ /** Ċ Ġ* ĠTrans forms Ġcomponent Ġinto Ġflow Ġof Ġstates Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. observe States (): ĠFlow < S > Ġ= ĊĠĠĠ Ġobserve Snapshots (). map Ġ{ Ġsnapshot Ġ-> Ġsnapshot . currentState Ġ} Ċ Ċ /** Ċ Ġ* ĠTrans forms Ġcomponent Ġinto Ġfunction Ġthat Ġaccepts Ġmessages Ġand Ġreturns Ġflow Ġthat Ċ Ġ* Ġemits Ġstates Ġonly Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. states (): Ġ(( Flow < M >) Ġ-> ĠFlow < S >) Ġ= ĊĠĠĠ Ġ{ Ġinput Ġ-> Ġthis ( input ). map Ġ{ Ġsnapshot Ġ-> Ġsnapshot . currentState Ġ} Ġ} Ċ Ċ /** Ċ Ġ* ĠSup p lies Ġ[ messages ] Ġto Ġthe Ġcomponent . ĠNote Ġthat Ġmessages Ġwon 't Ġbe Ġconsumed Ċ Ġ* Ġuntil Ġterminal Ġoperator Ġis Ġcalled Ġon Ġthe Ġresulting Ġflow Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġoperator Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. invoke ( ĊĠĠĠ Ġvar arg Ġmessages : ĠM , Ċ ): ĠFlow < Snapshot < M , ĠS , ĠC >> Ġ= Ġthis ( flow Of (* messages )) Ċ Ċ /** Ċ Ġ* ĠSup p lies Ġ[ messages ] Ġto Ġthe Ġcomponent . ĠNote Ġthat Ġmessages Ġwon 't Ġbe Ġconsumed Ċ Ġ* Ġuntil Ġterminal Ġoperator Ġis Ġcalled Ġon Ġthe Ġresulting Ġflow Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġoperator Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. invoke ( ĊĠĠĠ Ġmessages : ĠIterable < M >, Ċ ): ĠFlow < Snapshot < M , ĠS , ĠC >> Ġ= Ġthis ( messages . as Flow ()) Ċ Ċ /** Ċ Ġ* ĠSup p lies Ġ[ message ] Ġto Ġthe Ġcomponent . ĠNote Ġthat Ġmessages Ġwon 't Ġbe Ġconsumed Ċ Ġ* Ġuntil Ġterminal Ġoperator Ġis Ġcalled Ġon Ġthe Ġresulting Ġflow Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġoperator Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. invoke ( ĊĠĠĠ Ġmessage : ĠM , Ċ ): ĠFlow < Snapshot < M , ĠS , ĠC >> Ġ= Ġthis ( flow Of ( message )) Ċ Ċ /** Ċ Ġ* ĠAtt aches Ġ[ interceptor ] Ġto Ġthe Ġcomponent Ċ Ġ* Ċ Ġ* Ġ@ receiver Ġcomponent Ġto Ġtransform Ċ Ġ* Ġ@ param ĠC Ġcommand Ċ Ġ* Ġ@ param ĠM Ġmessage Ċ Ġ* Ġ@ param ĠS Ġstate Ċ Ġ*/ Ċ public Ġin fix Ġfun Ġ< M , ĠS , ĠC > ĠComponent < M , ĠS , ĠC >. with ( ĊĠĠĠ Ġinterceptor : ĠInter ceptor < M , ĠS , ĠC >, Ċ ): ĠComponent < M , ĠS , ĠC > Ġ= ĊĠĠĠ Ġ{ Ġinput Ġ-> Ġthis ( input ). on Each ( interceptor ) Ġ} Ċ