package Ġcommon Ċ Ċ import Ġorg . hyper skill . h st est . testcase . Check Result Ċ import Ġorg . hyper skill . h st est . testcase . TestCase ĊĊ Ċ // Ġ---- ĠDialog Cl ue Ġ---- Ċ Ċ /** ĠMay Ġbe Ġseveral Ġlines Ġor Ġjust Ġone . Ġ*/ Ċ interface ĠP hr ase Ġ{ ĊĠĠĠ Ġfun Ġto Phrase Lines (): ĠList < Phrase Line > Ċ } Ċ Ċ /** Ġlist Ġof Ġinput Ġand Ġoutput Ġlines , Ġcombined Ġtogether . Ġ*/ Ċ fun Ġcomposite Phrase ( block : Ġ() Ġ-> ĠList < Phrase >) Ġ= Ġobject Ġ: ĠP hr ase Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġto Phrase Lines () Ġ= Ġblock (). flatMap Ġ{ Ġit . to Phrase Lines () Ġ} Ċ } Ċ Ċ fun Ġcomposite Phrase ( var arg Ġphrases : ĠP hr ase ) Ġ= Ġobject Ġ: ĠP hr ase Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġto Phrase Lines () Ġ= Ġphrases . flatMap Ġ{ Ġit . to Phrase Lines () Ġ} Ċ } Ċ Ċ /** ĠEither Ġuser Ġ( input ) Ġor Ġoutput Ġphrase . ĠEach Ġphrase Ġshould Ġbe Ġa Ġline . Ġ*/ Ċ sealed Ġclass ĠP hr ase Line Ġ: ĠP hr ase Ġ{ ĊĠĠĠ Ġoverride Ġfun Ġto Phrase Lines () Ġ= ĠlistOf ( this ) Ċ } Ċ Ċ /** ĠSome Ġmutable Ġdata , Ġthat Ġis Ġpassed Ġacross Ġdialog Ġphrases . Ġ*/ Ċ class ĠContext Ġ{ ĊĠĠĠ Ġval Ġraw Data Ġ= Ġmutable Map Of < String , ĠAny >() Ċ } Ċ Ċ class ĠUser Line ( val Ġtext : ĠString , Ġval Ġupdate Context : ĠC tx Update Ġ= Ġ{}) Ġ: ĠP hr ase Line () Ġ{ Ċ Ċ } Ċ type alias ĠC tx Update Ġ= Ġ( ctx : ĠContext ) Ġ-> ĠUnit Ċ Ċ class ĠOutput Line ( val Ġchecker : Ġ( text : ĠString , Ġctx : ĠContext ) Ġ-> ĠCheck Result ) Ġ: ĠP hr ase Line () Ċ Ċ /** ĠThis Ġfunction Ġcreates Ġa Ġline Ġwith Ġuser Ġinput Ġ( our Ġtest Ġinput ). Ċ Ġ* Ċ Ġ* ĠUnfortunately Ġwe Ġcan 't Ġaccess Ġthe ĠContext , Ġwhen Ġwe Ġadding Ġuser Ġtext . Ċ Ġ* ĠThis Ġoccurs Ġbecause Ġof ĠH S Ġtest Ġframework Ġlimitations : Ċ Ġ* Ġwe Ġneed Ġto Ġpass Ġall Ġinputs Ġfirst , Ġand Ġthen Ġstart Ġchecking Ġoutputs . Ġ*/ Ċ fun Ġuser ( text : ĠString , Ġupdate Context : Ġ( ctx : ĠContext ) Ġ-> ĠUnit Ġ= Ġ{}) Ġ= ĠUser Line ( text , Ġupdate Context ) Ċ Ċ fun Ġany Line ( update Context : ĠC tx Update Ġ= Ġ{}) Ġ= ĠOutput Line Ġ{ Ġ_, Ġctx Ġ-> ĠCheck Result . correct (). also Ġ{ Ġupdate Context ( ctx ) Ġ} Ġ} Ċ Ċ fun Ġcontaining ( ĊĠĠĠĠĠĠĠ Ġvar arg Ġparts : ĠString , ĊĠĠĠĠĠĠĠ Ġignore Case : ĠBoolean Ġ= Ġtrue , ĊĠĠĠĠĠĠĠ Ġhint : ĠString ? Ġ= Ġnull , ĊĠĠĠĠĠĠĠ Ġupdate Context : ĠC tx Update Ġ= Ġ{} Ċ ) Ġ= ĠOutput Line Ġ{ Ġline , Ġcontext Ġ-> ĊĠĠĠ Ġfun Ġbuild Feedback (): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfeedback Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġfeedback . append (" Your Ġline \ n `$ line `\ n should Ġcontain Ġ${ parts . join ToString (" `, Ġ` ", Ġ"` ", Ġ"` ") }") ĊĠĠĠĠĠĠĠ Ġif Ġ( ignore Case ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeedback . append (" Ġ( ign oring Ġcase )") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfeedback . append (".") ĊĠĠĠĠĠĠĠ Ġif Ġ( hint Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfeedback . append ("\ n $ hint ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġfeedback . toString () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar ĠstartIndex Ġ= Ġ 0 ĊĠĠĠ Ġfor Ġ( part Ġin Ġparts ) Ġ{ ĊĠĠĠĠĠĠĠ ĠstartIndex Ġ= Ġline . indexOf ( part , ĠstartIndex , Ġignore Case ) ĊĠĠĠĠĠĠĠ Ġif Ġ( startIndex Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ Output Line ĠCheck Result . wrong ( build Feedback ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġupdate Context ( context ) Ġ// Ġeverything Ġis Ġcorrect , Ġupdate Ġcontext ĊĠĠĠ ĠCheck Result . correct (); Ċ } Ċ Ċ class ĠDialog Cl ue ( private Ġval Ġphrases : ĠList < Phrase Line >) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġinput Ph rases Ġ= Ġphrases . filter Ġ{ Ġit Ġis ĠUser Line Ġ}. map Ġ{ Ġit Ġas ĠUser Line Ġ} ĊĠĠĠ Ġprivate Ġval Ġoutput Ph rases Ġ= Ġphrases . filter Ġ{ Ġit Ġis ĠOutput Line Ġ}. map Ġ{ Ġit Ġas ĠOutput Line Ġ} ĊĊĠĠĠ Ġfun Ġgenerate Input () Ġ= Ġinput Ph rases ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString ("\ n ", Ġpostfix Ġ= Ġ"\ n ") Ġ{ Ġit . text Ġ} ĊĊĠĠĠ Ġfun Ġcheck Output ( output : ĠString ): ĠCheck Result Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġlines Ġ= Ġoutput . lines () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . isNotBlank () Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġwrong Output Size Feedback () Ġ= ĠCheck Result . wrong (" The Ġnumber Ġof Ġlines Ġin Ġyour Ġoutput Ġis Ġ${ lines . size }, Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" but Ġit Ġshould Ġbe Ġ${ output Ph rases . size }. Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Check , Ġthat Ġyou Ġoutput Ġyour Ġlines Ġwith Ġprintln , Ġnot Ġprint . ĠAnd Ġthere Ġare Ġno Ġextra Ġoutputs .") Ċ Ċ // Ġhere Ġwe Ġstore Ġsome Ġmutable Ġdata Ġfrom Ġphrase Ġto Ġphrase ĊĠĠĠĠĠĠĠ Ġval Ġcontext Ġ= ĠContext () ĊĊĠĠĠĠĠĠĠ Ġval Ġline Iter Ġ= Ġlines . list Iterator () ĊĠĠĠĠĠĠĠ Ġphrases . forEach Ġ{ Ġphrase Line Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( phrase Line ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠUser Line Ġ-> Ġphrase Line . update Context ( context ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠOutput Line Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! line Iter . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwrong Output Size Feedback () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġphrase Line . checker ( line Iter . next (), Ġcontext ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! result . is Correct ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠCheck Result . wrong ( result . feedback ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( line Iter . hasNext ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwrong Output Size Feedback () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠCheck Result . correct (); ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġdialog Test ( var arg Ġphrases : ĠP hr ase , Ġconsole Args : ĠArray < String > Ġ= Ġempty Array ()): ĠTestCase < Dialog Cl ue > Ġ{ ĊĠĠĠ Ġval Ġdialog Cl ue Ġ= ĠDialog Cl ue ( ph rases . flatMap Ġ{ Ġit . to Phrase Lines () Ġ}) ĊĠĠĠ Ġreturn ĠTestCase < Dialog Cl ue >() ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. setInput ( dialog Cl ue . generate Input ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. set Attach ( dialog Cl ue ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. add Arguments (* console Args ) Ċ } Ċ