/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 7 ĠVS CT Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* Ġ ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* Ġ ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġfr . vs ct . to ck . bot . admin . test Ċ Ċ import Ġcom . github . sal om on br ys . kode in . instance Ċ import Ġcom . google . common . cache . Cache Ċ import Ġcom . google . common . cache . Cache Builder Ċ import Ġfr . vs ct . to ck . bot . admin . bot . Bot ApplicationConfiguration DAO Ċ import Ġfr . vs ct . to ck . bot . admin . dialog . Dialog Report DAO Ċ import Ġfr . vs ct . to ck . bot . connector . rest . client . Connector RestClient Ċ import Ġfr . vs ct . to ck . bot . connector . rest . client . model . Client Connector Type Ċ import Ġfr . vs ct . to ck . bot . connector . rest . client . model . Client Message Ċ import Ġfr . vs ct . to ck . bot . connector . rest . client . model . Client Message Request Ċ import Ġfr . vs ct . to ck . bot . connector . rest . client . model . Client Sentence Ċ import Ġfr . vs ct . to ck . bot . engine . dialog . Dialog Ċ import Ġfr . vs ct . to ck . bot . engine . user . Player Id Ċ import Ġfr . vs ct . to ck . bot . engine . user . Player Type Ċ import Ġfr . vs ct . to ck . bot . engine . user . User Timeline DAO Ċ import Ġfr . vs ct . to ck . shared . Dice Ċ import Ġfr . vs ct . to ck . shared . error Ċ import Ġfr . vs ct . to ck . shared . injector Ċ import Ġfr . vs ct . to ck . shared . provide Ċ import Ġmu . Kotlin Logging Ċ import Ġorg . lit ote . km ongo . Id Ċ import Ġorg . lit ote . km ongo . to Id Ċ import Ġjava . time . Duration Ċ import Ġjava . time . Instant Ċ Ċ /** Ċ Ġ* Ċ Ġ*/ Ċ object ĠTest Plan Service Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= ĠKotlin Logging . logger Ġ{} ĊĊĠĠĠ Ġprivate Ġval Ġtest Plan DAO : ĠTest Plan DAO Ġby Ġinjector . instance () ĊĠĠĠ Ġprivate Ġval Ġuser Timeline DAO : ĠUser Timeline DAO Ġby Ġinjector . instance () ĊĠĠĠ Ġprivate Ġval Ġdialog DAO : ĠDialog Report DAO Ġby Ġinjector . instance () ĊĠĠĠ Ġprivate Ġval Ġbot Configuration DAO : ĠBot ApplicationConfiguration DAO Ġget () Ġ= Ġinjector . provide () ĊĊĠĠĠ Ġprivate Ġval Ġapplication Id Path Cache : ĠCache < String , ĠString > Ġ= ĊĠĠĠĠĠĠĠ ĠCache Builder . newBuilder (). expire After Access ( Duration . of Minutes ( 1 )). build () ĊĊĠĠĠ Ġfun Ġget Plan Execution s ( plan : ĠTest Plan ): ĠList < Test Plan Execution > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtest Plan DAO . get Plan Execution s ( plan ._ id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Test Plans By Namespace And N lp Model ( namespace : ĠString , Ġn lp Model : ĠString ): ĠList < Test Plan > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtest Plan DAO . get Plans (). filter Ġ{ Ġit . namespace Ġ== Ġnamespace Ġ&& Ġit . nlp Model Ġ== Ġn lp Model Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Test Plans By Namespace ( namespace : ĠString ): ĠList < Test Plan > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtest Plan DAO . get Plans (). filter Ġ{ Ġit . namespace Ġ== Ġnamespace Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Test Plans By Application ( application Id : ĠString ): ĠList < Test Plan > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtest Plan DAO . get Plans By Application Id ( application Id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġremove Dialog From Test Plan ( plan : ĠTest Plan , Ġdialog Id : ĠId < Dialog >) Ġ{ ĊĠĠĠĠĠĠĠ Ġsave Test Plan ( plan . copy ( dialogs Ġ= Ġplan . dialogs . filter Ġ{ Ġit . id Ġ!= Ġdialog Id Ġ})) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġadd Dialog To Test Plan ( plan : ĠTest Plan , Ġdialog Id : ĠId < Dialog >) Ġ{ ĊĠĠĠĠĠĠĠ Ġsave Test Plan ( plan . copy ( dialogs Ġ= Ġplan . dialogs Ġ+ ĠTest Dialog Report ( dialog DAO . get Dialog ( dialog Id ) !! ))) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġremove Test Plan ( plan : ĠTest Plan ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtest Plan DAO . remove Test Plan ( plan ._ id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave Test Plan ( plan : ĠTest Plan ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtest Plan DAO . save ( plan ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġget Test Plan ( plan Id : ĠId < Test Plan >): ĠTest Plan ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtest Plan DAO . get Plan ( plan Id ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġsave And Run Test Plan ( client : ĠConnector RestClient , Ġplan : ĠTest Plan ): ĠTest Plan Execution Ġ{ ĊĠĠĠĠĠĠĠ Ġtest Plan DAO . save ( plan ) ĊĠĠĠĠĠĠĠ Ġreturn Ġrun Test Plan ( client , Ġplan ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrun Test Plan ( client : ĠConnector RestClient , Ġplan : ĠTest Plan ): ĠTest Plan Execution Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= ĠInstant . now () ĊĠĠĠĠĠĠĠ Ġval Ġdialog s : ĠMutable List < Dialog Execution Report > Ġ= Ġmutable ListOf () ĊĠĠĠĠĠĠĠ Ġvar Ġnb Errors : ĠInt Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġplan . dialogs . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrun Dialog ( client , Ġplan , Ġit ). run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog s . add ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( error ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnb Errors ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġexec Ġ= ĠTest Plan Execution ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplan ._ id , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdialog s , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnb Errors , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġduration Ġ= ĠDuration . between ( start , ĠInstant . now ()) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġtest Plan DAO . save ( exec ) ĊĠĠĠĠĠĠĠ Ġreturn Ġexec ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġprivate Ġfun Ġrun Dialog ( ĊĠĠĠĠĠĠĠ Ġclient : ĠConnector RestClient , ĊĠĠĠĠĠĠĠ Ġtest Plan : ĠTest Plan , ĊĠĠĠĠĠĠĠ Ġdialog : ĠTest Dialog Report ĊĠĠĠ Ġ): ĠDialog Execution Report Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġplayer Id Ġ= ĠD ice . new Id () ĊĠĠĠĠĠĠĠ Ġval Ġbot Id Ġ= ĠD ice . new Id () ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġbot Messages : ĠMutable List < Client Message > Ġ= Ġmutable ListOf () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// send Ġfirst Ġaction Ġif Ġspecified ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( test Plan . start Action Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclient . talk ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠgetPath ( test Plan ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Plan . locale , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠClient Message Request ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplayer Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbot Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Plan . start Action !!. to Client Message (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Plan . target Connector Type . to Client Connector Type (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . actions . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . player Id . type Ġ== ĠPlayer Type . user ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= ĠClient Message Request ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġplayer Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbot Id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . findFirst Message (). to Client Message (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtest Plan . target Connector Type . to Client Connector Type (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ" ask : Ġ$ request " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġanswer Ġ= Ġclient . talk ( getPath ( test Plan ), Ġtest Plan . locale , Ġrequest ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( answer . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbody Ġ= Ġanswer . body () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ" answer : Ġ$ body " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbot Messages Ġ= Ġbody ?. messages ?. to Mutable List () Ġ?: Ġmutable ListOf () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error Ġ{ Ġanswer . error Body ()?. string () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDialog Execution Report ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . id , Ġtrue , ĠerrorMessage Ġ= Ġanswer . error Body ()?. toString () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġ" unknown Ġerror " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( bot Messages . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠDialog Execution Report ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠerrorMessage Ġ= Ġ"( no Ġanswer Ġbut Ġone Ġexpected )" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbot Message Ġ= Ġbot Messages . remove At ( 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! bot Message . deep Equals ( it )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠDialog Execution Report ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdialog . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbot Message . to Message () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠDialog Execution Report ( dialog . id ) ĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( e ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠDialog Execution Report ( dialog . id , Ġtrue , ĠerrorMessage Ġ= Ġe . message ) ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuser Timeline DAO . remove ( Player Id ( player Id , ĠPlayer Type . user )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠgetPath ( test Plan : ĠTest Plan ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġapplication Id Ġ= Ġtest Plan . application Id ĊĠĠĠĠĠĠĠ Ġreturn Ġapplication Id Path Cache . get ( application Id ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbot Configuration DAO . getConfiguration ById ( test Plan . bot ApplicationConfiguration Id )?. path Ġ?: Ġapplication Id ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClient Message . deep Equals ( action : ĠTest Action Report ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġaction . messages . any Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdeep Equals ( it . to Client Message ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠClient Message . deep Equals ( message : ĠClient Message ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( message Ġis ĠClient Sentence Ġ&& Ġthis Ġis ĠClient Sentence ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage . copy ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmessages Ġ= Ġmessage . messages . map Ġ{ Ġit . copy ( connector Type Ġ= ĠClient Connector Type . none ) Ġ}. to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ== Ġcopy ( messages Ġ= Ġmessages . map Ġ{ Ġit . copy ( connector Type Ġ= ĠClient Connector Type . none ) Ġ}. to Mutable List ()) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Ġ== Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ Ċ }