Console Formatting: Creating Tables

For scripting examples for learning how to use AMXX.
User avatar
Archive-Poster
Posts: 1229
Gender:
United States of America

Console Formatting: Creating Tables

Post by Archive-Poster »

Introduction

I've mapped the width of the most basic characters ( Basically ASCII 32 to 126 )
and developed a function to easily calculate the amount of whitespaces
required to pad a string in order to create formatted tables

Please note that because the total width of a string does not always become the equivalent of a rational number of whitespaces, it is not always possible to get the exact equivalent width.
This means that the end result can deviate between the equivalent width of 0.25 to 0.75 whitespaces.

However, if the delta ( padding - calculated string width ) is greater
than 9.75 perfect padding are always guaranteed because ot the utilization of
an horizontal tab character that is the equivalent of 3.25 whitespaces in width.

The Font Problem

The font used in the console of Half-Life games is not monospaced, essentially meaning that some characters are wider than others.
This creates a problem every time you wish to line up rows of strings printed to the console in a table like fashion.

Imagine that we wish to create two rows of data to display in the console that looks something like this:

Code: Select all

Property                Value

Name                    Zynda
Health                  100.0
Armor                   100.0
Speed                   255.0 
Seemingly an easy task, but doing this manually would require an painstaking "trial and error" approach to find the amount of whitespace required to pad the space between
the rows.

But what if the data of the first row is dynamic and there is no way of knowing it's width in advance.

Like this:

Code: Select all

Player Name            Health

Richard                90.0
Hariwini               100.0
Rambert                87.5
Oda                    0.0
This is where we have to calculate the amount of whitespaces required during runtime.

Usage Example

Code: Select all

public TableTest( id, level, cid )
{
    if ( !cmd_access( id, level, cid, 1 ) )
    {
        return PLUGIN_HANDLED
    }
    
    new firstRowString[ 128 ]
    new secondRowString[ 32 ]
    new const padding = 60
    
    // ### Static first row data ###
    
    console_print( id, "^nStatic:^n" )
    
    // First line
    
    firstRowString = "Name"
    secondRowString = "Zynda"
    
    FormatConsolePadding( firstRowString, padding, firstRowString, charsmax( firstRowString ) )
    
    console_print( id, "%s%s", firstRowString, secondRowString )
    
    // Second line
    
    firstRowString = "Health Value"
    secondRowString = "100.0"
    
    FormatConsolePadding( firstRowString, padding, firstRowString, charsmax( firstRowString ) )
    
    console_print( id, "%s%s", firstRowString, secondRowString )
    
    // Third line
    
    firstRowString = "Really Long Example String"
    secondRowString = "Some Value"
    
    FormatConsolePadding( firstRowString, padding, firstRowString, charsmax( firstRowString ) )
    
    console_print( id, "%s%s", firstRowString, secondRowString )
    
    // ### Dynamic first row data ###
    
    console_print( id, "^nDynamic:^n" )
    
    // First line
    
    get_mapname( firstRowString, charsmax( firstRowString ) )
    secondRowString = "Current Map"
    
    FormatConsolePadding( firstRowString, padding, firstRowString, charsmax( firstRowString ) )
    
    console_print( id, "%s%s", firstRowString, secondRowString )
    
    // Second line
    
    get_user_name( id, firstRowString, charsmax( firstRowString ) )
    secondRowString = "Your Name"
    
    FormatConsolePadding( firstRowString, padding, firstRowString, charsmax( firstRowString ) )
    
    console_print( id, "%s%s", firstRowString, secondRowString )
    
    return PLUGIN_HANDLED
} 
Function

Code: Select all

FormatConsolePadding( const inputString[], padding, outputString[], outputStringLength )
{
    new whitespaceString[ 512 ]
    new currentChar = 0
    
    // ### Calucate length equivalent
    
    new Float:inputLength = 0.0
    
    for( new i = 0; i < strlen( inputString ); i++ )
    {
        switch( inputString[ i ] )
        {
            // ### LOWERCASE ###
            
            case 97: // a
            {
                inputLength += 1.75
            }
            case 98: // b
            {
                inputLength += 1.75
            }
            case 99: // c
            {
                inputLength += 1.5
            }
            case 100: // d
            {
                inputLength += 1.75
            }
            case 101: // e
            {
                inputLength += 1.75
            }
            case 102: // f
            {
                inputLength += 1.0
            }
            case 103: // g
            {
                inputLength += 1.75
            }
            case 104: // h
            {
                inputLength += 1.75
            }
            case 105: // i
            {
                inputLength += 0.75
            }
            case 106: // j
            {
                inputLength += 1.0
            }
            case 107: // k
            {
                inputLength += 1.5
            }
            case 108: // l
            {
                inputLength += 0.75
            }
            case 109: // m
            {
                inputLength += 2.75
            }
            case 110: // n
            {
                inputLength += 1.75
            }
            case 111: // o
            {
                inputLength += 1.75
            }
            case 112: // p
            {
                inputLength += 1.75
            }
            case 113: // q
            {
                inputLength += 1.75
            }
            case 114: // r
            {
                inputLength += 1.25
            }
            case 115: // s
            {
                inputLength += 1.5
            }
            case 116: // t
            {
                inputLength += 1.0
            }
            case 117: // u
            {
                inputLength += 1.75
            }
            case 118: // v
            {
                inputLength += 1.5
            }
            case 119: // w
            {
                inputLength += 2.5
            }
            case 120: // x
            {
                inputLength += 1.5
            }
            case 121: // y
            {
                inputLength += 1.5
            }
            case 122: // z
            {
                inputLength += 1.5
            }
            
            // ### UPPERCASE ###
            
            case 65: // A
            {
                inputLength += 2.0
            }
            case 66: // B
            {
                inputLength += 1.75
            }
            case 67: // C
            {
                inputLength += 2.0
            }
            case 68: // D
            {
                inputLength += 2.0
            }
            case 69: // E
            {
                inputLength += 1.75
            }
            case 70: // F
            {
                inputLength += 1.75
            }
            case 71: // G
            {
                inputLength += 2.0
            }
            case 72: // H
            {
                inputLength += 2.0
            }
            case 73: // I
            {
                inputLength += 1.0
            }
            case 74: // J
            {
                inputLength += 1.25
            }
            case 75: // K
            {
                inputLength += 1.75
            }
            case 76: // L
            {
                inputLength += 1.5
            }
            case 77: // M
            {
                inputLength += 2.5
            }
            case 78: // N
            {
                inputLength += 2.0
            }
            case 79: // O
            {
                inputLength += 2.25
            }
            case 80: // P
            {
                inputLength += 1.75
            }
            case 81: // Q
            {
                inputLength += 2.25
            }
            case 82: // R
            {
                inputLength += 2.0
            }
            case 83: // S
            {
                inputLength += 2.0
            }
            case 84: // T
            {
                inputLength += 2.0
            }
            case 85: // U
            {
                inputLength += 2.0
            }
            case 86: // V
            {
                inputLength += 2.0
            }
            case 87: // W
            {
                inputLength += 3.0
            }
            case 88: // X
            {
                inputLength += 2.0
            }
            case 89: // Y
            {
                inputLength += 1.75
            }
            case 90: // Z
            {
                inputLength += 1.75
            }
            
            // ### NUMBER ###
            
            case 48: // 0
            {
                inputLength += 1.75
            }
            case 49: // 1
            {
                inputLength += 1.75
            }
            case 50: // 2
            {
                inputLength += 1.75
            }
            case 51: // 3
            {
                inputLength += 1.75
            }
            case 52: // 4
            {
                inputLength += 1.75
            }
            case 53: // 5
            {
                inputLength += 1.75
            }
            case 54: // 6
            {
                inputLength += 1.75
            }
            case 55: // 7
            {
                inputLength += 1.75
            }
            case 56: // 8
            {
                inputLength += 1.75
            }
            case 57: // 9
            {
                inputLength += 1.75
            }
            
            // ### SPECIAL ###
            
            case 33: // !
            {
                inputLength += 1.0
            }
            case 34: // "
            {
                inputLength += 1.25
            }
            case 35: // #
            {
                inputLength += 2.25
            }
            case 36: // $
            {
                inputLength += 1.75
            }
            case 37: // %
            {
                inputLength += 1.5
            }
            case 38: // &
            {
                inputLength += 2.25
            }
            case 39: // '
            {
                inputLength += 0.75
            }
            case 40: // (
            {
                inputLength += 1.25
            }
            case 41: // )
            {
                inputLength += 1.25
            }
            case 42: // *
            {
                inputLength += 2.0
            }
            case 43: // +
            {
                inputLength += 2.0
            }
            case 44: // ,
            {
                inputLength += 1.0
            }
            case 45: // -
            {
                inputLength += 1.25
            }
            case 46: // .
            {
                inputLength += 1.0
            }
            case 47: // /
            {
                inputLength += 1.25
            }
            
            case 58: // :
            {
                inputLength += 1.25
            }
            case 59: // ;
            {
                inputLength += 1.25
            }
            case 60: // <
            {
                inputLength += 2.25
            }
            case 61: // =
            {
                inputLength += 2.25
            }
            case 62: // >
            {
                inputLength += 2.25
            }
            case 63: // ?
            {
                inputLength += 1.5
            }
            case 64: // @
            {
                inputLength += 3.0
            }
            case 91: // [
            {
                inputLength += 1.25
            }
            case 92: // ( BACKWARDS SLASH )
            {
                inputLength += 1.25
            }
            case 93: // ]
            {
                inputLength += 1.25
            }
            case 94: // ^
            {
                inputLength += 2.25
            }
            case 95: // _
            {
                inputLength += 1.75
            }
            case 96: // `
            {
                inputLength += 1.75
            }

            case 123: // {
            {
                inputLength += 1.5
            }
            case 124: // |
            {
                inputLength += 1.5
            }
            case 125: // }
            {
                inputLength += 1.5
            }
            case 126: // ~
            {
                inputLength += 2.25
            }
            
            // ### DEFAULT ###
            
            default:
            {
                inputLength += 1.0
            }
        }
    }
    
    // ### Calculate delta ###
    
    new Float:delta = float( padding ) - inputLength
    
    if( delta < 0.0 ) // Insufficent space
    {
        copy( outputString , outputStringLength, inputString )
        return
    }
    
    // ### Get rid of any decimals where possible ###


    while( floatround( delta ) != delta )
    {
        if( ( delta -= 3.25 ) >= 0.0 )
        {
            if( currentChar < 511 )
            {
                whitespaceString[ currentChar ] = 9
                currentChar++
            }
        }
        else
        {
            break
        }
    }
    
    // ### Add remaining whitespaces ###
    
    while( ( delta -= 1.0 ) > 0.0 )
    {
        if( currentChar < 511 )
        {
            whitespaceString[ currentChar ] = 32
            currentChar++
        }
    }
    
    format( outputString, outputStringLength, "%s%s", inputString, whitespaceString )
} 
Attachments
padding_test.sma.zip
(1.71 KiB) Downloaded 2 times

Who is online

Users browsing this forum: No registered users and 0 guests