package Ġcore . ems . service . exercise Ċ Ċ import Ġcom . fasterxml . jackson . annotation . JsonProperty Ċ import Ġcore . conf . security . Easy User Ċ import Ġcore . db . Course Exercise Ċ import Ġcore . ems . service . IDX _ STEP Ċ import Ġcore . ems . service . assert Teacher Or Admin Has Access To Course Ċ import Ġcore . ems . service . id To Long Or Invalid Req Ċ import Ġcore . ems . service . normal ise Course Ex Indices Ċ import Ġcore . exception . Invalid RequestException Ċ import Ġmu . Kotlin Logging Ċ import Ġorg . jetbrains . ex posed . sql . SortOrder Ċ import Ġorg . jetbrains . ex posed . sql . select Ċ import Ġorg . jetbrains . ex posed . sql . transactions . transaction Ċ import Ġorg . jetbrains . ex posed . sql . update Ċ import Ġorg . springframework . security . access . annotation . Sec ured Ċ import Ġorg . springframework . web . bind . annotation .* Ċ import Ġjavax . validation . Valid Ċ import Ġkotlin . math . abs Ċ import Ġkotlin . math . max Ċ import Ġkotlin . math . min Ċ Ċ private Ġval Ġlog Ġ= ĠKotlin Logging . logger Ġ{} Ċ Ċ @ RestController Ċ @ RequestMapping ("/ v 2 ") Ċ class ĠTe acher Re order Exercise Controller Ġ{ ĊĊĠĠĠ Ġdata Ġclass ĠReq (@ JsonProperty (" new _ index ", Ġrequired Ġ= Ġtrue ) Ġval Ġnew Index : ĠInt ) ĊĊĠĠĠ Ġ@ Sec ured (" ROLE _ TE AC HER ", Ġ" ROLE _ ADMIN ") ĊĠĠĠ Ġ@ PostMapping ("/ courses /{ course Id }/ exercises /{ course Exercise Id }/ reorder ") ĊĠĠĠ Ġfun Ġcontroller (@ PathVariable (" course Id ") Ġcourse Id Str : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ PathVariable (" course Exercise Id ") Ġcourse Exercise Id Str : ĠString , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ@ Valid Ġ@ RequestBody Ġdto : ĠReq , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcaller : ĠEasy User ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġlog . debug Ġ{ Ġ" Re order Ġcourse Ġexercise Ġ$ course Exercise Id Str Ġto Ġnew Ġindex Ġ${ dto . new Index } Ġ( caller : Ġ${ caller . id })" Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcourse Id Ġ= Ġcourse Id Str . id To Long Or Invalid Req () ĊĠĠĠĠĠĠĠ Ġval Ġcourse Ex Id Ġ= Ġcourse Exercise Id Str . id To Long Or Invalid Req () ĊĠĠĠĠĠĠĠ Ġval Ġnew Idx Ġ= Ġdto . new Index ĊĊĠĠĠĠĠĠĠ Ġassert Teacher Or Admin Has Access To Course ( caller , Ġcourse Id ) ĊĊĠĠĠĠĠĠĠ Ġset New Course Ex Index ( course Id , Ġcourse Ex Id , Ġnew Idx ) ĊĠĠĠ Ġ} Ċ } ĊĊ Ċ private Ġfun Ġset New Course Ex Index ( course Id : ĠLong , Ġcourse Ex Id : ĠLong , Ġraw New Idx : ĠInt ) Ġ{ ĊĠĠĠ Ġdata Ġclass ĠOrdered Ex ( val Ġid : ĠLong , Ġval Ġidx : ĠLong ) ĊĊĠĠĠ Ġval Ġordered Ex ercises Ġ= Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠCourse Exercise ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. slice ( Course Exercise . id , ĠCourse Exercise . order Idx ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. select Ġ{ ĠCourse Exercise . course Ġeq Ġcourse Id Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. orderBy ( Course Exercise . order Idx , ĠSort Order . ASC ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOrdered Ex ( it [ Course Exercise . id ]. value , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit [ Course Exercise . order Idx ]. to Long ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġold Idx Ġ= Ġordered Ex ercises . indexOf First Ġ{ Ġit . id Ġ== Ġcourse Ex Id Ġ} ĊĠĠĠ Ġif Ġ( old Idx Ġ== Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠInvalid RequestException (" No Ġexercise Ġwith Ġid Ġ$ course Ex Id Ġon Ġcourse Ġ$ course Id ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠMake Ġsure Ġthe Ġnew Ġindex Ġis Ġnot Ġout Ġof Ġbounds ĊĠĠĠ Ġval Ġnew Idx Ġ= Ġmin ( max ( raw New Idx , Ġ 0 ), Ġordered Ex ercises . size Ġ- Ġ 1 ) ĊĊĠĠĠ Ġif Ġ( new Idx Ġ== Ġold Idx ) Ġ{ ĊĠĠĠĠĠĠĠ Ġlog . warn Ġ{ Ġ" The Ġexercise Ġis Ġalready Ġon Ġposition Ġ$ new Idx " Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠPosition Between ( val Ġprev Idx : ĠLong , Ġval Ġnext Idx : ĠLong ) ĊĠĠĠ Ġval Ġnew Real Position Ġ= Ġwhen Ġ( new Idx ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠMove Ġto Ġfirst ĊĠĠĠĠĠĠĠĠ 0 Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Ġ= Ġordered Ex ercises [ new Idx ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPosition Between ( 0 , Ġnext ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// ĠMove Ġto Ġlast ĊĠĠĠĠĠĠĠ Ġordered Ex ercises . size Ġ- Ġ 1 Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprev Ġ= Ġordered Ex ercises [ new Idx ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPosition Between ( prev , Ġprev Ġ+ Ġ 2 Ġ* ĠIDX _ STEP ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( new Idx Ġ> Ġold Idx ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠMoving Ġup ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprev Ġ= Ġordered Ex ercises [ new Idx ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Ġ= Ġordered Ex ercises [ new Idx Ġ+ Ġ 1 ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPosition Between ( prev , Ġnext ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠMoving Ġdown ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġprev Ġ= Ġordered Ex ercises [ new Idx Ġ- Ġ 1 ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Ġ= Ġordered Ex ercises [ new Idx ]. idx ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPosition Between ( prev , Ġnext ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġlog . debug Ġ{ Ġ" New Ġposition Ġis Ġbetween Ġ${ new Real Position . prev Idx } Ġand Ġ${ new Real Position . next Idx }" Ġ} ĊĊĠĠĠ Ġif Ġ( abs ( new Real Position . next Idx Ġ- Ġnew Real Position . prev Idx ) Ġ< Ġ 2 Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Real Position . prev Idx Ġ+ Ġ 2 Ġ* ĠIDX _ STEP Ġ> ĠInt . MAX _ VALUE ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠNormal ise Ġand Ġtry Ġagain ĊĠĠĠĠĠĠĠ Ġlog . info Ġ{ Ġ" Bad Ġnew Ġposition , Ġnormal ising " Ġ} ĊĠĠĠĠĠĠĠ Ġnormal ise Course Ex Indices ( course Id ) ĊĠĠĠĠĠĠĠ Ġset New Course Ex Index ( course Id , Ġcourse Ex Id , Ġnew Idx ) ĊĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġnew Real Idx Ġ= Ġ(( new Real Position . next Idx Ġ+ Ġnew Real Position . prev Idx ) Ġ/ Ġ 2 ). toInt () ĊĠĠĠ Ġlog . debug Ġ{ Ġ" New Ġreal Ġindex : Ġ$ new Real Idx " Ġ} ĊĠĠĠ Ġupdate Course Ex Idx ( course Ex Id , Ġnew Real Idx ) Ċ } ĊĊ Ċ private Ġfun Ġupdate Course Ex Idx ( id : ĠLong , Ġnew Idx : ĠInt ) Ġ{ ĊĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠ ĠCourse Exercise . update ({ ĠCourse Exercise . id Ġeq Ġid Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit [ order Idx ] Ġ= Ġnew Idx ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ