package Ġkl al umi ere . re per to ire Ċ Ċ import Ġkotlin . math . min Ċ import Ġkotlin . text . StringBuilder Ċ Ċ data Ġclass ĠCh ord ( ĊĠĠĠ Ġval Ġposition : ĠInt , ĊĠĠĠ Ġval Ġvalue : ĠString Ċ ) Ġ{ ĊĠĠĠ Ġclass ĠBuilder ( val Ġposition : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠ Ġenum Ġclass ĠState Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠL Y RIC , ĠCH ORD ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconst Ġval ĠCREATE _ DE LIMITER Ġ= Ġ'[' ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconst Ġval ĠCH ORD _ STATE _ DE LIMITER _ 0 Ġ= Ġ' ]' ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconst Ġval ĠCH ORD _ STATE _ DE LIMITER _ 1 Ġ= Ġ'(' ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconst Ġval ĠCOMP LETED _ DE LIMITER Ġ= Ġ')' ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconst Ġval ĠESC APE _ CHAR Ġ= Ġ'\\ ' ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠRES ER VED _ CHARS Ġ= ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCREATE _ DE LIMITER , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCH ORD _ STATE _ DE LIMITER _ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCH ORD _ STATE _ DE LIMITER _ 1 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCOMP LETED _ DE LIMITER , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠESC APE _ CHAR ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġvar Ġstate Ġ= ĠState . LY RIC ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprivate Ġset ĊĊĠĠĠĠĠĠĠ Ġfun Ġappend ( char : ĠChar ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( state Ġ== ĠState . CH ORD ) Ġbuilder . append ( char ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġbuild (): ĠCh ord Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠCh ord ( position , Ġbuilder . toString ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġtransition ( look behind : ĠChar , Ġchar : ĠChar ): ĠBuilder Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( look behind Ġ== ĠCH ORD _ STATE _ DE LIMITER _ 0 Ġ&& Ġchar Ġ== ĠCH ORD _ STATE _ DE LIMITER _ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstate Ġ= ĠState . CH ORD ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġbuilder Ġ= ĠStringBuilder () ĊĠĠĠ Ġ} Ċ } Ċ Ċ data Ġclass ĠVer se ( ĊĠĠĠĠĠĠĠ Ġval Ġl yr ics : ĠString , ĊĠĠĠĠĠĠĠ Ġval Ġch ords : ĠList < Ch ord > Ċ ) Ġ{ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġparse ( line : ĠString ): ĠVer se Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠVer se Parser (). parse ( line ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġto Text ( ch ords : ĠList < Ch ord >, Ġl yr ics Length : ĠInt ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= Ġ ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġadd Spaces Ġ= Ġ{ Ġcount : ĠInt Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( count Ġ> Ġ 0 ) Ġbuilder . append (" Ġ". repeat ( count )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor ( ch ord Ġin Ġch ords ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Spaces ( ch ord . position Ġ- Ġbuilder . length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( ch ord . value ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( ch ord Ġ!== Ġch ords . last ()) Ġadd Spaces ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Spaces ( lyr ics Length Ġ- Ġbuilder . length ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġbuilder . toString () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġfun Ġsafe Substring ( string : ĠString , Ġbegin : ĠInt , Ġlength : ĠInt ): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( begin Ġ>= Ġstring . length ) Ġreturn Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġstring . substring ( begin , Ġmin ( string . length , Ġbegin Ġ+ Ġlength )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrender Text ( screen Width In Char : ĠInt , Ġch ord Line Decorator : Ġ( String ) Ġ-> ĠString Ġ= Ġ{ Ġx Ġ-> Ġx Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnewline : ĠString Ġ= Ġ"\ n "): ĠString ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġif ( lyr ics . isEmpty ()) Ġreturn Ġnewline . repeat ( 2 ) ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= Ġ ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġval Ġch ords As Text Ġ= Ġto Text ( ch ords , Ġl yr ics . length ) ĊĠĠĠĠĠĠĠ Ġfor ( i Ġin Ġl yr ics . indices Ġstep Ġscreen Width In Char ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( ch ord Line Decorator ( safe Substring ( ch ords As Text , Ġi , Ġscreen Width In Char ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( newline ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( safe Substring ( lyr ics , Ġi , Ġscreen Width In Char )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( newline ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġbuilder . toString () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrender Html Text ( screen Width In Char : ĠInt , Ġch ord Format : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġch ord Line Decorator Ġ= Ġ{ Ġline : ĠString Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġch ord Buffer Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor ( char Ġin Ġline ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen ( char ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ' Ġ' Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( ch ord Buffer . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . append ( ch ord Format . format ( ch ord Buffer )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch ord Buffer Ġ= ĠStringBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . append ("& nbsp ; ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġch ord Buffer . append ( char ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif ( ch ord Buffer . isNotEmpty ()) Ġresult . append ( ch ord Format . format ( ch ord Buffer )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult . toString () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġrender Text ( screen Width In Char , Ġch ord Line Decorator = ch ord Line Decorator , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnewline ="< br >\ n ") ĊĠĠĠ Ġ} ĊĊĊĠĠĠ Ġprivate Ġclass ĠVer se Parser Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġparse ( line : ĠString ): ĠVer se Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor ( char Ġin Ġline ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( is Reserved ( char )) Ġparse Reserved ( char ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġparse Regular ( char ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlook behind Ġ= Ġchar ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠVer se ( lyr ics Builder . toString (), Ġch ords ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġis Reserved ( char : ĠChar ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġchar Ġin ĠCh ord . Builder . RESERVED _ CHARS Ġ&& Ġlook behind Ġ!= ĠCh ord . Builder . ESCAPE _ CHAR ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġparse Reserved ( char : ĠChar ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( char ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCh ord . Builder . CREATE _ DE LIMITER Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch ord Builder Ġ= ĠCh ord . Builder ( lyr ics Builder . length ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCh ord . Builder . COMPLETED _ DE LIMITER Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch ord Builder ?. build (). also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif ( it Ġ!= Ġnull ) Ġch ords . add ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch ord Builder Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġch ord Builder ?. transition ( look behind , Ġchar ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġparse Regular ( char : ĠChar ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( ch ord Builder ?. state ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠCh ord . Builder . State . CH ORD Ġ-> Ġ{ Ġch ord Builder ?. append ( char ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ Ġl yr ics Builder . append ( char ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġch ord Builder : ĠCh ord . Builder ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġprivate Ġvar Ġlook behind Ġ= Ġ' x ' ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġch ords Ġ= Ġmutable ListOf < Ch ord >() ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġl yr ics Builder Ġ= ĠStringBuilder () ĊĠĠĠ Ġ} Ċ } Ċ Ċ data Ġclass ĠSong Content ( val Ġver ses : ĠList < Ver se >) Ġ{ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġfun Ġparse ( song Content : ĠString ): ĠSong Content Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠSong Content ( song Content . lines (). map Ġ{ ĠVer se . parse ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrender Text ( screen Width In Char : ĠInt , Ġch ord Line Decorator : Ġ( String ) Ġ-> ĠString Ġ= Ġ{ Ġx Ġ-> Ġx Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnewline : ĠString Ġ= Ġ"\ n "): ĠString ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= Ġ ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġver ses . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . append ( it . render Text ( screen Width In Char , Ġch ord Line Decorator = ch ord Line Decorator , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnewline = newline )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġbuilder . toString () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġrender Html Text ( screen Width In Char : ĠInt , Ġch ord Format : ĠString ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġbuilder Ġ= Ġ ĠStringBuilder () ĊĠĠĠĠĠĠĠ Ġver ses . forEach Ġ{ Ġbuilder . append ( it . render Html Text ( screen Width In Char , Ġch ord Format )) Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġbuilder . toString () ĊĠĠĠ Ġ} Ċ } Ċ