// Copyright (C) 1999-2000 Id Software, Inc.
//
/*
=============================================================================
 
SINGLE PLAYER POSTGAME MENU
 
=============================================================================
*/


/*
The work contained within this file is software written by various
copyright holders.  The initial contributor, Id Software holds all
copyright over their software.  However, software used and written by
and for UI Enhanced has copyrights held by the initial author of the
software.
 
The changes written by and for UI Enhanced are contained alongside the
original work from Id Software for convenience and ease of interoperability.
 
For the code contained herein that was written by Id Software, see
the license agreement on their original archive for restrictions and
limitations.
 
The UI Enhanced copyright owner permit free reuse of his code contained
herein, as long as the following terms are met:
 
----------------------------------------------------------------------
1) Credit is given in a place where users of the mod may read
   it. (Title screen, credit screen or README will do).  The
   recommended format is: "First, Last, alias, email"
 
2) There are no attempts to misrepresent the public as to who made the
   alterations.  The UI Enhanced copyright owner does not give permission
   for others to release software under the UI Enhanced name.
----------------------------------------------------------------------
 
Ian Jefferies   - HypoThermia ( uie@planetquake.com )
http://www.planetquake.com/uie
*/


#include "../q3_ui/q3ui_local.h"

#define MAX_SCOREBOARD_CLIENTS		8

#define MAX_PLAYER_NAME 32

#define AWARD_PRESENTATION_TIME		2000

#define ART_MENU0		"menu/art/menu_0"
#define ART_MENU1		"menu/art/menu_1"
#define ART_REPLAY0		"menu/art/replay_0"
#define ART_REPLAY1		"menu/art/replay_1"
#define ART_NEXT0		"menu/art/next_0"
#define ART_NEXT1		"menu/art/next_1"

#define ID_AGAIN		10
#define ID_NEXT			11
#define ID_MENU			12

typedef struct {
    menuframework_s	menu;
    menubitmap_s	item_again;
    menubitmap_s	item_next;
    menubitmap_s	item_menu;

    int				phase;
    int				ignoreKeysTime;
    int				starttime;
    int				scoreboardtime;
    int				serverId;

    int				clientNums[MAX_SCOREBOARD_CLIENTS];
    int				ranks[MAX_SCOREBOARD_CLIENTS];
    int				scores[MAX_SCOREBOARD_CLIENTS];

    char			placeNames[3][64];

    int				level;
    int				numClients;
    int				won;
    int				numAwards;
    int				awardsEarned[6];
    int				awardsLevels[6];
    qboolean		playedSound[6];
    int				lastTier;
    sfxHandle_t		winnerSound;
}
postgameMenuInfo_t;

static postgameMenuInfo_t	postgameMenuInfo;
static char					arenainfo[MAX_INFO_VALUE];

char	*ui_medalNames[] = {"Accuracy", "Impressive", "Excellent", "Gauntlet", "Frags", "Perfect"};
char	*ui_medalPicNames[] = {
                               "menu/medals/medal_accuracy",
                               "menu/medals/medal_impressive",
                               "menu/medals/medal_excellent",
                               "menu/medals/medal_gauntlet",
                               "menu/medals/medal_frags",
                               "menu/medals/medal_victory"
                           };
char	*ui_medalSounds[] = {
                             "sound/feedback/accuracy.wav",
                             "sound/feedback/impressive_a.wav",
                             "sound/feedback/excellent_a.wav",
                             "sound/feedback/gauntlet.wav",
                             "sound/feedback/frags.wav",
                             "sound/feedback/perfect.wav"
                         };




/*
=================
UI_SPKickDupe_f
=================
*/
void UI_SPKickDupe_f( void ) {
    char	info[MAX_INFO_STRING];
    char	info2[MAX_INFO_STRING];
    int numPlayers;
    int i, j;
    char name[MAX_PLAYER_NAME];

    if (!trap_Cvar_VariableValue( "sv_running" ) || trap_Cvar_VariableValue( "g_gametype" ) != GT_SINGLE_PLAYER) {
        Com_Printf("Local server and single player game only\n");
        return;
    }

    trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
    numPlayers = atoi( Info_ValueForKey( info, "sv_maxclients" ) );

    for( i = 0; i < numPlayers; i++ ) {
        trap_GetConfigString( CS_PLAYERS + i, info, MAX_INFO_STRING );

        if (!atoi( Info_ValueForKey( info, "skill" ) ))
            continue;

        Q_strncpyz(name, Info_ValueForKey( info, "n" ), MAX_PLAYER_NAME);
        for (j = i + 1; j < numPlayers; j++) {
            trap_GetConfigString( CS_PLAYERS + j, info2, MAX_INFO_STRING );
            if (!atoi( Info_ValueForKey( info2, "skill" ) ))
                continue;

            if (Q_stricmpn(name, Info_ValueForKey( info2, "n" ), MAX_PLAYER_NAME))
                continue;

            trap_Print(va("Duplicate kicked: %s\n", name));

            // kick the dupe
            trap_Cmd_ExecuteText( EXEC_APPEND, va("clientkick %i\n", i));
        }
    }
}





/*
=================
UI_SPPostgameMenu_AgainEvent
=================
*/
static void UI_SPPostgameMenu_AgainEvent( void* ptr, int event ) {
    if (event != QM_ACTIVATED) {
        return;
    }
    UI_PopMenu();
    trap_Cmd_ExecuteText( EXEC_APPEND, "set activeAction uie_kickdupe\nmap_restart 0\n" );
}





/*
=================
UI_SPPostgameMenu_NextEvent
=================
*/
static void UI_SPPostgameMenu_NextEvent( void* ptr, int event ) {
    int			currentSet;
    int			levelSet;
    int			level;
    int			currentLevel;
    const char	*arenaInfo;

    if (event != QM_ACTIVATED) {
        return;
    }
    UI_PopMenu();

    // handle specially if we just won the training map
    if( postgameMenuInfo.won == 0 ) {
        level = 0;
    } else {
        level = postgameMenuInfo.level + 1;
    }
    levelSet = level / ARENAS_PER_TIER;

    currentLevel = UI_GetCurrentGame();
    if( currentLevel == -1 ) {
        currentLevel = postgameMenuInfo.level;
    }
    currentSet = currentLevel / ARENAS_PER_TIER;

    if( levelSet > currentSet || levelSet == UI_GetNumSPTiers() ) {
        level = currentLevel;
    }

    arenaInfo = UI_GetArenaInfoByNumber( level );
    if ( !arenaInfo ) {
        return;
    }

    UI_SPArena_Start( arenaInfo );
}


/*
=================
UI_SPPostgameMenu_MenuEvent
=================
*/
static void UI_SPPostgameMenu_MenuEvent( void* ptr, int event ) {
    if (event != QM_ACTIVATED) {
        return;
    }
    UI_PopMenu();
    trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; levelselect\n" );
}


/*
=================
UI_SPPostgameMenu_MenuKey
=================
*/
static sfxHandle_t UI_SPPostgameMenu_MenuKey( int key ) {
    if ( uis.realtime < postgameMenuInfo.ignoreKeysTime ) {
        return 0;
    }

    if( postgameMenuInfo.phase == 1 ) {
        trap_Cmd_ExecuteText( EXEC_APPEND, "abort_podium\n" );
        postgameMenuInfo.phase = 2;
        postgameMenuInfo.starttime = uis.realtime;
        postgameMenuInfo.ignoreKeysTime	= uis.realtime + 250;
        return 0;
    }

    if( postgameMenuInfo.phase == 2 ) {
        postgameMenuInfo.phase = 3;
        postgameMenuInfo.starttime = uis.realtime;
        postgameMenuInfo.ignoreKeysTime	= uis.realtime + 250;
        return 0;
    }

    if( key == K_ESCAPE || key == K_MOUSE2 ) {
        return 0;
    }

    return Menu_DefaultKey( &postgameMenuInfo.menu, key );
}


static int medalLocations[6] = {144, 448, 88, 504, 32, 560};

static void UI_SPPostgameMenu_DrawAwardsMedals( int max ) {
    int		n;
    int		medal;
    int		amount;
    int		x, y;
    char	buf[16];

    for( n = 0; n < max; n++ ) {
        x = medalLocations[n];
        y = 64;
        medal = postgameMenuInfo.awardsEarned[n];
        amount = postgameMenuInfo.awardsLevels[n];

        UI_DrawNamedPic( x, y, 48, 48, ui_medalPicNames[medal] );

        if( medal == AWARD_ACCURACY ) {
            Com_sprintf( buf, sizeof(buf), "%i%%", amount );
        } else {
            if( amount == 1 ) {
                continue;
            }
            Com_sprintf( buf, sizeof(buf), "%i", amount );
        }

        UI_DrawString( x + 24, y + 52, buf, UI_CENTER, color_yellow );
    }
}


static void UI_SPPostgameMenu_DrawAwardsPresentation( int timer ) {
    int		awardNum;
    int		atimer;
    vec4_t	color;

    awardNum = timer / AWARD_PRESENTATION_TIME;
    atimer = timer % AWARD_PRESENTATION_TIME;

    color[0] = color[1] = color[2] = 1.0f;
    color[3] = (float)( AWARD_PRESENTATION_TIME - atimer ) / (float)AWARD_PRESENTATION_TIME;
    UI_DrawProportionalString( 320, 64, ui_medalNames[postgameMenuInfo.awardsEarned[awardNum]], UI_CENTER, color );

    UI_SPPostgameMenu_DrawAwardsMedals( awardNum + 1 );

    if( !postgameMenuInfo.playedSound[awardNum] ) {
        postgameMenuInfo.playedSound[awardNum] = qtrue;
        trap_S_StartLocalSound( trap_S_RegisterSound( ui_medalSounds[postgameMenuInfo.awardsEarned[awardNum]], qfalse ), CHAN_ANNOUNCER );
    }
}


/*
=================
UI_SPPostgameMenu_MenuDrawScoreLine
=================
*/
static void UI_SPPostgameMenu_MenuDrawScoreLine( int n, int y ) {
    int		rank;
    char	name[64];
    char	info[MAX_INFO_STRING];

    if( n > (postgameMenuInfo.numClients + 1) ) {
        n -= (postgameMenuInfo.numClients + 2);
    }

    if( n >= postgameMenuInfo.numClients ) {
        return;
    }

    rank = postgameMenuInfo.ranks[n];
    if( rank & RANK_TIED_FLAG ) {
        UI_DrawString( 640 - 31 * SMALLCHAR_WIDTH, y, "(tie)", UI_LEFT|UI_SMALLFONT, color_white );
        rank &= ~RANK_TIED_FLAG;
    }
    trap_GetConfigString( CS_PLAYERS + postgameMenuInfo.clientNums[n], info, MAX_INFO_STRING );
    Q_strncpyz( name, Info_ValueForKey( info, "n" ), sizeof(name) );
    Q_CleanStr( name );

    UI_DrawString( 640 - 25 * SMALLCHAR_WIDTH, y, va( "#%i: %-16s %2i", rank + 1, name, postgameMenuInfo.scores[n] ), UI_LEFT|UI_SMALLFONT, color_white );
}


/*
=================
UI_SPPostgameMenu_MenuDraw
=================
*/
static void UI_SPPostgameMenu_MenuDraw( void ) {
    int		timer;
    int		serverId;
    int		n;
    char	info[MAX_INFO_STRING];

    trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) );
    serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) );
    if( serverId != postgameMenuInfo.serverId ) {
        UI_PopMenu();
        return;
    }

    // phase 1
    if ( postgameMenuInfo.numClients > 2 ) {
        UI_DrawProportionalString( 510, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[2], UI_CENTER, color_white );
    }
    UI_DrawProportionalString( 130, 480 - 64 - PROP_HEIGHT, postgameMenuInfo.placeNames[1], UI_CENTER, color_white );
    UI_DrawProportionalString( 320, 480 - 64 - 2 * PROP_HEIGHT, postgameMenuInfo.placeNames[0], UI_CENTER, color_white );

    if( postgameMenuInfo.phase == 1 ) {
        timer = uis.realtime - postgameMenuInfo.starttime;

        if( timer >= 1000 && postgameMenuInfo.winnerSound ) {
            trap_S_StartLocalSound( postgameMenuInfo.winnerSound, CHAN_ANNOUNCER );
            postgameMenuInfo.winnerSound = 0;
        }

        if( timer < 5000 ) {
            return;
        }
        postgameMenuInfo.phase = 2;
        postgameMenuInfo.starttime = uis.realtime;
    }

    // phase 2
    if( postgameMenuInfo.phase == 2 ) {
        timer = uis.realtime - postgameMenuInfo.starttime;
        if( timer >= ( postgameMenuInfo.numAwards * AWARD_PRESENTATION_TIME ) ) {

            if( timer < 5000 ) {
                return;
            }

            postgameMenuInfo.phase = 3;
            postgameMenuInfo.starttime = uis.realtime;
        } else {
            UI_SPPostgameMenu_DrawAwardsPresentation( timer );
        }
    }

    // phase 3
    if( postgameMenuInfo.phase == 3 ) {
        if( uis.demoversion ) {
            if( postgameMenuInfo.won == 1 && UI_ShowTierVideo( 8 )) {
                trap_Cvar_Set( "nextmap", "" );
                trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic demoEnd.RoQ\n" );
                return;
            }
        } else if( postgameMenuInfo.won > -1 && UI_ShowTierVideo( postgameMenuInfo.won + 1 )) {
            if( postgameMenuInfo.won == postgameMenuInfo.lastTier ) {
                trap_Cvar_Set( "nextmap", "" );
                trap_Cmd_ExecuteText( EXEC_APPEND, "disconnect; cinematic end.RoQ\n" );
                return;
            }

            trap_Cvar_SetValue( "ui_spSelection", postgameMenuInfo.won * ARENAS_PER_TIER );
            trap_Cvar_Set( "nextmap", "levelselect" );
            trap_Cmd_ExecuteText( EXEC_APPEND, va( "disconnect; cinematic tier%i.RoQ\n", postgameMenuInfo.won + 1 ) );
            return;
        }

        postgameMenuInfo.item_again.generic.flags &= ~QMF_INACTIVE;
        postgameMenuInfo.item_next.generic.flags &= ~QMF_INACTIVE;
        postgameMenuInfo.item_menu.generic.flags &= ~QMF_INACTIVE;

        UI_SPPostgameMenu_DrawAwardsMedals( postgameMenuInfo.numAwards );

        Menu_Draw( &postgameMenuInfo.menu );
    }

    // draw the scoreboard
    if( !trap_Cvar_VariableValue( "ui_spScoreboard" ) ) {
        return;
    }

    timer = uis.realtime - postgameMenuInfo.scoreboardtime;
    if( postgameMenuInfo.numClients <= 3 ) {
        n = 0;
    } else {
        n = timer / 1500 % (postgameMenuInfo.numClients + 2);
    }
    UI_SPPostgameMenu_MenuDrawScoreLine( n, 0 );
    UI_SPPostgameMenu_MenuDrawScoreLine( n + 1, 0 + SMALLCHAR_HEIGHT );
    UI_SPPostgameMenu_MenuDrawScoreLine( n + 2, 0 + 2 * SMALLCHAR_HEIGHT );
}


/*
=================
UI_SPPostgameMenu_Cache
=================
*/
void UI_SPPostgameMenu_Cache( void ) {
    int			n;
    qboolean	buildscript;

    buildscript = trap_Cvar_VariableValue("com_buildscript");

    trap_R_RegisterShaderNoMip( ART_MENU0 );
    trap_R_RegisterShaderNoMip( ART_MENU1 );
    trap_R_RegisterShaderNoMip( ART_REPLAY0 );
    trap_R_RegisterShaderNoMip( ART_REPLAY1 );
    trap_R_RegisterShaderNoMip( ART_NEXT0 );
    trap_R_RegisterShaderNoMip( ART_NEXT1 );
    for( n = 0; n < 6; n++ ) {
        trap_R_RegisterShaderNoMip( ui_medalPicNames[n] );
        trap_S_RegisterSound( ui_medalSounds[n], qfalse );
    }

    if( buildscript ) {
        trap_S_RegisterSound( "music/loss.wav", qfalse );
        trap_S_RegisterSound( "music/win.wav", qfalse );
        trap_S_RegisterSound( "sound/player/announce/youwin.wav", qfalse );
    }
}


/*
=================
UI_SPPostgameMenu_Init
=================
*/
static void UI_SPPostgameMenu_Init( void ) {
    postgameMenuInfo.menu.wrapAround	= qtrue;
    postgameMenuInfo.menu.key			= UI_SPPostgameMenu_MenuKey;
    postgameMenuInfo.menu.draw			= UI_SPPostgameMenu_MenuDraw;
    postgameMenuInfo.ignoreKeysTime		= uis.realtime + 1500;

    UI_SPPostgameMenu_Cache();

    postgameMenuInfo.item_menu.generic.type			= MTYPE_BITMAP;
    postgameMenuInfo.item_menu.generic.name			= ART_MENU0;
    postgameMenuInfo.item_menu.generic.flags		= QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE;
    postgameMenuInfo.item_menu.generic.x			= 0;
    postgameMenuInfo.item_menu.generic.y			= 480-64;
    postgameMenuInfo.item_menu.generic.callback		= UI_SPPostgameMenu_MenuEvent;
    postgameMenuInfo.item_menu.generic.id			= ID_MENU;
    postgameMenuInfo.item_menu.width				= 128;
    postgameMenuInfo.item_menu.height				= 64;
    postgameMenuInfo.item_menu.focuspic				= ART_MENU1;

    postgameMenuInfo.item_again.generic.type		= MTYPE_BITMAP;
    postgameMenuInfo.item_again.generic.name		= ART_REPLAY0;
    postgameMenuInfo.item_again.generic.flags		= QMF_CENTER_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE;
    postgameMenuInfo.item_again.generic.x			= 320;
    postgameMenuInfo.item_again.generic.y			= 480-64;
    postgameMenuInfo.item_again.generic.callback	= UI_SPPostgameMenu_AgainEvent;
    postgameMenuInfo.item_again.generic.id			= ID_AGAIN;
    postgameMenuInfo.item_again.width				= 128;
    postgameMenuInfo.item_again.height				= 64;
    postgameMenuInfo.item_again.focuspic			= ART_REPLAY1;

    postgameMenuInfo.item_next.generic.type			= MTYPE_BITMAP;
    postgameMenuInfo.item_next.generic.name			= ART_NEXT0;
    postgameMenuInfo.item_next.generic.flags		= QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_INACTIVE;
    postgameMenuInfo.item_next.generic.x			= 640;
    postgameMenuInfo.item_next.generic.y			= 480-64;
    postgameMenuInfo.item_next.generic.callback		= UI_SPPostgameMenu_NextEvent;
    postgameMenuInfo.item_next.generic.id			= ID_NEXT;
    postgameMenuInfo.item_next.width				= 128;
    postgameMenuInfo.item_next.height				= 64;
    postgameMenuInfo.item_next.focuspic				= ART_NEXT1;

    Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_menu );
    Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_again );
    Menu_AddItem( &postgameMenuInfo.menu, ( void * )&postgameMenuInfo.item_next );
}


static void Prepname( int index ) {
    int		len;
    char	name[64];
    char	info[MAX_INFO_STRING];

    trap_GetConfigString( CS_PLAYERS + postgameMenuInfo.clientNums[index], info, MAX_INFO_STRING );
    Q_strncpyz( name, Info_ValueForKey( info, "n" ), sizeof(name) );
    Q_CleanStr( name );
    len = strlen( name );

    while( len && UI_ProportionalStringWidth( name ) > 256 ) {
        len--;
        name[len] = 0;
    }

    Q_strncpyz( postgameMenuInfo.placeNames[index], name, sizeof(postgameMenuInfo.placeNames[index]) );
}


/*
=================
UI_SPPostgameMenu_f
=================
*/
void UI_SPPostgameMenu_f( void ) {
    int			playerGameRank;
    int			playerClientNum;
    int			n;
    int			oldFrags, newFrags;
    const char	*arena;
    int			awardValues[6];
    char		map[MAX_QPATH];
    char		info[MAX_INFO_STRING];

    memset( &postgameMenuInfo, 0, sizeof(postgameMenuInfo) );

    trap_GetConfigString( CS_SYSTEMINFO, info, sizeof(info) );
    postgameMenuInfo.serverId = atoi( Info_ValueForKey( info, "sv_serverid" ) );

    trap_GetConfigString( CS_SERVERINFO, info, sizeof(info) );
    Q_strncpyz( map, Info_ValueForKey( info, "mapname" ), sizeof(map) );
    arena = UI_GetArenaInfoByMap( map );
    if ( !arena ) {
        return;
    }
    Q_strncpyz( arenainfo, arena, sizeof(arenainfo) );

    postgameMenuInfo.level = atoi( Info_ValueForKey( arenainfo, "num" ) );

    postgameMenuInfo.numClients = atoi( UI_Argv( 1 ) );
    playerClientNum = atoi( UI_Argv( 2 ) );
    playerGameRank = 8;		// in case they ended game as a spectator

    if( postgameMenuInfo.numClients > MAX_SCOREBOARD_CLIENTS ) {
        postgameMenuInfo.numClients = MAX_SCOREBOARD_CLIENTS;
    }

    for( n = 0; n < postgameMenuInfo.numClients; n++ ) {
        postgameMenuInfo.clientNums[n] = atoi( UI_Argv( 8 + n * 3 + 1 ) );
        postgameMenuInfo.ranks[n] = atoi( UI_Argv( 8 + n * 3 + 2 ) );
        postgameMenuInfo.scores[n] = atoi( UI_Argv( 8 + n * 3 + 3 ) );

        if( postgameMenuInfo.clientNums[n] == playerClientNum ) {
            playerGameRank = (postgameMenuInfo.ranks[n] & ~RANK_TIED_FLAG) + 1;
        }
    }

    UI_SetBestScore( postgameMenuInfo.level, playerGameRank );

    // process award stats and prepare presentation data
    awardValues[AWARD_ACCURACY] = atoi( UI_Argv( 3 ) );
    awardValues[AWARD_IMPRESSIVE] = atoi( UI_Argv( 4 ) );
    awardValues[AWARD_EXCELLENT] = atoi( UI_Argv( 5 ) );
    awardValues[AWARD_GAUNTLET] = atoi( UI_Argv( 6 ) );
    awardValues[AWARD_FRAGS] = atoi( UI_Argv( 7 ) );
    awardValues[AWARD_PERFECT] = atoi( UI_Argv( 8 ) );

    postgameMenuInfo.numAwards = 0;

    if( awardValues[AWARD_ACCURACY] >= 50 ) {
        UI_LogAwardData( AWARD_ACCURACY, 1 );
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_ACCURACY;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_ACCURACY];
        postgameMenuInfo.numAwards++;
    }

    if( awardValues[AWARD_IMPRESSIVE] ) {
        UI_LogAwardData( AWARD_IMPRESSIVE, awardValues[AWARD_IMPRESSIVE] );
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_IMPRESSIVE;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_IMPRESSIVE];
        postgameMenuInfo.numAwards++;
    }

    if( awardValues[AWARD_EXCELLENT] ) {
        UI_LogAwardData( AWARD_EXCELLENT, awardValues[AWARD_EXCELLENT] );
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_EXCELLENT;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_EXCELLENT];
        postgameMenuInfo.numAwards++;
    }

    if( awardValues[AWARD_GAUNTLET] ) {
        UI_LogAwardData( AWARD_GAUNTLET, awardValues[AWARD_GAUNTLET] );
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_GAUNTLET;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = awardValues[AWARD_GAUNTLET];
        postgameMenuInfo.numAwards++;
    }

    oldFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100;
    UI_LogAwardData( AWARD_FRAGS, awardValues[AWARD_FRAGS] );
    newFrags = UI_GetAwardLevel( AWARD_FRAGS ) / 100;
    if( newFrags > oldFrags ) {
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_FRAGS;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = newFrags * 100;
        postgameMenuInfo.numAwards++;
    }

    if( awardValues[AWARD_PERFECT] ) {
        UI_LogAwardData( AWARD_PERFECT, 1 );
        postgameMenuInfo.awardsEarned[postgameMenuInfo.numAwards] = AWARD_PERFECT;
        postgameMenuInfo.awardsLevels[postgameMenuInfo.numAwards] = 1;
        postgameMenuInfo.numAwards++;
    }

    if ( playerGameRank == 1 ) {
        postgameMenuInfo.won = UI_TierCompleted( postgameMenuInfo.level );
    } else {
        postgameMenuInfo.won = -1;
    }

    postgameMenuInfo.starttime = uis.realtime;
    postgameMenuInfo.scoreboardtime = uis.realtime;

    trap_Key_SetCatcher( KEYCATCH_UI );
    uis.menusp = 0;

    UI_SPPostgameMenu_Init();
    UI_PushMenu( &postgameMenuInfo.menu );

    if ( playerGameRank == 1 ) {
        Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_next );
    } else {
        Menu_SetCursorToItem( &postgameMenuInfo.menu, &postgameMenuInfo.item_again );
    }

    Prepname( 0 );
    Prepname( 1 );
    Prepname( 2 );

    if ( playerGameRank != 1 ) {
        postgameMenuInfo.winnerSound = trap_S_RegisterSound( va( "sound/player/announce/%s_wins.wav", postgameMenuInfo.placeNames[0] ), qfalse );
        trap_Cmd_ExecuteText( EXEC_APPEND, "music music/loss\n" );
    } else {
        postgameMenuInfo.winnerSound = trap_S_RegisterSound( "sound/player/announce/youwin.wav", qfalse );
        trap_Cmd_ExecuteText( EXEC_APPEND, "music music/win\n" );
    }

    postgameMenuInfo.phase = 1;

    postgameMenuInfo.lastTier = UI_GetNumSPTiers();
    if ( UI_GetSpecialArenaInfo( "final" ) ) {
        postgameMenuInfo.lastTier++;
    }
}
