/****************************************************
  Persistent Token Helper Include Script
  apts_inc_toksys

  Last Updated: September 26, 2002

  ***Ambrosia Persistent Token System***
    Created by Mojo(Allen Sun)

  This script includes helper functions that are
  called by the accessor functions in the
  apts_inc_ptok script.

****************************************************/
/* Function Declarations */

// Gets the decimal value of a bit position
int APTS_GetBitValue(int iBitPos);
// Returns whether or not a specified binary bit of a number is set
int APTS_IsBitSet(int iNumber, int iBitPos);
// Gets the maximum value of iSize number of tokens
int APTS_GetMaxSizeValue(int iSize, int bSigned);
// Gets the minimum value of iSize number of tokens
int APTS_GetMinSizeValue(int iSize, int bSigned);
// Returns the number of tokens needed to store the number
int APTS_GetTokenSpace(int iNumber, int bSigned);
// Creates a token on the player and puts it in the token box
object APTS_CreateTokenOnPlayer(object oPlayer, int iSlot, int iType, int iValue);
// Converts a base ten number to any base and returns it as a string
string APTS_ConvertNumberToBaseString(int iNumber, int iBase);
// Gets the total integer value of tokens starting at a slot number
int APTS_GetTokenIntValue(object oPlayer, int iSlotNum, int iSize, int bSigned);
// Gets the value of the token at a certain slot
int APTS_GetSlotValue(object oPlayer, int iSlotNum, int bSigned);
// Converts an integer into a binary string
string APTS_IntToBinaryString(int iValue, int bAlignBit = 0);
// Converts a binary string into an integer
int APTS_BinaryStringToInt(string sBinary, int bSigned = TRUE);
// Converts a binarty string into a fractional value
float APTS_BinaryStringToDecimal(string sBinary);
// Calculates a number raised to a certain exponent
float APTS_Pow(float fValue, int iExp);
// Removes trailing zeroes in a binary string
string APTS_RemoveTrailingZeroes(string sBinary);
// Converts a floating point number into an integer representation using the
// 32-bit IEEE FP format
int APTS_FloatToIntRep(float fValue, int iSize);
// Converts an integer representation back into a floating point number
float APTS_IntRepToFloat(int iValue, int iSize);
// Removes all declaration information for a variable
void APTS_RemoveOldDeclaration(string sVarName);
// Converts a string of up to three characters into an medium integer
int APTS_ConvertThreeCharToInt(string sString);
// Converts a medium integer value into a three character string
string APTS_ConvertIntToThreeChar(int iMedValue);

/* Function Definitions */


string APTS_GetResRefFromTag(string sTag)
{
    return GetStringLowerCase(GetStringLeft(sTag, 16));
}

object APTS_FindItemInInventoryByTag(object oTarget, string sTag, int iNth = 0)
{
    int iCount = 0;
    object oCurrentObject = OBJECT_INVALID;

    if(GetHasInventory(oTarget) == FALSE)
        return oCurrentObject;

    oCurrentObject =  GetFirstItemInInventory(oTarget);

    while(GetIsObjectValid(oCurrentObject) == TRUE)
    {
        if(GetTag(oCurrentObject) == sTag)
        {
            if(iCount == iNth)
                return oCurrentObject;
            else
                ++iCount;
        }
        oCurrentObject = GetNextItemInInventory(oTarget);
    }
    return oCurrentObject;

}
int APTS_GetBitValue(int iBitPos)
{
    return FloatToInt(pow(2.0, IntToFloat(iBitPos)));
}

int APTS_IsBitSet(int iNumber, int iBitPos)
{
    return ((iNumber & APTS_GetBitValue(iBitPos)) > 0);
}

int APTS_GetTokenSpace(int iNumber, int bSigned)
{
    if(bSigned)
    {
        if(iNumber > CINT_MAX_SIGNED_TWO)
            return 3;
        else if(iNumber > CINT_MAX_SIGNED_ONE)
            return 2;
        else if(iNumber > 0)
            return 1;
        else if(iNumber == 0)
            return 0;
        else if(iNumber >= (-CINT_MAX_SIGNED_ONE-1))
            return 1;
        else if(iNumber >= (-CINT_MAX_SIGNED_TWO-1))
            return 2;
        else
            return 3;
    }
    else
    {
        if(iNumber > CINT_MAX_UNSIGNED_TWO)
            return 3;
        else if(iNumber > CINT_MAX_UNSIGNED_ONE)
            return 2;
        else if(iNumber > 0)
            return 1;
        else
            return 0;
    }
}
int APTS_GetMaxSizeValue(int iSize, int bSigned)
{
    if(bSigned)
    {
        switch(iSize)
        {
            case 0:
                return 0;
            case 1:
                return CINT_MAX_SIGNED_ONE;
            case 2:
                return CINT_MAX_SIGNED_TWO;
            case 3:
                return CINT_MAX_SIGNED_THREE;
            default:
                return MAX_INT;
        }
    }
    else
    {
        switch(iSize)
        {
            case 0:
                return 0;
            case 1:
                return CINT_MAX_UNSIGNED_ONE;
            case 2:
                return CINT_MAX_UNSIGNED_TWO;
            case 3:
                return CINT_MAX_UNSIGNED_THREE;
            default:
                return MAX_INT;
        }
    }
    return 0;
}
int APTS_GetMinSizeValue(int iSize, int bSigned)
{
    if(bSigned)
    {
        switch(iSize)
        {
            case 0:
                return 0;
            case 1:
                return (-CINT_MAX_SIGNED_ONE-1);
            case 2:
                return (-CINT_MAX_SIGNED_TWO-1);
            case 3:
                return (-CINT_MAX_SIGNED_THREE-1);
            default:
                return (-MAX_INT-1);
        }
    }
    return 0;
}
object APTS_CreateTokenOnPlayer(object oPlayer, int iSlot, int iType, int iValue)
{
    if(iValue <= 0)
        return OBJECT_INVALID;
    object oTokenBox = APTS_FindItemInInventoryByTag(oPlayer, APTS_TOKEN_BOX_TAG);
    if(!GetIsObjectValid(oTokenBox))
    {
        oTokenBox = CreateItemOnObject(APTS_GetResRefFromTag(APTS_TOKEN_BOX_TAG), oPlayer);
        if(!GetIsObjectValid(oTokenBox))
            return OBJECT_INVALID;
    }
    string sTokenTag = APTS_TOKEN_TAG + "_S";

    if(iSlot < 100)
        sTokenTag += "0";
    if(iSlot < 10)
        sTokenTag += "0";
    sTokenTag += (IntToString(iSlot) + "_");
    if(iType < 10)
        sTokenTag += "0";
    sTokenTag += IntToString(iType);
    string sTokenResRef = APTS_GetResRefFromTag(sTokenTag);

    int i = 1;
    object oToken = CreateItemOnObject(sTokenResRef, oTokenBox, iValue);
    // Token could not be created
    while(GetItemPossessor(oToken) == OBJECT_INVALID && GetIsObjectValid(oTokenBox))
    {
        DestroyObject(oToken);
        oToken = CreateItemOnObject(sTokenResRef, oTokenBox, iValue);
        oTokenBox = APTS_FindItemInInventoryByTag(oPlayer, APTS_TOKEN_BOX_TAG, i++);
    }
    if(GetItemPossessor(oToken) == OBJECT_INVALID)
    {
        DestroyObject(oToken);
        oTokenBox = CreateItemOnObject(APTS_GetResRefFromTag(APTS_TOKEN_BOX_TAG), oPlayer);
        if(!GetIsObjectValid(oTokenBox))
            return OBJECT_INVALID;
        oToken = CreateItemOnObject(sTokenResRef, oTokenBox, iValue);
    }
    SetLocalObject(oToken, "ats_obj_possessor", oPlayer);

    return oToken;

}
// Converts a base ten number to any base and returns it as a string
string APTS_ConvertNumberToBaseString(int iNumber, int iBase)
{
    string sRemainderString = "";
    int iQuotient = iNumber;
    int iRemainder;
    int iAddedZeroes;
    int i;

    while(iQuotient != 0)
    {
        iRemainder = abs(iQuotient % iBase);
        iAddedZeroes = GetStringLength(IntToString(CINT_NUMBER_BASE-1)) - GetStringLength(IntToString(iRemainder));
        sRemainderString = IntToString(iRemainder) + sRemainderString;
        for(i = 0; i < iAddedZeroes; ++i)
        {
            sRemainderString = "0" + sRemainderString;
        }
         iQuotient = iQuotient / iBase;
    }
    if(iNumber < 0)
        sRemainderString = "-" + sRemainderString;
    return sRemainderString;
}

void APTS_CreateSlotTokens(object oPlayer, int iValue, int iSlot, int bSigned = TRUE )
{
    int iNumTokens = APTS_GetTokenSpace(iValue, bSigned);
    int i, iType;
    int iFieldValue;
    int iTokenSize;
    int bPlotFlag = TRUE;
    object oCreatedToken;

    string sBinaryString = APTS_IntToBinaryString(iValue, CINT_BITS_PER_TOKEN);

    for(i = 0; i < iNumTokens; ++i)
    {
        iFieldValue = APTS_BinaryStringToInt(GetStringRight(sBinaryString, CINT_BITS_PER_TOKEN), FALSE);
        if(sBinaryString == "" && bSigned)
        {
            // Create a special token to indicate a positive sign
            iFieldValue = CINT_TOKENS_FOR_BASE * 198;
        }

        sBinaryString = GetStringLeft(sBinaryString, GetStringLength(sBinaryString) - CINT_BITS_PER_TOKEN);

        for(iType = 0; iType < CINT_TOKENS_FOR_BASE; ++iType)
        {
            bPlotFlag = TRUE;

            // Find which token to use to store value
            if(iFieldValue <= ((iType+1) * 198))
            {

                iTokenSize = iFieldValue - (198 * iType);
                if(iTokenSize > 99)
                {
                    bPlotFlag = FALSE;
                    iTokenSize -= 99;
                }

                oCreatedToken = APTS_CreateTokenOnPlayer(oPlayer, iSlot + i, iType, iTokenSize);
                SetPlotFlag(oCreatedToken, bPlotFlag);
                break;
            }
        }

    }
}
void APTS_RemoveSlotTokens(object oPlayer, int iSlotNum)
{
    object oItem;
    string sPartialTokenTag = APTS_TOKEN_TAG + "_S";
    if(iSlotNum < 100)
        sPartialTokenTag += "0";
    if(iSlotNum < 10)
        sPartialTokenTag += "0";
    sPartialTokenTag += (IntToString(iSlotNum) + "_");

    oItem = GetFirstItemInInventory(oPlayer);
    while(GetIsObjectValid(oItem))
    {
        // Found a matching token to remove
        if(FindSubString(GetTag(oItem), sPartialTokenTag) == 0)
        {
            DestroyObject(oItem);
        }
        oItem = GetNextItemInInventory(oPlayer);
    }
}
int APTS_GetTokenIntValue(object oPlayer, int iSlotNum, int iSize, int bSigned)
{
    int iTotalValue = 0;
    int bFoundToken = FALSE;
    int iSlotValue;
    int i;

    for(i = iSize-1; i >= 0; --i)
    {
        iSlotValue = APTS_GetSlotValue(oPlayer, iSlotNum+i, FALSE);
        if(iSlotValue != 0)
        {
            if(bSigned)
            {
                if(iSlotValue == CINT_TOKENS_FOR_BASE * 198)
                    iSlotValue = 0;
                else if(bFoundToken == FALSE)
                    iSlotValue = APTS_GetSlotValue(oPlayer, iSlotNum+i, TRUE);
            }
            bFoundToken = TRUE;
            iTotalValue += (iSlotValue*FloatToInt(pow(IntToFloat(CINT_NUMBER_BASE), IntToFloat(i))));
        }
    }
    return iTotalValue;
}

int APTS_GetSlotValue(object oPlayer, int iSlotNum, int bSigned)
{
    string sItemTag;

    int iTokenType;
    int iFixedTokenType = -1;

    int iTokenValue = 0;
    int bFoundToken = FALSE;
    int bPlotFlag = FALSE;

    string sPartialTokenTag = APTS_TOKEN_TAG + "_S";
    if(iSlotNum < 100)
        sPartialTokenTag += "0";
    if(iSlotNum < 10)
        sPartialTokenTag += "0";
    sPartialTokenTag += (IntToString(iSlotNum) + "_");

    // Search through inventory looking for tokens
    object oItem = GetFirstItemInInventory(oPlayer);
    while(GetIsObjectValid(oItem))
    {
        sItemTag = GetTag(oItem);
        // Found a matching token
        if(FindSubString(sItemTag, sPartialTokenTag) == 0)
        {
            iTokenType = StringToInt(GetStringRight(sItemTag, 2));
            if(!bFoundToken)
            {
                iTokenValue = (198 * iTokenType) + GetNumStackedItems(oItem);

                bFoundToken = TRUE;
                iFixedTokenType = iTokenType;
                bPlotFlag = GetPlotFlag(oItem);
            }
            else if(iFixedTokenType == iTokenType)
            {
                iTokenValue += GetNumStackedItems(oItem);
                if(GetPlotFlag(oItem) == TRUE)
                    bPlotFlag = TRUE;
            }
            else
                DestroyObject(oItem);
        }
        oItem = GetNextItemInInventory(oPlayer);
    }

    if(iTokenValue > 0 && bPlotFlag == FALSE)
    {
           iTokenValue += 99;
    }

    // If Signed, convert to negative number by two's complement
    if(bSigned && (iTokenValue > APTS_GetBitValue(CINT_BITS_PER_TOKEN-1)-1))
        iTokenValue -= APTS_GetBitValue(CINT_BITS_PER_TOKEN);

    return iTokenValue;
}

string APTS_IntToBinaryString(int iValue, int iAlignBit = 0)
{
    string sHexString = IntToHexString(iValue);
    string sBinaryString = "";
    string sChar;
    int i;
    for(i = 2; i < 10; ++i)
    {
        sChar = GetSubString(sHexString, i, 1);
        if(sChar == "0")
            sBinaryString += "0000";
        else if(sChar == "1")
            sBinaryString += "0001";
        else if(sChar == "2")
           sBinaryString += "0010";
        else if(sChar == "3")
           sBinaryString += "0011";
        else if(sChar == "4")
           sBinaryString += "0100";
        else if(sChar == "5")
           sBinaryString += "0101";
        else if(sChar == "6")
           sBinaryString += "0110";
        else if(sChar == "7")
           sBinaryString += "0111";
        else if(sChar == "8")
           sBinaryString += "1000";
        else if(sChar == "9")
           sBinaryString += "1001";
        else if(sChar == "a")
           sBinaryString += "1010";
        else if(sChar == "b")
           sBinaryString += "1011";
        else if(sChar == "c")
           sBinaryString += "1100";
        else if(sChar == "d")
           sBinaryString += "1101";
        else if(sChar == "e")
           sBinaryString += "1110";
        else // F
           sBinaryString += "1111";
    }


    // Remove Leading Zeroes
    while(GetStringLeft(sBinaryString, 1) == "0")
    {
        sBinaryString = GetStringRight(sBinaryString, GetStringLength(sBinaryString) - 1);
    }
    if(iAlignBit > 0)
    {
        int iAddedZeroes = GetStringLength(sBinaryString) % iAlignBit;
        if(iAddedZeroes > 0)
            iAddedZeroes = iAlignBit - iAddedZeroes;
        // Fill with ones if negative
        if(iValue < 0)
        {
            for(i = 0; i < iAddedZeroes; ++i)
                sBinaryString = "1" + sBinaryString;
        }
        else  // Fill with zeroes
        {
            for(i = 0; i < iAddedZeroes; ++i)
                sBinaryString = "0" + sBinaryString;
        }

    }
    return sBinaryString;
}

int APTS_BinaryStringToInt(string sBinary, int bSigned = TRUE)
{
    int iNumBits = GetStringLength(sBinary);
    string sChar;
    int iTotal = 0;
    int i;
    for(i = iNumBits; i > 0; --i)
    {
        sChar = GetSubString(sBinary, iNumBits - i, 1);
        if(sChar == "1")
                iTotal += APTS_GetBitValue(i-1);
    }
    if(bSigned && (iTotal > APTS_GetBitValue(iNumBits-1)-1))
        iTotal -= APTS_GetBitValue(iNumBits);

    return iTotal;


}

float APTS_BinaryStringToDecimal(string sBinary)
{
    int iLength = GetStringLength(sBinary);
    int i;

    float fTotal = 0.0;
    float fDivider = 1.0;

    for(i = 0; i < iLength; ++i)
    {
        fDivider /= 2.0;
        if(GetSubString(sBinary, i, 1) == "1")
            fTotal += fDivider;
    }
    return fTotal;
}
float APTS_Pow(float fValue, int iExp)
{
    int i;
    float fTotal = 1.0;

    if(iExp < 0)
    {
        fTotal = 1.0;
        for(i = 0; i < -iExp; ++i)
        {
            fTotal /= fValue;
        }
    }
    else
    {
        for(i = 0; i < iExp; ++i)
        {
            fTotal *= fValue;
        }
    }
    return fTotal;
}
string APTS_RemoveTrailingZeroes(string sBinary)
{
    string sTruncString = sBinary;

    while(GetStringRight(sTruncString, 1) == "0")
    {
        sTruncString = GetStringLeft(sTruncString, GetStringLength(sTruncString) - 1);
    }
    return sTruncString;

}
int APTS_FloatToIntRep(float fValue, int iSize)
{
    if(fValue == 0.0)
        return 0;
    float fAbsValue = fabs(fValue);

    string sFloatString = FloatToString(fAbsValue);
    string sIntPartBinary = "";
    int iMantissaSize;
    int iExpOffset;
    int iExpSize;

    if(iSize == 2)
    {
        iMantissaSize = 15;
        iExpOffset = 31;
        iExpSize = 6;
    }
    else if(iSize == 3)
    {
        iMantissaSize = 23;
        iExpOffset = 127;
        iExpSize = 8;
    }

    while(GetStringLeft(sFloatString, 1) == " ")
    {
        sFloatString = GetStringRight(sFloatString, GetStringLength(sFloatString) - 1);
    }
    // Get Integer part
    sFloatString = GetStringLeft(sFloatString, FindSubString(sFloatString, "."));
    float fIntPart = StringToFloat(sFloatString);

    float fDiv = fIntPart;
    while(fDiv >= 1.0)
    {
        sFloatString = FloatToString(fDiv);
        while(GetStringLeft(sFloatString, 1) == " ")
        {
            sFloatString = GetStringRight(sFloatString, GetStringLength(sFloatString) - 1);
        }

        sFloatString = GetStringLeft(sFloatString, FindSubString(sFloatString, "."));
        if(StringToInt(GetStringRight(sFloatString, 1)) % 2 == 1)
            sIntPartBinary = "1" + sIntPartBinary;
        else
            sIntPartBinary = "0" + sIntPartBinary;

        fDiv = StringToFloat(sFloatString);
        fDiv /= 2.0;
    }

    int iExp = 0;

    float fDecimalPart = fAbsValue - fIntPart;
    string sFloatBinary;

    int i;

    // Remove the leading "1"
    string sMantissa = GetStringRight(sIntPartBinary,  GetStringLength(sIntPartBinary) - 1);
    while(GetStringLength(sMantissa) < iMantissaSize)
    {
        fDecimalPart *= 2;
        if(fDecimalPart >= 1.0)
        {
            sMantissa += "1";
            fDecimalPart -= 1;
        }
        else
        {
            if(GetStringLength(sMantissa) > 0 || GetStringLength(sIntPartBinary) > 0)
                sMantissa += "0";
            else
                iExp -= 1;
        }
    }

    if(GetStringLength(sIntPartBinary) > 0)
        iExp = GetStringLength(sIntPartBinary) - 1;

    sMantissa = GetStringLeft(sMantissa, iMantissaSize);

    sFloatBinary = IntToString(fValue < 0.0);
    sFloatBinary += (APTS_IntToBinaryString(iExp + iExpOffset, iExpSize) + sMantissa);

    return APTS_BinaryStringToInt(sFloatBinary);
}

float APTS_IntRepToFloat(int iValue, int iSize)
{
    if(iValue == 0)
        return 0.0;
    int iMantissaSize;
    int iExpOffset;
    int iExpSize;
    string sBinaryString;

    if(iSize == 2)
    {
        iMantissaSize = 15;
        iExpOffset = 31;
        iExpSize = 6;
        sBinaryString = APTS_IntToBinaryString(iValue, 22);
        sBinaryString = GetStringRight(sBinaryString, 22);
    }
    else if(iSize == 3)
    {
        iMantissaSize = 23;
        iExpOffset = 127;
        iExpSize = 8;
        sBinaryString = APTS_IntToBinaryString(iValue, 32);
    }
    string sExpPart = GetSubString(sBinaryString, 1, iExpSize);
    string sMantissaPart = GetSubString(sBinaryString, iExpSize+1, iMantissaSize);

    int iExp;
    int iIntPart;
    float fDecPart;
    float fResult;


    iExp = APTS_BinaryStringToInt(sExpPart, FALSE) - iExpOffset;

    if(iExp < iMantissaSize)
    {
        if(iExp >= 0)
        {
            iIntPart = APTS_BinaryStringToInt(GetStringLeft("1" + sMantissaPart, iExp + 1), FALSE);
            sMantissaPart = GetStringRight(sMantissaPart, iMantissaSize - iExp);
        }
        else
        {
            iIntPart = 0;
            int i;
            for(i = 0; i < -iExp; ++i)
            {
                sMantissaPart = "0" + sMantissaPart;
            }
        }

        fDecPart = APTS_BinaryStringToDecimal(APTS_RemoveTrailingZeroes(sMantissaPart));
        fResult = iIntPart + fDecPart;
    }
    else
    {
        iIntPart = 1;
        fDecPart = APTS_BinaryStringToDecimal(APTS_RemoveTrailingZeroes(sMantissaPart));
        fResult = iIntPart + fDecPart;
        fResult *= APTS_Pow(2.0, iExp);
    }
    if(GetStringLeft(sBinaryString, 1) == "1")
        fResult = -fResult;
    return fResult;
}

void APTS_RemoveOldDeclaration(string sVarName)
{
    if(GetLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_TYPE") == APTS_TYPE_BOOL)
    {
        string sBoolName = "boolean" + IntToString(GetLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_SLOT"));
        APTS_RemoveOldDeclaration(sBoolName);
    }

    else if(GetLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_TYPE") == APTS_TYPE_LOCATION)
    {
        string sSlotString = IntToString(GetLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_SLOT"));
        APTS_RemoveOldDeclaration("area_string" + sSlotString);
        APTS_RemoveOldDeclaration("xPos" + sSlotString);
        APTS_RemoveOldDeclaration("yPos" + sSlotString);
        APTS_RemoveOldDeclaration("zPos" + sSlotString);
        APTS_RemoveOldDeclaration("facing" + sSlotString);

    }
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_SLOT");
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_SIZE");
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_SIGNED");
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_BIT");
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_TYPE");
    DeleteLocalInt(GetModule(), "APTS_ITOK_" + sVarName + "_DATA");
}

int APTS_ConvertThreeCharToInt(string sString)
{
    int i;
    string sChar;
    string sIntRep = "";
    int iValue;

    for(i = 0; i < 3; ++i)
    {
        // Gets a single character of the string
        sChar = GetSubString(sString, i, 1);
        if(sChar == "")
            break;
        // Converts the character into an integer by use of a lookup table
        iValue = FindSubString(APTS_CHAR_TABLE, sChar)+1;
        if(iValue < 10)
            sIntRep += "0";
        sIntRep += IntToString(iValue);
    }
    return StringToInt(sIntRep);
}

string APTS_ConvertIntToThreeChar(int iMedValue)
{
    string sResultString = "";
    string sIntRep = IntToString(iMedValue);
    int i;
    int iValue;

    for(i = 0; i < 3; ++i)
    {
        // Only get the first character if the string is odd sized
        if(i == 0 && (GetStringLength(sIntRep)%2 == 1))
        {
            iValue = StringToInt(GetSubString(sIntRep, 0, 1));
        }
        else
            iValue = StringToInt(GetSubString(sIntRep, i*2, 2));

        sResultString += GetSubString(APTS_CHAR_TABLE, iValue-1, 1);
    }
    return sResultString;
}

int APTS_HashAreaTag(string sTag, int iPrimeNum)
{
// Roating hash function
    int iHash, i;
    int iLength = GetStringLength(sTag);
    string sChar;

    iHash = iLength;

    for (i=0; i < iLength; ++i)
    {
        sChar = GetSubString(sTag, i, 1);
        iHash = (iHash<<8)^(iHash>>24)^(FindSubString(APTS_CHAR_TABLE, sChar)+1);
    }
    return (iHash % iPrimeNum);
}


int APTS_HashString(string sString, int iPrimeNum)
{
    return APTS_HashAreaTag(sString, iPrimeNum);

}