namespace Models { export const enum UserFlags { Guest = ( 1 << 00 ) , Connected = ( 1 << 01 ) , Deleted = ( 1 << 02 ) , Idle = ( 1 << 03 ) , HasAvatar = ( 1 << 04 ) , Robot = ( 1 << 05 ) , TournamentWinner = ( 1 << 06 ) , TournamentRunnerUp = ( 1 << 07 ) , Playing = ( 1 << 08 ) , PlayingTournament = ( 1 << 09 ) , KGSPlus = ( 1 << 10 ) , KGSMeijin = ( 1 << 11 ) , Ranked = ( 1 << 12 ) , Biased = ( 1 << 13 ) } export const enum UserRankFormat { Default , Long , Numeric } ; export class User { public name : string ; public rank : string ; private _flags : string ; public flags : UserFlags ; constructor ( user ) { this . name = user . name ; this . rank = user . rank ; this . mergeFlags ( user . flags ) ; } public mergeUser ( user ) { let touch = false ; if ( this . name != user . name ) { this . name = user . name ; touch = true ; } if ( this . rank != user . rank ) { this . rank = user . rank ; touch = true ; } return ( ( touch ) || ( this . mergeFlags ( user . flags ) ) ) ; } private mergeFlags ( flags ) { if ( this . _flags != flags ) { let bits = 0 ; if ( flags ) { for ( let i = 0 ; i < flags . length ; ++ i ) { switch ( flags . charAt ( i ) ) { case "g" : bits |= UserFlags . Guest ; break ; case "c" : bits |= UserFlags . Connected ; break ; case "d" : bits |= UserFlags . Deleted ; break ; case "s" : bits |= UserFlags . Idle ; break ; case "a" : bits |= UserFlags . HasAvatar ; break ; case "r" : bits |= UserFlags . Robot ; break ; case "T" : bits |= UserFlags . TournamentWinner ; break ; case "t" : bits |= UserFlags . TournamentRunnerUp ; break ; case "p" : bits |= UserFlags . Playing ; break ; case "P" : bits |= UserFlags . PlayingTournament ; break ; case "*" : bits |= UserFlags . KGSPlus ; break ; case "!" : bits |= UserFlags . KGSMeijin ; break ; case "=" : bits |= UserFlags . Ranked ; break ; case "~" : bits |= UserFlags . Biased ; break ; } } } if ( this . flags != bits ) { this . _flags = flags ; this . flags = bits ; return true ; } } return false ; } public hasFlag ( flags ) { return ( ( this . flags & flags ) == flags ) ; } private static unifyRating ( rating ) { if ( ( rating == null ) || ( rating < 0 ) || ( rating == KGS . Constants . RatingNull ) ) return null ; else if ( rating > KGS . Constants . Rating9Dan ) return KGS . Constants . Rating9Dan ; else return rating ; } public static ratingToRank ( rating , unsettled ? , format ? ) { rating = User . unifyRating ( rating ) ; if ( rating == null ) return ( format != UserRankFormat . Numeric ) ? "?" : null ; let dan = ( rating >= KGS . Constants . RatingShodan ) ; let r = ( dan ) ? ( ~ ~ ( rating / 100 ) - 29 ) : ( 30 - ~ ~ ( rating / 100 ) ) ; let rank = r . toString ( ) ; if ( format != UserRankFormat . Numeric ) { if ( format == UserRankFormat . Long ) rank += ( dan ) ? " dan" : " kyu" ; else rank += ( dan ) ? "d" : "k" ; if ( unsettled ) rank += "?" ; } return rank ; } public static rankToRating ( rank ) { if ( null == rank ) return null ; let parts = KGS . Constants . RegularExpressions . Rank . exec ( rank ) ; if ( ( ! parts ) || ( ! parts [ 1 ] ) ) return null ; if ( parts [ 3 ] == 'd' ) { return 2900 + ( ( + parts [ 2 ] ) * 100 ) ; } else { return KGS . Constants . RatingShodan - ( ( + parts [ 2 ] ) * 100 ) ; } } public static estimateHandicap ( player , opponent ) { let playerRating = ( Utils . isNumber ( player ) ) ? User . unifyRating ( < number > player ) : User . rankToRating ( < string > player ) ; if ( playerRating == null ) return null ; let opponentRating = ( Utils . isNumber ( opponent ) ) ? User . unifyRating ( < number > opponent ) : User . rankToRating ( < string > opponent ) ; if ( opponentRating == null ) return null ; return ~ ~ ( opponentRating / 100 ) - ~ ~ ( playerRating / 100 ) ; } } }