/* Ċ Ġ* ĠCopyright ĠÂ© Ġ 2 0 2 1 ĠPaul ĠAmb rose Ġ( p amb rose @ mac . com ) Ċ Ġ* Ċ Ġ* Ġ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 Ġcom . github . reading bat . common Ċ Ċ import Ġcom . github . p amb rose . common . util . isNotNull Ċ import Ġcom . github . p amb rose . common . util . isNull Ċ import Ġcom . github . p amb rose . common . util . maxLength Ċ import Ġcom . github . p amb rose . common . util . md 5 Of Ċ import Ġcom . github . p amb rose . common . util . new String Salt Ċ import Ġcom . github . p amb rose . common . util . random Id Ċ import Ġcom . github . reading bat . common . Class Code . Companion . DISABLED _ CLASS _ CODE Ċ import Ġcom . github . reading bat . common . Constants . UNKNOWN Ċ import Ġcom . github . reading bat . common . Endpoints . TH UM BS _ DOWN Ċ import Ġcom . github . reading bat . common . Endpoints . TH UM BS _ UP Ċ import Ġcom . github . reading bat . common . Key Constants . AUTH _ KEY Ċ import Ġcom . github . reading bat . common . Key Constants . CH ALL EN GE _ AN SW ERS _ KEY Ċ import Ġcom . github . reading bat . common . Key Constants . CORRECT _ AN SW ERS _ KEY Ċ import Ġcom . github . reading bat . common . Key Constants . key Of Ċ import Ġcom . github . reading bat . dsl . DataException Ċ import Ġcom . github . reading bat . dsl . Language Type . Companion . default Language Type Ċ import Ġcom . github . reading bat . dsl . Language Type . Companion . to Language Type Ċ import Ġcom . github . reading bat . dsl . challenge . Challenge Ċ import Ġcom . github . reading bat . dsl . is Db ms Enabled Ċ import Ġcom . github . reading bat . dsl . is Multi Server Enabled Ċ import Ġcom . github . reading bat . posts . Challenge History Ċ import Ġcom . github . reading bat . posts . Challenge Results Ċ import Ġcom . github . reading bat . posts . Dashboard History Ċ import Ġcom . github . reading bat . posts . Dashboard Info Ċ import Ġcom . github . reading bat . posts . Like Dis like Info Ċ import Ġcom . github . reading bat . server .* Ċ import Ġcom . github . reading bat . server . Email . Companion . EMPTY _ EMAIL Ċ import Ġcom . github . reading bat . server . Email . Companion . UNKNOWN _ EMAIL Ċ import Ġcom . github . reading bat . server . FullName . Companion . EMPTY _ FULL NAME Ċ import Ġcom . github . reading bat . server . FullName . Companion . UNKNOWN _ FULL NAME Ċ import Ġcom . github . reading bat . server . Reading B at Server . admin Users Ċ import Ġcom . github . reading bat . server . Reset Id . Companion . EMPTY _ RESET _ ID Ċ import Ġcom . github . reading bat . server . ws . Challenge Ws . class Target Name Ċ import Ġcom . github . reading bat . server . ws . Challenge Ws . multi Server Ws Write Channel Ċ import Ġcom . github . reading bat . server . ws . Challenge Ws . single Server Ws Channel Ċ import Ġcom . github . reading bat . server . ws . Pub Sub Commands Ws . Challenge Answer Data Ċ import Ġcom . github . reading bat . server . ws . Pub Sub Commands Ws . Pub Sub Topic . LIKE _ DIS LIKE Ċ import Ġcom . github . reading bat . server . ws . Pub Sub Commands Ws . Pub Sub Topic . USER _ AN SW ERS Ċ import Ġcom . p amb rose . common . ex posed . get Ċ import Ġcom . p amb rose . common . ex posed . upsert Ċ import Ġkotlinx . html . Entities . nbsp Ċ import Ġkotlinx . serialization . decode FromString Ċ import Ġkotlinx . serialization . encode ToString Ċ import Ġkotlinx . serialization . json . Json Ċ import Ġmu . K Logging Ċ import Ġorg . jetbrains . ex posed . sql . Count Ċ import Ġorg . jetbrains . ex posed . sql . Result Row Ċ import Ġorg . jetbrains . ex posed . sql . and Ċ import Ġorg . jetbrains . ex posed . sql . delete Where Ċ import Ġorg . jetbrains . ex posed . sql . insert Ċ import Ġorg . jetbrains . ex posed . sql . insert AndGet Id Ċ import Ġorg . jetbrains . ex posed . sql . or Ċ import Ġorg . jetbrains . ex posed . sql . select Ċ import Ġorg . jetbrains . ex posed . sql . transactions . transaction Ċ import Ġorg . jetbrains . ex posed . sql . update Ċ import Ġorg . joda . time . DateTime Ċ import Ġorg . joda . time . DateTime Zone . UTC Ċ import Ġjava . util . concurrent . Concurrent HashMap Ċ import Ġkotlin . contracts . contract Ċ import Ġkotlin . time . measure Time Ċ Ċ class ĠUser Ġ{ ĊĊĠ Ġprivate Ġconstructor ( ĊĠĠĠ ĠuserId : ĠString , ĊĠĠĠ Ġbrowser Session : ĠBrowser Session ?, ĊĠĠĠ Ġinit Fields : ĠBoolean ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġthis . userId Ġ= ĠuserId ĊĠĠĠ Ġthis . browser Session Ġ= Ġbrowser Session ĊĊĠĠĠ Ġif Ġ( init Fields Ġ&& Ġis Db ms Enabled ()) Ġ{ ĊĠĠĠĠĠ Ġmeasure Time Ġ{ ĊĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUsers Table . userId Ġeq Ġthis @ User . userId Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġassign Row Vals ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () Ġ?: Ġerror (" UserId Ġnot Ġfound : Ġ${ this @ User . userId }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ}. also Ġ{ Ġlogger . debug Ġ{ Ġ" Selected Ġuser Ġinfo Ġin Ġ$ it " Ġ} Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġconstructor ( ĊĠĠĠ ĠuserId : ĠString , ĊĠĠĠ Ġbrowser Session : ĠBrowser Session ?, ĊĠĠĠ Ġrow : ĠResult Row ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġthis . userId Ġ= ĠuserId ĊĠĠĠ Ġthis . browser Session Ġ= Ġbrowser Session ĊĠĠĠ Ġassign Row Vals ( row ) ĊĠ Ġ} ĊĊĠ Ġval ĠuserId : ĠString ĊĠ Ġval Ġbrowser Session : ĠBrowser Session ? ĊĠ Ġvar Ġuser Db ms Id : ĠLong Ġ= Ġ- 1 ĊĠ Ġvar Ġemail : ĠEmail Ġ= ĠEMPTY _ EMAIL ĊĠ Ġvar ĠfullName : ĠFull Name Ġ= ĠEMPTY _ FULL NAME ĊĠ Ġvar Ġen rolled Class Code : ĠClass Code Ġ= ĠDISABLE D _ CLASS _ CODE ĊĠ Ġvar Ġdefault Language Ġ= Ġdefault Language Type ĊĠ Ġprivate Ġvar Ġsalt Backing : ĠString Ġ= Ġ"" ĊĠ Ġprivate Ġvar Ġdigest Backing : ĠString Ġ= Ġ"" ĊĊĠ Ġval Ġsalt : ĠString ĊĠĠĠ Ġget () Ġ= Ġsalt Backing . if Blank Ġ{ Ġthrow ĠData Exception (" Missing Ġsalt Ġfield ") Ġ} ĊĠ Ġval Ġdigest : ĠString ĊĠĠĠ Ġget () Ġ= Ġdigest Backing . if Blank Ġ{ Ġthrow ĠData Exception (" Missing Ġdigest Ġfield ") Ġ} ĊĊĠ Ġprivate Ġfun Ġsession Db ms Id () Ġ= ĊĠĠĠ Ġbrowser Session ?. session Db ms Id () Ġ?: Ġerror (" Null Ġbrowser Ġsession ") ĊĊĠ Ġprivate Ġfun Ġassign Row Vals ( row : ĠResult Row ) Ġ{ ĊĠĠĠ Ġuser Db ms Id Ġ= Ġrow [ Users Table . id ]. value ĊĠĠĠ Ġemail Ġ= ĠEmail ( row [ Users Table . email ]) ĊĠĠĠ ĠfullName Ġ= ĠFull Name ( row [ Users Table . fullName ]) ĊĠĠĠ Ġen rolled Class Code Ġ= ĠClass Code ( row [ Users Table . en rolled Class Code ]) ĊĠĠĠ Ġdefault Language Ġ= Ġrow [ Users Table . default Language ]. to Language Type () Ġ?: Ġdefault Language Type ĊĠĠĠ Ġsalt Backing Ġ= Ġrow [ Users Table . salt ] ĊĠĠĠ Ġdigest Backing Ġ= Ġrow [ Users Table . digest ] ĊĠ Ġ} ĊĊĠ Ġfun Ġbrowser Sessions () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval ĠsessionId Ġ= ĠBrowser Sessions Table . sessionId ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠUser Sessions Table . user Ref ĊĠĠĠĠĠ Ġ( Browser Sessions Table Ġinner Join ĠUser Sessions Table ) ĊĠĠĠĠĠĠĠ Ġ. slice ( sessionId ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġuser Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġ// ĠLook Ġacross Ġall Ġpossible Ġbrowser Ġsessions ĊĠ Ġprivate Ġfun Ġinterested In Active Class Code ( class Code : ĠClass Code ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġid Ġ= ĠUser Sessions Table . id ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠUser Sessions Table . user Ref ĊĠĠĠĠĠ Ġval Ġactive Class Code Ġ= ĠUser Sessions Table . active Class Code ĊĠĠĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Count ( id )) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( user Ref Ġeq Ġuser Db ms Id ) Ġand Ġ( active Class Code Ġeq Ġclass Code . class Code ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠ Ġ. first () Ġ> Ġ 0 ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġcorrect Answers () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġall Correct Ġ= ĠUser Challenge Info Table . all Correct ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠUser Challenge Info Table . user Ref ĊĠĠĠĠĠ ĠUser Challenge Info Table ĊĠĠĠĠĠĠĠ Ġ. slice ( all Correct ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( user Ref Ġeq Ġuser Db ms Id ) Ġand Ġall Correct Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġ( it [ 0 ] Ġas ĠBoolean ). toString () Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġlike Dis like Emoji ( like Dis like : ĠInt ) Ġ= ĊĠĠĠ Ġwhen Ġ( like Dis like ) Ġ{ ĊĠĠĠĠĠĠ 1 Ġ-> ĠTH UM BS _ UP ĊĠĠĠĠĠĠ 2 Ġ-> ĠTH UM BS _ DOWN ĊĠĠĠĠĠ Ġelse Ġ-> Ġnb sp . text ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġlike Dis like Emoji ( challenge : ĠChallenge ) Ġ= Ġlike Dis like Emoji ( like Dis like ( challenge )) ĊĊĠ Ġfun Ġlike Dis like ( challenge : ĠChallenge ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġlike Dis like Ġ= ĠUser Challenge Info Table . like Dis like ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠUser Challenge Info Table . user Ref ĊĠĠĠĠĠ Ġval Ġmd 5 Ġ= ĠUser Challenge Info Table . md 5 ĊĠĠĠĠĠ ĠUser Challenge Info Table ĊĠĠĠĠĠĠĠ Ġ. slice ( like Dis like ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( user Ref Ġeq Ġuser Db ms Id ) Ġand Ġ( md 5 Ġeq Ġchallenge . md 5 ()) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ like Dis like ]. toInt () Ġ} ĊĠĠĠĠĠĠĠ Ġ. first OrNull () Ġ?: Ġ 0 ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġlike Dis likes () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠUser Challenge Info Table . user Ref ĊĠĠĠĠĠ Ġval Ġlike Dis like Ġ= ĠUser Challenge Info Table . like Dis like ĊĠĠĠĠĠ ĠUser Challenge Info Table . slice ( like Dis like ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( user Ref Ġeq Ġuser Db ms Id ) Ġand Ġ(( like Dis like Ġeq Ġ 1 ) Ġor Ġ( like Dis like Ġeq Ġ 2 )) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . toString () Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġclass Count () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠClasses Table . user Ref ĊĠĠĠĠĠ ĠClasses Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Count ( Classes Table . class Code )) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġuser Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠ Ġ. first (). also Ġ{ Ġlogger . info Ġ{ Ġ" class Count () Ġreturned Ġ$ it " Ġ} Ġ} ĊĠĠĠĠĠĠĠ Ġ. toInt () ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġadd Class Code ( class Code : ĠClass Code , Ġclass Desc : ĠString ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠClasses Table ĊĠĠĠĠĠĠĠ Ġ. insert Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠĠĠ Ġrow [ Classes Table . class Code ] Ġ= Ġclass Code . class Code ĊĠĠĠĠĠĠĠĠĠ Ġrow [ description ] Ġ= Ġclass Desc . maxLength ( 2 5 6 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġclass Codes () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġclass Code Ġ= ĠClasses Table . class Code ĊĠĠĠĠĠ Ġval Ġuser Ref Ġ= ĠClasses Table . user Ref ĊĠĠĠĠĠ ĠClasses Table ĊĠĠĠĠĠĠĠ Ġ. slice ( class Code ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġuser Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠClass Code ( it [ 0 ] Ġas ĠString ) Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun ĠisIn Db ms () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġval Ġid Ġ= ĠUsers Table . id ĊĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Count ( id )) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġid Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠ Ġ. first () Ġ> Ġ 0 ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġassign Digest ( new Digest : ĠString ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠPassword Re sets Table . delete Where Ġ{ ĠPassword Re sets Table . user Ref Ġeq Ġuser Db ms Id Ġ} ĊĊĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠ Ġ. update ({ ĠUsers Table . id Ġeq Ġuser Db ms Id Ġ}) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠĠĠ Ġrow [ digest ] Ġ= Ġnew Digest ĊĠĠĠĠĠĠĠĠĠ Ġdigest Backing Ġ= Ġnew Digest ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġassign En rolled Class Code ( class Code : ĠClass Code ) Ġ= ĊĠĠĠ ĠUsers Table ĊĠĠĠĠĠ Ġ. update ({ ĠUsers Table . id Ġeq Ġuser Db ms Id Ġ}) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠ Ġrow [ en rolled Class Code ] Ġ= Ġclass Code . class Code ĊĠĠĠĠĠĠĠ Ġthis @ User . en rolled Class Code Ġ= Ġclass Code ĊĠĠĠĠĠ Ġ} ĊĊĠ Ġfun Ġchallenges () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠUser Challenge Info Table ĊĠĠĠĠĠĠĠ Ġ. slice ( User Challenge Info Table . md 5 ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUser Challenge Info Table . user Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ}. also Ġ{ Ġlogger . info Ġ{ Ġ" challenges () Ġreturn Ġ${ it . size }" Ġ} Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġprivate Ġval Ġu ah Id Ġ= ĠUser Answer History Table . id ĊĠ Ġprivate Ġval Ġu ah Invocation Ġ= ĠUser Answer History Table . invocation ĊĠ Ġprivate Ġval Ġu ah User Ref Ġ= ĠUser Answer History Table . user Ref ĊĠ Ġprivate Ġval Ġu ah Md 5 Ġ= ĠUser Answer History Table . md 5 ĊĊĠ Ġfun Ġinv ocations () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠUser Answer History Table ĊĠĠĠĠĠĠĠ Ġ. slice ( u ah Md 5 ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġu ah User Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ}. also Ġ{ Ġlogger . info Ġ{ Ġ" inv ocations () Ġreturn Ġ${ it . size }" Ġ} Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġhistory Exists ( md 5 : ĠString , Ġinvocation : ĠInvocation ) Ġ= ĊĠĠĠ ĠUser Answer History Table ĊĠĠĠĠĠ Ġ. slice ( Count ( u ah Id )) ĊĠĠĠĠĠ Ġ. select Ġ{ Ġ( u ah User Ref Ġeq Ġuser Db ms Id ) Ġand Ġ( u ah Md 5 Ġeq Ġmd 5 ) Ġand Ġ( u ah Invocation Ġeq Ġinvocation . value ) Ġ} ĊĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠ Ġ. first () Ġ> Ġ 0 ĊĊĠ Ġfun Ġanswer History ( md 5 : ĠString , Ġinvocation : ĠInvocation ): ĠChallenge History Ġ{ ĊĠĠĠ Ġval Ġcorrect Ġ= ĠUser Answer History Table . correct ĊĠĠĠ Ġval Ġincorrect Attempts Ġ= ĠUser Answer History Table . incorrect Attempts ĊĠĠĠ Ġval Ġhistory Json Ġ= ĠUser Answer History Table . history Json ĊĊĠĠĠ Ġreturn ĠUser Answer History Table ĊĠĠĠĠĠ Ġ. slice ( u ah Invocation , Ġcorrect , Ġincorrect Attempts , Ġhistory Json ) ĊĠĠĠĠĠ Ġ. select Ġ{ Ġ( u ah User Ref Ġeq Ġuser Db ms Id ) Ġand Ġ( u ah Md 5 Ġeq Ġmd 5 ) Ġand Ġ( u ah Invocation Ġeq Ġinvocation . value ) Ġ} ĊĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġjson Ġ= Ġit [ history Json ] ĊĠĠĠĠĠĠĠ Ġval Ġhistory Ġ= ĠJson . decode FromString < List < String >>( json ). to Mutable List () ĊĠĠĠĠĠĠĠ ĠChallenge History ( Invocation ( it [ u ah Invocation ]), Ġit [ correct ], Ġit [ incorrect Attempts ]. toInt (), Ġhistory ) ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ. first OrNull () Ġ?: ĠChallenge History ( invocation ) ĊĠ Ġ} ĊĊĠ Ġfun Ġassign Active Class Code ( class Code : ĠClass Code , Ġreset Previous Class Code : ĠBoolean ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠĠĠ Ġ. upsert ( conflict Index Ġ= Ġuser Session Index ) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġrow [ session Ref ] Ġ= Ġsession Db ms Id () ĊĠĠĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠĠĠ Ġrow [ active Class Code ] Ġ= Ġclass Code . class Code ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( reset Previous Class Code ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ previous Teacher Class Code ] Ġ= Ġclass Code . class Code ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġreset Active Class Code () Ġ{ ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Reset ting Ġ$ fullName Ġ($ email ) Ġactive Ġclass Ġcode " Ġ} ĊĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠ Ġ. upsert ( conflict Index Ġ= Ġuser Session Index ) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠ Ġrow [ session Ref ] Ġ= Ġsession Db ms Id () ĊĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠ Ġrow [ active Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠ Ġrow [ previous Teacher Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġis En rolled ( class Code : ĠClass Code ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠEn rol le es Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Count ( En rol le es Table . id )) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠEn rol le es Table . user Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠ Ġ. first (). also Ġ{ Ġlogger . info Ġ{ Ġ" is En rolled () Ġreturned Ġ$ it Ġfor Ġ$ class Code " Ġ} Ġ} Ġ> Ġ 0 ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġcorrect Answers Key ( language Name : ĠLanguage Name , ĠgroupName : ĠGroup Name , Ġchallenge Name : ĠChallenge Name ) Ġ= ĊĠĠĠ Ġkey Of ( CORRECT _ AN SW ERS _ KEY , ĠAUTH _ KEY , ĠuserId , Ġmd 5 Of ( language Name , ĠgroupName , Ġchallenge Name )) ĊĊĠ Ġfun Ġchallenge Answers Key ( language Name : ĠLanguage Name , ĠgroupName : ĠGroup Name , Ġchallenge Name : ĠChallenge Name ) Ġ= ĊĠĠĠ Ġkey Of ( CH ALL EN GE _ AN SW ERS _ KEY , ĠAUTH _ KEY , ĠuserId , Ġmd 5 Of ( language Name , ĠgroupName , Ġchallenge Name )) ĊĊĠ Ġfun Ġis Not En rolled ( class Code : ĠClass Code ) Ġ= Ġ! is En rolled ( class Code ) ĊĊĠ Ġfun Ġen roll In Class ( class Code : ĠClass Code ) Ġ{ ĊĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠ Ġclass Code . isNot Enabled Ġ-> Ġthrow ĠData Exception (" Not Ġreport able Ġclass Ġcode ") ĊĠĠĠĠĠ Ġclass Code . isNot Valid () Ġ-> Ġthrow ĠData Exception (" Invalid Ġclass Ġcode : Ġ$ class Code ") ĊĠĠĠĠĠ Ġis En rolled ( class Code ) Ġ-> Ġthrow ĠData Exception (" Already Ġen rolled Ġin Ġclass Ġ$ class Code ") ĊĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠ Ġval Ġprevious Class Code Ġ= Ġen rolled Class Code ĊĠĠĠĠĠĠĠĠĠ Ġif Ġ( previous Class Code . isEnabled ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Class Code . remove En rol lee ( this @ User ) ĊĠĠĠĠĠĠĠĠĠ Ġassign En rolled Class Code ( class Code ) ĊĠĠĠĠĠĠĠĠĠ Ġclass Code . add En rol lee ( this @ User ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġwithdraw From Class ( class Code : ĠClass Code ) Ġ{ ĊĠĠĠ Ġif Ġ( class Code . isNot Enabled ) ĊĠĠĠĠĠ Ġthrow ĠData Exception (" Not Ġen rolled Ġin Ġa Ġclass ") ĊĊĠĠĠ Ġ// ĠThis Ġshould Ġalways Ġbe Ġtrue ĊĠĠĠ Ġval Ġen rolled Ġ= Ġclass Code . isValid () Ġ&& Ġis En rolled ( class Code ) ĊĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġassign En rolled Class Code ( DISABLED _ CLASS _ CODE ) ĊĠĠĠĠĠ Ġif Ġ( en rolled ) ĊĠĠĠĠĠĠĠ Ġclass Code . remove En rol lee ( this @ User ) ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġun enroll En rol le es Class Code ( class Code : ĠClass Code , Ġen rol le es : ĠList < User >) Ġ{ ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Deleting Ġ${ en rol le es . size } Ġen rol le es Ġfor Ġclass Ġcode Ġ$ class Code Ġfor Ġ$ fullName Ġ($ email )" Ġ} ĊĠĠĠ Ġ// ĠReset Ġevery Ġen rol lee 's Ġen rolled Ġclass Ġand Ġremove Ġfrom Ġclass ĊĠĠĠ Ġen rol le es ĊĠĠĠĠĠ Ġ. forEach Ġ{ Ġen rol lee Ġ-> ĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Assign ing Ġ${ en rol lee . email } Ġto Ġ$ DISABLED _ CLASS _ CODE " Ġ} ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. update ({ ĠUsers Table . id Ġeq Ġen rol lee . user Db ms Id Ġ}) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ en rolled Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġis Unique Class Desc ( class Desc : ĠString ) Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠClasses Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Count ( Classes Table . id )) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠClasses Table . description Ġeq Ġclass Desc Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠ Ġ. first () Ġ== Ġ 0 L ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġuser Password Reset Id () Ġ= ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠPassword Re sets Table ĊĠĠĠĠĠĠĠ Ġ. slice ( Password Re sets Table . reset Id ) ĊĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠPassword Re sets Table . user Ref Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ}. also Ġ{ Ġlogger . info Ġ{ Ġ" user Password Reset Id () Ġreturned Ġ$ it " Ġ} Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠReset Id ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. first OrNull () Ġ?: ĠEMPTY _ RESET _ ID ĊĠĠĠ Ġ} ĊĊĠ Ġfun Ġsave Password Reset Id ( email : ĠEmail , Ġnew Reset Id : ĠReset Id ) Ġ{ ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ ĠPassword Re sets Table ĊĠĠĠĠĠĠĠ Ġ. upsert ( conflict Index Ġ= Ġpassword Re sets Index ) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠĠĠ Ġrow [ reset Id ] Ġ= Ġnew Reset Id . value ĊĠĠĠĠĠĠĠĠĠ Ġrow [ Password Re sets Table . email ] Ġ= Ġemail . value ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġdelete User () Ġ{ ĊĠĠĠ Ġval Ġclass Codes Ġ= Ġclass Codes () ĊĠĠĠ Ġval Ġbrowser Sessions Ġ= Ġbrowser Sessions () ĊĠĠĠ Ġval Ġcorrect Answers Ġ= Ġcorrect Answers () ĊĠĠĠ Ġval Ġlike Dis likes Ġ= Ġlike Dis likes () ĊĠĠĠ Ġval Ġchallenges Ġ= Ġchallenges () ĊĠĠĠ Ġval Ġinv ocations Ġ= Ġinv ocations () ĊĊĠĠĠ Ġval Ġen rol lee Pairs Ġ= Ġclass Codes . map Ġ{ Ġit Ġto Ġit . fetch En rol le es () Ġ} ĊĊĠĠĠ Ġlogger . info Ġ{ Ġ" Deleting ĠUser : Ġ$ userId Ġ$ fullName " Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" User ĠEmail : Ġ$ email " Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" UserId : Ġ$ userId " Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" User ĠInfo Ġbrowser Ġsessions : Ġ${ browser Sessions . size }" Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Correct ĠAn swers : Ġ${ correct Answers . size }" Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Lik es / Dis likes : Ġ${ like Dis likes . size }" Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Ch allenges : Ġ${ challenges . size }" Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" Inv ocations : Ġ${ inv ocations . size }" Ġ} ĊĠĠĠ Ġlogger . info Ġ{ Ġ" User ĠClasses : Ġ$ class Codes " Ġ} ĊĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠ Ġ// ĠReset Ġen rol le es Ġin Ġall Ġclasses Ġcreated Ġby ĠUser ĊĠĠĠĠĠ Ġen rol lee Pairs . forEach Ġ{ Ġ( class Code , Ġen rol le es ) Ġ-> Ġun enroll En rol le es Class Code ( class Code , Ġen rol le es ) Ġ} ĊĊĠĠĠĠĠ Ġ// ĠClasses Ġdelete Ġon Ġcascade ĊĠĠĠĠĠ Ġ// ĠUser Answer History Ġdelete Ġon Ġcascade ĊĠĠĠĠĠ Ġ// ĠUser Challenge Info Ġdelete Ġon Ġcascade ĊĠĠĠĠĠ Ġ// ĠUser Sessions Ġdelete Ġon Ġcascade ĊĠĠĠĠĠ Ġ// ĠPassword Re sets Ġdelete Ġon Ġcascade ĊĠĠĠĠĠ ĠUsers Table . delete Where Ġ{ ĠUsers Table . id Ġeq Ġuser Db ms Id Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġsuspend Ġfun Ġpublish Answers ( ĊĠĠĠ Ġchallenge Md 5 : ĠString , ĊĠĠĠ Ġmax History Length : ĠInt , ĊĠĠĠ Ġcomplete : ĠBoolean , ĊĠĠĠ Ġnum Correct : ĠInt , ĊĠĠĠ Ġhistory : ĠChallenge History ĊĠ Ġ) Ġ{ ĊĠĠĠ Ġ// ĠPublish Ġto Ġchallenge Ġdashboard ĊĠĠĠ Ġlogger . debug Ġ{ Ġ" Publishing Ġuser Ġanswers Ġto Ġ$ en rolled Class Code Ġon Ġ$ challenge Md 5 Ġfor Ġ$ this " Ġ} ĊĠĠĠ Ġval Ġdashboard History Ġ= ĠDashboard History ( ĊĠĠĠĠĠ Ġhistory . invocation . value , ĊĠĠĠĠĠ Ġhistory . correct , ĊĠĠĠĠĠ Ġhistory . answers . as Re versed (). take ( max History Length ). join ToString ("< br >") ĊĠĠĠ Ġ) ĊĠĠĠ Ġval Ġtarget Name Ġ= Ġclass Target Name ( en rolled Class Code , Ġchallenge Md 5 ) ĊĠĠĠ Ġval Ġdashboard Info Ġ= ĠDashboard Info ( userId , Ġcomplete , Ġnum Correct , Ġdashboard History ) ĊĠĠĠ Ġ( if Ġ( is Multi Server Enabled ()) Ġmulti Server Ws Write Channel Ġelse Ġsingle Server Ws Channel ) ĊĠĠĠĠĠ Ġ. send ( Challenge Answer Data ( USER _ AN SW ERS , Ġtarget Name , Ġdashboard Info . toJson ())) ĊĠ Ġ} ĊĊĠ Ġsuspend Ġfun Ġpublish Like Dis like ( challenge Md 5 : ĠString , Ġlike Dis like : ĠInt ) Ġ{ ĊĠĠĠ Ġlogger . debug Ġ{ Ġ" Publishing Ġuser Ġlike Dis like Ġto Ġ$ en rolled Class Code Ġon Ġ$ challenge Md 5 Ġfor Ġ$ this " Ġ} ĊĠĠĠ Ġval Ġtarget Name Ġ= Ġclass Target Name ( en rolled Class Code , Ġchallenge Md 5 ) ĊĠĠĠ Ġval Ġemoji Ġ= Ġlike Dis like Emoji ( like Dis like ) ĊĠĠĠ Ġval Ġlike Dis like Info Ġ= ĠLike Dis like Info ( userId , Ġemoji ) ĊĠĠĠ Ġ( if Ġ( is Multi Server Enabled ()) Ġmulti Server Ws Write Channel Ġelse Ġsingle Server Ws Channel ) ĊĠĠĠĠĠ Ġ. send ( Challenge Answer Data ( LIKE _ DIS LIKE , Ġtarget Name , Ġlike Dis like Info . toJson ())) ĊĠ Ġ} ĊĊĠ Ġsuspend Ġfun Ġreset History ( func Info : ĠFunction Info , Ġchallenge : ĠChallenge , Ġmax History Length : ĠInt ) Ġ{ ĊĠĠĠ Ġlogger . debug Ġ{ Ġ" Reset ting Ġchallenge : Ġ$ challenge " Ġ} ĊĊĠĠĠ Ġfunc Info . inv ocations ĊĠĠĠĠĠ Ġ. map Ġ{ ĠChallenge Results ( invocation Ġ= Ġit ) Ġ} ĊĠĠĠĠĠ Ġ. forEach Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠ Ġ// ĠReset Ġthe Ġhistory Ġof Ġeach Ġanswer Ġon Ġa Ġper - invocation Ġbasis ĊĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ" Reset ting Ġinvocation : Ġ${ result . invocation }" Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġhistory Ġ= ĠChallenge History ( result . invocation ). apply Ġ{ Ġmark Un answer ed () Ġ} ĊĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠ ĠUser Answer History Table ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. upsert ( conflict Index Ġ= Ġuser Answer History Index ) Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ md 5 ] Ġ= Ġchallenge . md 5 ( result . invocation ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ updated ] Ġ= ĠDateTime . now ( UTC ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ invocation ] Ġ= Ġhistory . invocation . value ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ correct ] Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ incorrect Attempts ] Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ history Json ] Ġ= ĠJson . encode ToString ( emptyList < String >()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( should Publish ()) ĊĠĠĠĠĠĠĠĠĠ Ġfunc Info . challenge Md 5 . value . also Ġ{ Ġmd 5 Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpublish Answers ( md 5 , Ġmax History Length , Ġfalse , Ġ 0 , Ġhistory ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpublish Like Dis like ( md 5 , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġfun Ġshould Publish ( class Code : ĠClass Code Ġ= Ġen rolled Class Code ) Ġ= ĊĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠ Ġ! is Db ms Enabled () Ġ-> Ġfalse ĊĠĠĠĠĠ Ġclass Code . isEnabled Ġ-> Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠCheck Ġto Ġsee Ġif Ġthe Ġteacher Ġthat Ġowns Ġclass Ġhas Ġit Ġset Ġas Ġtheir Ġactive Ġclass Ġin Ġone Ġof Ġthe Ġsessions ĊĠĠĠĠĠĠĠ Ġval Ġteacher Id Ġ= Ġclass Code . fetch Class Teacher Id () ĊĠĠĠĠĠĠĠ Ġteacher Id . isNotEmpty () Ġ&& Ġteacher Id . to User (). inter ested In Active Class Code ( class Code ) ĊĠĠĠĠĠĠĠĠĠ Ġ. also Ġ{ Ġlogger . debug Ġ{ Ġ" Publishing Ġteacher Id : Ġ$ teacher Id Ġfor Ġ$ class Code " Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġelse Ġ-> Ġfalse ĊĠĠĠ Ġ} ĊĊĠ Ġoverride Ġfun ĠtoString () Ġ= Ġ" User ( userId ='$ userId ', Ġname ='$ fullName ')" ĊĊĠ Ġcompanion Ġobject Ġ: ĠK Logging () Ġ{ ĊĊĠĠĠ Ġ// ĠClass Ġcode Ġa Ġuser Ġis Ġen rolled Ġin . ĠWill Ġreport Ġanswers Ġto Ġwhen Ġin Ġstudent Ġmode ĊĠĠĠ Ġ// ĠThis Ġis Ġnot Ġbrowser - id Ġspecific ĊĠĠĠ Ġ// internal Ġconst Ġval ĠEN ROL LED _ CLASS _ CODE _ FIELD Ġ= Ġ" en rolled - class - code " ĊĊĠĠĠ Ġ// ĠClass Ġcode Ġyou Ġwill Ġobserve Ġupdates Ġon Ġwhen Ġin Ġteacher Ġmode ĊĠĠĠ Ġ// ĠThis Ġis Ġbrowser - id Ġspecific ĊĠĠĠ Ġ// private Ġconst Ġval ĠACT IVE _ CLASS _ CODE _ FIELD Ġ= Ġ" active - class - code " ĊĊĠĠĠ Ġ// ĠPrevious Ġteacher Ġclass Ġcode Ġthat Ġa Ġuser Ġhad ĊĠĠĠ Ġ// ĠThis Ġis Ġbrowser - id Ġspecific ĊĠĠĠ Ġ// private Ġconst Ġval ĠPRE V IOUS _ TE AC HER _ CLASS _ CODE _ FIELD Ġ= Ġ" previous - teacher - class - code " ĊĊĠĠĠ Ġval ĠuserId Cache Ġ= ĠConcurrent HashMap < String , ĠLong >() ĊĠĠĠ Ġval Ġemail Cache Ġ= ĠConcurrent HashMap < String , ĠEmail >() ĊĊĠĠĠ Ġfun ĠString . to User ( browser Session : ĠBrowser Session ? Ġ= Ġnull ) Ġ= ĠUser ( this , Ġbrowser Session , Ġtrue ) ĊĊĠĠĠ Ġfun ĠString . to User ( row : ĠResult Row ) Ġ= ĠUser ( this , Ġnull , Ġrow ) ĊĊĠĠĠ Ġfun Ġquery Active Te aching Class Code ( user : ĠUser ?) Ġ= ĊĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġuser . isNull () Ġ|| Ġ! is Db ms Enabled () Ġ-> ĠDISABLE D _ CLASS _ CODE ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. slice ( User Sessions Table . active Class Code ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( User Sessions Table . session Ref Ġeq Ġuser . session Db ms Id ()) Ġand Ġ( User Sessions Table . user Ref Ġeq Ġuser . user Db ms Id ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull ()?. let Ġ{ ĠClass Code ( it ) Ġ} Ġ?: ĠDISABLE D _ CLASS _ CODE ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġquery Previous Teacher Class Code ( user : ĠUser ?) Ġ= ĊĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠ Ġuser . isNull () Ġ|| Ġ! is Db ms Enabled () Ġ-> ĠDISABLE D _ CLASS _ CODE ĊĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. slice ( User Sessions Table . previous Teacher Class Code ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ Ġ( User Sessions Table . session Ref Ġeq Ġuser . session Db ms Id ()) Ġand Ġ( User Sessions Table . user Ref Ġeq Ġuser . user Db ms Id ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠString Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull ()?. let Ġ{ ĠClass Code ( it ) Ġ} Ġ?: ĠDISABLE D _ CLASS _ CODE ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġuser Exists ( userId : ĠString ) Ġ= ĊĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. slice ( Count ( Users Table . id )) ĊĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUsers Table . userId Ġeq ĠuserId Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ 0 ] Ġas ĠLong Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. first () Ġ> Ġ 0 ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġfetch User Db ms Id From Cache ( userId : ĠString ) Ġ= ĊĠĠĠĠĠ ĠuserId Cache . compute If Absent ( userId ) Ġ{ ĊĠĠĠĠĠĠĠ Ġquery User Db ms Id ( userId ). also Ġ{ Ġlogger . debug Ġ{ Ġ" Look ed Ġup Ġuser Db ms Id Ġfor Ġ$ userId : Ġ$ it " Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġfetch Email From Cache ( userId : ĠString ) Ġ= ĊĠĠĠĠĠ Ġemail Cache . compute If Absent ( userId ) Ġ{ ĊĠĠĠĠĠĠĠ Ġquery User Email ( userId ). also Ġ{ Ġlogger . debug Ġ{ Ġ" Look ed Ġup Ġemail Ġfor Ġ$ userId : Ġ$ it " Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġquery User Db ms Id ( userId : ĠString , Ġdefault If Missing : ĠLong Ġ= Ġ- 1 ) Ġ= ĊĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. slice ( Users Table . id ) ĊĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUsers Table . userId Ġeq ĠuserId Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit [ Users Table . id ]. value Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () Ġ?: Ġdefault If Missing ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġquery User Email ( userId : ĠString , Ġdefault If Missing : ĠEmail Ġ= ĠUNKNOWN _ EMAIL ) Ġ= ĊĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. slice ( Users Table . email ) ĊĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUsers Table . userId Ġeq ĠuserId Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠEmail ( it [ 0 ] Ġas ĠString ) Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () Ġ?: Ġdefault If Missing ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġcreate Unknown User ( userId : ĠString ) Ġ= ĊĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. insert AndGet Id Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ Users Table . userId ] Ġ= ĠuserId ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ fullName ] Ġ= ĠUNKNOWN _ FULL NAME . value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ email ] Ġ= Ġ"${ UNKNOWN _ EMAIL . value }-${ random Id ( 4 )}" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ en rolled Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ default Language ] Ġ= Ġdefault Language Type . language Name . value ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ salt ] Ġ= ĠUNKNOWN ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ digest ] Ġ= ĠUNKNOWN ĊĠĠĠĠĠĠĠĠĠ Ġ}. value . also Ġ{ Ġlogger . info Ġ{ Ġ" Created Ġunknown Ġuser Ġ$ it " Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġcreate User ( ĊĠĠĠĠĠ Ġname : ĠFull Name , ĊĠĠĠĠĠ Ġemail : ĠEmail , ĊĠĠĠĠĠ Ġpassword : ĠPassword , ĊĠĠĠĠĠ Ġbrowser Session : ĠBrowser Session ? ĊĠĠĠ Ġ): ĠUser Ġ= ĊĠĠĠĠĠ ĠUser ( random Id ( 2 5 ), Ġbrowser Session , Ġfalse ) ĊĠĠĠĠĠĠĠ Ġ. also Ġ{ Ġuser Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsalt Ġ= Ġnew String Salt () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdigest Ġ= Ġpassword . sha 2 5 6 ( salt ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġuser Db ms Id Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. insert AndGet Id Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ userId ] Ġ= Ġuser . userId ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ fullName ] Ġ= Ġname . value . maxLength ( 1 2 8 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ Users Table . email ] Ġ= Ġemail . value . maxLength ( 1 2 8 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ en rolled Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ default Language ] Ġ= Ġdefault Language Type . language Name . value ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ Users Table . salt ] Ġ= Ġsalt ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ Users Table . digest ] Ġ= Ġdigest ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. value ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbrowser Id Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbrowser Session ?. session Db ms Id () Ġ?: Ġerror (" Missing Ġbrowser Ġsession ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ ĠUser Sessions Table ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. insert Ġ{ Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ session Ref ] Ġ= Ġbrowser Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ user Ref ] Ġ= Ġuser Db ms Id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ active Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow [ previous Teacher Class Code ] Ġ= ĠDISABLE D _ CLASS _ CODE . class Code ĊĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Created Ġuser Ġ$ email Ġ${ user . userId }" Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Registered Email ( email : ĠEmail ) Ġ= Ġquery User By Email ( email ). isNotNull () ĊĊĠĠĠ Ġfun Ġis Not Registered Email ( email : ĠEmail ) Ġ= Ġ! is Registered Email ( email ) ĊĊĠĠĠ Ġfun Ġquery User By Email ( email : ĠEmail ): ĠUser ? Ġ= ĊĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠUsers Table ĊĠĠĠĠĠĠĠĠĠ Ġ. slice ( Users Table . userId ) ĊĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠUsers Table . email Ġeq Ġemail . value Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġ( it [ 0 ] Ġas ĠString ). to User () Ġ} ĊĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () ĊĠĠĠĠĠĠĠĠĠ Ġ. also Ġ{ Ġlogger . info Ġ{ Ġ" lookup User By Email () Ġreturned : Ġ${ it ?. email Ġ?: Ġ" Ġ${ email . value } Ġnot Ġfound "} " Ġ} Ġ} ĊĠĠĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ internal Ġfun ĠUser ?. isAdmin User () Ġ= ĠisValid User () Ġ&& Ġemail . value Ġin Ġadmin Users Ċ Ċ internal Ġfun ĠUser ?. isNot Admin User () Ġ= Ġ! isAdmin User () Ċ Ċ internal Ġfun ĠUser ?. isNot Valid User (): ĠBoolean Ġ{ ĊĠ Ġcontract Ġ{ ĊĠĠĠ Ġreturns ( false ) Ġimplies Ġ( this @ isNot Valid User Ġis ĠUser ) ĊĠ Ġ} ĊĠ Ġreturn Ġ! isValid User () Ċ } Ċ Ċ internal Ġfun ĠUser ?. isValid User (): ĠBoolean Ġ{ ĊĠ Ġcontract Ġ{ ĊĠĠĠ Ġreturns ( true ) Ġimplies Ġ( this @ isValid User Ġis ĠUser ) ĊĠ Ġ} ĊĠ Ġreturn Ġif Ġ( isNull ()) Ġfalse Ġelse ĠisIn Db ms () Ċ }