Exemplo n.º 1
0
QString RealFormat::doFormat(const Variant& val) const
{
  QString result;
  const LongReal* vr = dynamic_cast<const LongReal*>((const VariantData*)val);
  if (!vr)
    return result;
  if (vr->isNaN())
    return formatNaN();
  if (vr->isZero())
    return formatZero();
  int usedigits = significandbase == base || precision == 0?
                  getDigits() :
                  (precision - 1) / _digitsz(base) + 1;
  RawFloatIO RawFloatIO = vr->convert(usedigits, mode, base);
  if (RawFloatIO.error != Success)
    return result;
  result = getSignificandPrefix(RawFloatIO)
      + formatInt(RawFloatIO)
      + formatFrac(RawFloatIO)
      + getSignificandSuffix(RawFloatIO);
  if (useScale(RawFloatIO))
    result += getScalePrefix(RawFloatIO)
        + formatScale(RawFloatIO)
        + getScaleSuffix(RawFloatIO);
  return result;
}
Exemplo n.º 2
0
void OTTrade::UpdateContents()
{
    // I release this because I'm about to repopulate it.
    m_xmlUnsigned.Release();

    const String NOTARY_ID(GetNotaryID()), NYM_ID(GetSenderNymID()),
        INSTRUMENT_DEFINITION_ID(GetInstrumentDefinitionID()),
        ASSET_ACCT_ID(GetSenderAcctID()), CURRENCY_TYPE_ID(GetCurrencyID()),
        CURRENCY_ACCT_ID(GetCurrencyAcctID());

    Tag tag("trade");

    tag.add_attribute("version", m_strVersion.Get());
    tag.add_attribute("hasActivated", formatBool(hasTradeActivated_));
    tag.add_attribute("notaryID", NOTARY_ID.Get());
    tag.add_attribute("instrumentDefinitionID", INSTRUMENT_DEFINITION_ID.Get());
    tag.add_attribute("assetAcctID", ASSET_ACCT_ID.Get());
    tag.add_attribute("currencyTypeID", CURRENCY_TYPE_ID.Get());
    tag.add_attribute("currencyAcctID", CURRENCY_ACCT_ID.Get());
    tag.add_attribute("nymID", NYM_ID.Get());
    tag.add_attribute("completedNoTrades", formatInt(tradesAlreadyDone_));
    tag.add_attribute("transactionNum", formatLong(m_lTransactionNum));
    tag.add_attribute("creationDate", formatTimestamp(GetCreationDate()));
    tag.add_attribute("validFrom", formatTimestamp(GetValidFrom()));
    tag.add_attribute("validTo", formatTimestamp(GetValidTo()));

    // There are "closing" transaction numbers, used to CLOSE a transaction.
    // Often where Cron items are involved such as this payment plan, or in
    // baskets,
    // where many asset accounts are involved and require receipts to be closed
    // out.

    for (int32_t i = 0; i < GetCountClosingNumbers(); i++) {
        int64_t closingNumber = GetClosingTransactionNoAt(i);
        OT_ASSERT(closingNumber > 0);
        TagPtr tagClosing(new Tag("closingTransactionNumber"));
        tagClosing->add_attribute("value", formatLong(closingNumber));
        tag.add_tag(tagClosing);
    }

    if (('<' == stopSign_) || ('>' == stopSign_)) {
        TagPtr tagStopOrder(new Tag("stopOrder"));
        tagStopOrder->add_attribute("hasActivated", formatBool(stopActivated_));
        tagStopOrder->add_attribute("sign", formatChar(stopSign_));
        tagStopOrder->add_attribute("price", formatLong(stopPrice_));
        tag.add_tag(tagStopOrder);
    }

    if (marketOffer_.Exists()) {
        OTASCIIArmor ascOffer(marketOffer_);
        tag.add_tag("offer", ascOffer.Get());
    }

    std::string str_result;
    tag.output(str_result);

    m_xmlUnsigned.Concatenate("%s", str_result.c_str());
}
Exemplo n.º 3
0
char *getData(){
    
    int totmem = totalMemory();
    char *TOTAL_MEMORY = formatInt(totmem);
    
    float freemem = freeMemory();
    float usedmem = usedMemory();
    char *FREE_MEMORY = formatFloat(freemem);
    char *USED_MEMORY = formatFloat(usedmem);
    
    double loadavg[1];
    getloadavg(loadavg, 1);
    char *CPU_LOAD_AVG = formatDouble(loadavg[0] * 10);
    
    double cpuLoad = getCpuReading();
    char *CPU_LOAD_CURR = formatDouble(cpuLoad);
    
    double cpuTemp = getCpuTemp();
    char *CPU_TEMP = formatDouble(cpuTemp);
    
    char host[40];//cuts username off if more than 40 characters.
    gethostname(host, sizeof(host));
    char HOSTNAME[40] ="|";
    strcat(HOSTNAME,host);
    
    int hostlen = strlen(HOSTNAME);
    for (int s = hostlen; s <40; s++){//fill excess space to prevent overflows.
        strcpy(&HOSTNAME[s], " ");
    }
    
    char *data = new char[75]; //original 35
    strcpy(data,HOSTNAME);
    strcat(data,TOTAL_MEMORY);
    strcat(data,FREE_MEMORY);
    strcat(data,USED_MEMORY);
    strcat(data,CPU_LOAD_AVG);
    strcat(data,CPU_LOAD_CURR);
    strcat(data,CPU_TEMP);
    return data;
}
Exemplo n.º 4
0
UnicodeString &
DigitFormatter::formatPositiveInt32(
        int32_t positiveValue,
        const IntDigitCountRange &range,
        FieldPositionHandler &handler,
        UnicodeString &appendTo) const {
    // super fast path
    if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) {
        int32_t begin = appendTo.length();
        SmallIntFormatter::format(positiveValue, range, appendTo);
        handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length());
        return appendTo;
    }
    uint8_t digits[10];
    int32_t count = formatInt(positiveValue, digits);
    return formatDigits(
            digits,
            count,
            range,
            UNUM_INTEGER_FIELD,
            handler,
            appendTo);
}
Exemplo n.º 5
0
bool Format::format( VMachine *vm, const Item &source, String &target )
{
   String sBuffer;

   switch( source.type() )
   {
      case FLC_ITEM_NIL:
         switch( m_nilFormat )
         {
            case e_nilEmpty: break;
            case e_nilNil: sBuffer = "Nil"; break;
            case e_nilN: sBuffer = "N"; break;
            case e_nilnil: sBuffer = "nil"; break;
            case e_nilNA: sBuffer = "N/A"; break;
            case e_nilNone: sBuffer = "None"; break;
            case e_nilNULL: sBuffer = "NULL"; break;
            case e_nilNull: sBuffer = "Null"; break;
            case e_nilPad: sBuffer.append( m_paddingChr );
         }
         applyPad( sBuffer );

      break;

      case FLC_ITEM_UNB:
         sBuffer = "_";
         applyPad( sBuffer );
         break;


      //==================================================
      // Parse an integer
      //
      case FLC_ITEM_INT:
      {
         int64 num = source.asInteger();

         // number formats are compatible with string formats
         if ( m_convType != e_tNum && m_convType != e_tStr )
         {
            return processMismatch( vm, source, target );
         }

         formatInt( num, sBuffer, true );

         // minus sign must be added AFTER padding with parentesis/fixed size or with *End signs,
         // else it must be added before.
         if ( negBeforePad() )
         {
            applyNeg( sBuffer, num );
            applyPad( sBuffer );
         }
         else {
            applyPad( sBuffer, negPadSize( num ) );
            applyNeg( sBuffer, num );
         }
      }
      break;

      //==================================================
      // Parse double format
      //
      case FLC_ITEM_NUM:
      {
         numeric num = source.asNumeric();

         // number formats are compatible with string formats
         if ( m_convType != e_tNum && m_convType != e_tStr )
         {
            return processMismatch( vm, source, target );
         }

         if( m_numFormat == e_scientific )
         {
           formatScientific( num, sBuffer );
         }
         else {
            double intPart, fractPart;
            bool bNeg, bIntIsZero;
            fractPart = modf( num, &intPart );
            if ( intPart < 0.0 ) {
               intPart = -intPart;
               fractPart = -fractPart;
               bNeg = true;
               bIntIsZero = false;
            }
            else
            {
               bIntIsZero = intPart > 0.0 ? false : true;

               if ( fractPart < 0.0 )
               {
                  fractPart = -fractPart;
                  // draw neg sign only if < 0 but int
                  bNeg = true;
               }
               else
                  bNeg = false;
            }



            String precPart;
            int base = 10;
            switch( m_numFormat )
            {
               case e_binary: case e_binaryB: base = 2; break;
               case e_octalZero: case e_octal: base = 8; break;
               case e_cHexUpper: case e_hexUpper: case e_cHexLower: case e_hexLower: base = 16; break;
               default:
                  break;
            }

            while( intPart > 9e14 )
            {
               intPart /= base;
               precPart.append( '0' );
            }

            // manual round
            if( (pow((double)10.0,-(m_decimals+1)) *5)+fractPart >=1.0)
            {
               intPart++;
               bIntIsZero = false;
            }

            uint8 decs = m_decimals;
            m_decimals = 0;


            formatInt( (int64) intPart, sBuffer, false );
            sBuffer.append( precPart );

            // now we can add the grouping
            if ( m_grouping > 0 )
            {
               String token;
               token.append( m_thousandSep );
               uint32 pos = sBuffer.size();

               while( pos > m_grouping )
               {
                  pos -= m_grouping;
                  sBuffer.insert( pos, 0, token );
               }
            }

            // finally add decimals
            m_decimals = decs;
            if( base == 10 && m_decimals > 0 )
            {

               char bufFmt[32];
               char buffer[255];
               sprintf( bufFmt, "%%.%df", m_decimals );
               sprintf( buffer, bufFmt, fractPart );
               sBuffer.append( m_decimalSep );
               sBuffer.append( buffer + 2 );
            }
            else if ( bIntIsZero )
            {
               // do not print -0!
               bNeg = false;
            }

            // we must fix the number.
            num = bNeg ? -1.0 : 1.0;
         }

         // minus sign must be added AFTER padding with parentesis/fixed size or with *End signs,
         // else it must be added before.
         if ( negBeforePad() )
         {
            applyNeg( sBuffer, (int64) num );
            applyPad( sBuffer );
         }
         else {
            applyPad( sBuffer, negPadSize( (int64) num ) );
            applyNeg( sBuffer, (int64) num );
         }
      }
      break;

      case FLC_ITEM_RANGE:
      {
         // number formats are compatible with string formats
         if ( m_convType != e_tNum && m_convType != e_tStr )
         {
            return processMismatch( vm, source, target );
         }

         int64 begin = source.asRangeStart();
         String sBuf1, sBuf2, sBuf3;

         formatInt( begin, sBuf1, true );

         //apply negative format now.
         applyNeg( sBuf1, (int64) begin );
         if ( ! source.asRangeIsOpen() )
         {
            int64 end = source.asRangeEnd();
            formatInt( end, sBuf2, true );
            applyNeg( sBuf2, (int64) end );
            
            int64 step = source.asRangeStep();
            if ( (begin <= end && step != 1) ||
                 (begin > end && step != -1 ) )
            {
               formatInt( step, sBuf3, true );
               applyNeg( sBuf3, (int64) step );
               sBuffer = "[" + sBuf1 + ":" + sBuf2 + ":" + sBuf3 + "]";
            }
            else
               sBuffer = "[" + sBuf1 + ":" + sBuf2 + "]";
         }
         else
            sBuffer = "[" + sBuf1 + ":" + sBuf2 + "]";

         applyPad( sBuffer );
      }
      break;

      case FLC_ITEM_STRING:
      {
         // number formats are compatible with string formats
         if ( m_convType != e_tStr )
         {
            return processMismatch( vm, source, target );
         }

         sBuffer = *source.asString();
         applyPad( sBuffer );
      }
      break;


      case FLC_ITEM_OBJECT:
      {
         // try to format the object
         if( vm != 0 )
         {
            if( m_posOfObjectFmt != String::npos )
            {
               vm->itemToString( sBuffer, &source, m_originalFormat.subString( m_posOfObjectFmt + 1 ) );
            }
            else {
               vm->itemToString( sBuffer, &source );
            }
         }
         else {
            return processMismatch( vm, source, target );
         }

         applyPad( sBuffer );
      }
      break;

      default:
         return processMismatch( vm, source, target );
   }

   // out of bounds?
   if ( m_size > 0 && m_fixedSize && sBuffer.length() > m_size ) {
      return false;
   }

   target += sBuffer;
   return true;
}
void LeagueOverseer::Event (bz_EventData *eventData)
{
    switch (eventData->eventType)
    {
        case bz_eAllowFlagGrab: // This event is called each time a player attempts to grab a flag
        {
            bz_AllowFlagGrabData_V1* allowFlagGrabData = (bz_AllowFlagGrabData_V1*)eventData;
            std::string              flagAbbr          = allowFlagGrabData->flagType;
            int                      playerID          = allowFlagGrabData->playerID;

            if (isPcProtectionEnabled()) // Is the server configured to protect against Pass Camping
            {
                // Check if the last capture was within the 'PC_PROTECTION_DELAY' amount of seconds
                if (LAST_CAP + getPcProtectionDelay() > bz_getCurrentTime())
                {
                    // Check to see if the flag being grabbed belongs to the team that just had their flag captured AND check
                    // to see if someone not from the victim team grabbed it
                    if ((getTeamTypeFromFlag(flagAbbr) == CAP_VICTIM_TEAM && bz_getPlayerTeam(playerID) != CAP_VICTIM_TEAM))
                    {
                        // Disallow the flag grab if it's being grabbed by an enemy right after a flag capture
                        allowFlagGrabData->allow = false;
                    }
                }
            }
        }
        break;

        case bz_eAllowSpawn: // This event is called before a player respawns
        {
            bz_AllowSpawnData_V2* allowSpawnData = (bz_AllowSpawnData_V2*)eventData;
            int                   playerID       = allowSpawnData->playerID;

            if (!pluginSettings.isGuestSpawningEnabled(getCurrentGameMode()) && !isLeagueMember(playerID))
            {
                // Disable their spawning privileges
                allowSpawnData->handled    = true;
                allowSpawnData->allow      = false;
                allowSpawnData->kickPlayer = false;

                sendPluginMessage(playerID, pluginSettings.getGuestSpawningMessage(getCurrentGameMode()));
            }
        }
        break;

        case bz_eBZDBChange: // This event is called each time a BZDB variable is changed
        {
            bz_BZDBChangeData_V1* bzdbData = (bz_BZDBChangeData_V1*)eventData;

            if (bzdbData->key == "_pcProtectionDelay")
            {
                // Save the proposed value in a variable for easy access
                int proposedValue = std::stoi(bzdbData->value.c_str());

                // Our PC protection delay should be between 3 and 30 seconds only, otherwise set it to the default 5 seconds
                if (proposedValue < 3 || proposedValue > 30)
                {
                    bz_setBZDBInt("_pcProtectionDelay", 5);
                }
            }
        }
        break;

        case bz_eCaptureEvent: // This event is called each time a team's flag has been captured
        {
            if (isMatchInProgress())
            {
                bz_CTFCaptureEventData_V1* captureData = (bz_CTFCaptureEventData_V1*)eventData;
                std::shared_ptr<bz_BasePlayerRecord> capperData(bz_getPlayerByIndex(captureData->playerCapping));

                // Keep score
                (captureData->teamCapping == TEAM_ONE) ? currentMatch.incrementTeamOneScore() : currentMatch.incrementTeamTwoScore();

                // Store data for PC Protection
                CAP_VICTIM_TEAM = captureData->teamCapped;
                CAP_WINNER_TEAM = captureData->teamCapping;
                LAST_CAP        = captureData->eventTime;

                logMessage(pluginSettings.getDebugLevel(), "debug", "%s captured the flag at %s",
                        capperData->callsign.c_str(), getMatchTime().c_str());
                logMessage(pluginSettings.getDebugLevel(), "debug", "Match Score %s [%i] vs %s [%i]",
                        currentMatch.getTeamOneName().c_str(), currentMatch.getTeamOneScore(),
                        currentMatch.getTeamTwoName().c_str(), currentMatch.getTeamTwoScore());

                CaptureMatchEvent capEvent = CaptureMatchEvent().setBZID(capperData->bzID.c_str())
                                                                .setTime(getMatchTime());

                // If it's an official match, save the team ID
                if (isOfficialMatch())
                {
                    int teamID = (captureData->teamCapping == TEAM_ONE) ? currentMatch.getTeamOneID() : currentMatch.getTeamTwoID();

                    capEvent.setTeamID(teamID);
                }

                capEvent.save();

                currentMatch.saveEvent(capEvent.getJsonObject());
                currentMatch.stats_flagCapture(captureData->playerCapping);

                logMessage(pluginSettings.getVerboseLevel(), "debug", "CaptureMatchEvent JSON -> %s", capEvent.toString());
            }
        }
        break;

        case bz_eGameEndEvent: // This event is called each time a game ends
        {
            logMessage(pluginSettings.getVerboseLevel(), "debug", "A match has ended.");

            // Get the current standard UTC time
            bz_Time stdTime;
            bz_getUTCtime(&stdTime);
            std::string recordingFileName;

            // Only save the recording buffer if we actually started recording when the match started
            if (RECORDING)
            {
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Recording was in progress during the match.");

                std::stringstream recordingName;

                std::string _matchType = (isOfficialMatch()) ? "offi" : "fm",
                            _teamOneName = currentMatch.getTeamOneName(),
                            _teamTwoName = currentMatch.getTeamTwoName();

                // (offi|fm)-YYYYMMDD
                recordingName << _matchType << "-" << stdTime.year << formatInt("%02d", stdTime.month) << formatInt("%02d", stdTime.day);

                if (!currentMatch.isRosterEmpty())
                {
                    std::replace(_teamOneName.begin(), _teamOneName.end(), ' ', '_');
                    std::replace(_teamTwoName.begin(), _teamTwoName.end(), ' ', '_');

                    // Team_A-vs-Team_B
                    recordingName << "-" << _teamOneName << "-vs-" << _teamTwoName;
                }

                // -HHMM
                recordingName << "-" << formatInt("%02d", stdTime.hour) << formatInt("%02d", stdTime.minute);

                const std::string nameForHash = recordingName.str();
                std::string hash = bz_MD5(nameForHash.c_str());

                // -ACBD123
                recordingName << "-" << hash.substr(0, 7);

                if (currentMatch.matchCanceled())
                {
                    // -Canceled
                    recordingName << "-Canceled";
                }

                recordingName << ".rec";

                recordingFileName = recordingName.str();
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Replay file will be named: %s", recordingFileName.c_str());

                // Save the recording buffer and stop recording
                bz_saveRecBuf(recordingFileName.c_str(), 0);
                bz_stopRecBuf();
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Replay file has been saved and recording has stopped.");

                // We're no longer recording, so set the boolean and announce to players that the file has been saved
                RECORDING = false;
                bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "Match saved as: %s", recordingFileName.c_str());
            }

            // Format the date to -> year-month-day hour:minute:second
            char matchDate[20];
            sprintf(matchDate, "%02d-%02d-%02d %02d:%02d:%02d", stdTime.year, stdTime.month, stdTime.day, stdTime.hour, stdTime.minute, stdTime.second);

            currentMatch.save(matchDate, recordingFileName);

            if (pluginSettings.isMatchReportEnabled())
            {
                if (!currentMatch.isRosterEmpty())
                {
                    MatchUrlRepo.set("query", "matchReport")
                                .set("data", bz_urlEncode(currentMatch.toString().c_str()))
                                .submit();

                    if (currentMatch.isFM())
                    {
                        // It was a fun match, so there is no need to do anything

                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Fun match has completed.");
                    }
                    else if (currentMatch.matchCanceled())
                    {
                        // The match was canceled for some reason so output the reason to both the players and the server logs

                        logMessage(pluginSettings.getDebugLevel(), "debug", "%s", currentMatch.getCancelation().c_str());
                        bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, currentMatch.getCancelation().c_str());
                    }
                    else
                    {
                        logMessage(pluginSettings.getDebugLevel(), "debug", "Reporting match data...");
                        bz_sendTextMessage(BZ_SERVER, BZ_ALLUSERS, "Reporting match...");

                        // Send the match data to the league website
                        MATCH_INFO_SENT = true;
                    }
                }
            }

            // Reset our match data
            currentMatch = Match();

            // Empty our list of players since we don't need a history
            activePlayerList.clear();
        }
        break;

        case bz_eGamePauseEvent:
        {
            bz_GamePauseResumeEventData_V2* gamePauseData = (bz_GamePauseResumeEventData_V2*)eventData;

            // Get the current UTC time
            MATCH_PAUSED = time(NULL);

            // Send the messages
            bz_sendTextMessagef(BZ_SERVER, BZ_ALLUSERS, "    with %s remaining.", getMatchTime().c_str());
            logMessage(pluginSettings.getVerboseLevel(), "debug", "Match paused at %s by %s.", getMatchTime().c_str(), bz_getPlayerCallsign(gamePauseData->playerID));

            PauseResumeMatchEvent pauseEvent = PauseResumeMatchEvent();

            pauseEvent.setState(true)
                      .setTime(getMatchTime())
                      .setBZID(getPlayerBZID(gamePauseData->playerID))
                      .save();

            currentMatch.saveEvent(pauseEvent.getJsonObject());

            logMessage(pluginSettings.getVerboseLevel(), "debug", "PauseResumeMatchEvent JSON -> %s", pauseEvent.toString());
        }
        break;

        case bz_eGameResumeEvent:
        {
            bz_GamePauseResumeEventData_V2* gameResumeData = (bz_GamePauseResumeEventData_V2*)eventData;

            // Get the current UTC time
            time_t now = time(NULL);

            // Do the math to determine how long the match was paused
            double timePaused = difftime(now, MATCH_PAUSED);

            // Create a temporary variable to store and manipulate the match start time
            struct tm modMatchStart = *localtime(&MATCH_START);

            // Manipulate the time by adding the amount of seconds the match was paused in order to be able to accurately
            // calculate the amount of time remaining with LeagueOverseer::getMatchTime()
            modMatchStart.tm_sec += timePaused;

            // Save the manipulated match start time
            MATCH_START = mktime(&modMatchStart);
            logMessage(pluginSettings.getVerboseLevel(), "debug", "Match paused for %.f seconds. Match continuing at %s.", timePaused, getMatchTime().c_str());

            PauseResumeMatchEvent resumeEvent = PauseResumeMatchEvent();

            resumeEvent.setState(false)
                       .setTime(getMatchTime())
                       .setBZID(getPlayerBZID(gameResumeData->playerID))
                       .save();

            currentMatch.saveEvent(resumeEvent.getJsonObject());

            logMessage(pluginSettings.getVerboseLevel(), "debug", "PauseResumeMatchEvent JSON -> %s", resumeEvent.toString());
        }
        break;

        case bz_eGameStartEvent: // This event is triggered when a timed game begins
        {
            logMessage(pluginSettings.getVerboseLevel(), "debug", "A match has started");

            // Empty our list of players since we don't need a history
            activePlayerList.clear();

            // We started recording a match, so save the status
            RECORDING = bz_startRecBuf();

            // We want to notify the logs if we couldn't start recording just in case an issue were to occur and the server
            // owner needs to check to see if players were lying about there no replay
            if (RECORDING)
            {
                logMessage(pluginSettings.getVerboseLevel(), "debug", "Match recording has started successfully");
            }
            else
            {
                logMessage(0, "error", "This match could not be recorded");
            }

            currentMatch.setMatchDuration((int) bz_getTimeLimit());

            MATCH_START = time(NULL);
        }
        break;

        case bz_eGetAutoTeamEvent: // This event is called for each new player is added to a team
        {
            bz_GetAutoTeamEventData_V1* autoTeamData = (bz_GetAutoTeamEventData_V1*)eventData;

            int playerID = autoTeamData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            // Only force new players to observer if a match is in progress
            if (isMatchInProgress())
            {
                // Automatically move non-league members or players who just joined to the observer team
                if (!isLeagueMember(playerID) || !playerAlreadyJoined(playerData->bzID.c_str()))
                {
                    autoTeamData->handled = true;
                    autoTeamData->team    = eObservers;
                }
            }
        }
        break;

        case bz_eGetPlayerMotto: // This event is called when the player joins. It gives us the motto of the player
        {
            bz_GetPlayerMottoData_V2* mottoData = (bz_GetPlayerMottoData_V2*)eventData;

            if (pluginSettings.isMottoFetchEnabled())
            {
                std::map<std::string, std::string> parameters;

                parameters["{motto}"] = mottoData->motto;
                parameters["{team}"]  = getPlayerTeamNameByBZID(mottoData->record->bzID.c_str());

                mottoData->motto = formatMotto(parameters);
            }
        }
        break;

        case bz_ePlayerDieEvent: // This event is called each time a tank is killed
        {
            bz_PlayerDieEventData_V1* dieData = (bz_PlayerDieEventData_V1*)eventData;
            std::shared_ptr<bz_BasePlayerRecord> victimData(bz_getPlayerByIndex(dieData->playerID));
            std::shared_ptr<bz_BasePlayerRecord> killerData(bz_getPlayerByIndex(dieData->killerID));

            if (isMatchInProgress())
            {
                KillMatchEvent killEvent = KillMatchEvent();

                killEvent.setKiller(killerData->bzID.c_str())
                         .setVictim(victimData->bzID.c_str())
                         .setTime(getMatchTime())
                         .save();

                currentMatch.saveEvent(killEvent.getJsonObject());

                logMessage(pluginSettings.getVerboseLevel(), "debug", "KillMatchEvent JSON -> %s", killEvent.toString());
            }
        }
        break;

        case bz_ePlayerJoinEvent: // This event is called each time a player joins the game
        {
            bz_PlayerJoinPartEventData_V1* joinData = (bz_PlayerJoinPartEventData_V1*)eventData;

            int playerID = joinData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            setLeagueMember(playerID);
            storePlayerInfo(playerID, playerData->bzID.c_str());

            JoinMatchEvent joinEvent = JoinMatchEvent().setCallsign(playerData->callsign.c_str())
                                                       .setVerified(playerData->verified)
                                                       .setIpAddress(playerData->ipAddress.c_str())
                                                       .setBZID(playerData->bzID.c_str());
            joinEvent.save();

            // Only notify a player if they exist, have joined the observer team, and there is a match in progress
            if (isMatchInProgress() && isValidPlayerID(joinData->playerID) && playerData->team == eObservers)
            {
                bz_sendTextMessagef(BZ_SERVER, joinData->playerID, "*** There is currently %s match in progress, please be respectful. ***",
                                    ((isOfficialMatch()) ? "an official" : "a fun"));
            }

            if (pluginSettings.isMottoFetchEnabled())
            {
                // Only send a URL job if the user is verified
                if (playerData->verified)
                {
                    requestTeamName(playerData->callsign.c_str(), playerData->bzID.c_str());
                }
            }
        }
        break;

        case bz_ePlayerPartEvent: // This event is called each time a player leaves a game
        {
            bz_PlayerJoinPartEventData_V1* partData = (bz_PlayerJoinPartEventData_V1*)eventData;

            int playerID = partData->playerID;
            std::shared_ptr<bz_BasePlayerRecord> playerData(bz_getPlayerByIndex(playerID));

            removePlayerInfo(partData->record->bzID.c_str());

            // Only keep track of the parting player if they are a league member and there is a match in progress
            if (isLeagueMember(playerID) && isMatchInProgress())
            {
                if (!playerAlreadyJoined(playerData->bzID.c_str()))
                {
                    // Create a record for the player who just left
                    Player partingPlayer(playerData->bzID.c_str(), playerData->team, bz_getCurrentTime());

                    // Push the record to our vector
                    activePlayerList.push_back(partingPlayer);
                }
            }
        }
        break;

        case bz_eRawChatMessageEvent: // This event is called for each chat message the server receives. It is called before any filtering is done.
        {
            bz_ChatEventData_V1* chatData  = (bz_ChatEventData_V1*)eventData;

            bz_eTeamType target    = chatData->team;
            int          playerID  = chatData->from,
                         recipient = chatData->to;

            // The server is always allowed to talk
            if (playerID == BZ_SERVER)
            {
                break;
            }

            // A non-league player is attempting to talk
            if (!isLeagueMember(playerID))
            {
                std::string allowedChatTarget = pluginSettings.getAllowedTargetChat(getCurrentGameMode());
                bool ignoreMessage = true;

                if (allowedChatTarget == "Observers")
                {
                    if (recipient == eObservers || bz_getPlayerTeam(recipient) == eObservers)
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "ObvserverAdmins")
                {
                    if (bz_getPlayerTeam(recipient) == eObservers && isVisibleAdmin(recipient))
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "Admins")
                {
                    if (target == eAdministrators || isVisibleAdmin(recipient))
                    {
                        ignoreMessage = false;
                    }
                }
                else if (allowedChatTarget == "All")
                {
                    ignoreMessage = false;
                }

                if (ignoreMessage)
                {
                    chatData->message = "";
                    sendPluginMessage(playerID, pluginSettings.getGuestMessagingMessage(getCurrentGameMode()));
                }
            }
        }
        break;

        case bz_eTickEvent: // This event is called once for each BZFS main loop
        {
            // Get the total number of tanks playing
            int totalTanks = bz_getTeamCount(eRedTeam) + bz_getTeamCount(eGreenTeam) + bz_getTeamCount(eBlueTeam) + bz_getTeamCount(ePurpleTeam);

            // If there are no tanks playing, then we need to do some clean up
            if (totalTanks == 0)
            {
                // If there is an official match and no tanks playing, we need to cancel it
                if (isOfficialMatch())
                {
                    currentMatch.cancelMatch("Official match automatically canceled due to all players leaving the match.");
                }

                // If we have players recorded and there's no one around, empty the list
                if (!activePlayerList.empty())
                {
                    activePlayerList.clear();
                }

                // If there is a countdown active an no tanks are playing, then cancel it
                if (bz_isCountDownActive())
                {
                    bz_gameOver(253, eObservers);
                    logMessage(pluginSettings.getVerboseLevel(), "debug", "Game ended because no players were found playing with an active countdown.");
                }
            }

            // Let's get the roll call only if there is an official match
            if (isOfficialMatch())
            {
                // Check if the start time is not negative since our default value for the approxTimeProgress is -1. Also check
                // if it's time to do a roll call, which is defined as 90 seconds after the start of the match by default,
                // and make sure we don't have any match participants recorded and the match isn't paused
                if (getMatchProgress() > currentMatch.getMatchRollCall() && currentMatch.isRosterEmpty() &&
                    !bz_isCountDownPaused() && !bz_isCountDownInProgress())
                {
                    logMessage(pluginSettings.getVerboseLevel(), "debug", "Processing roll call...");

                    // @TODO Make sure all of these variables are used
                    std::shared_ptr<bz_APIIntList> playerList(bz_getPlayerIndexList());
                    bool invalidateRollCall, teamOneError, teamTwoError;
                    std::string teamOneMotto, teamTwoMotto;
                    int teamOneID, teamTwoID;

                    invalidateRollCall = teamOneError = teamTwoError = false;
                    teamOneMotto = teamTwoMotto = "";

                    // We can't do a roll call if the player list wasn't created
                    if (!playerList)
                    {
                        logMessage(pluginSettings.getVerboseLevel(), "error", "Failure to create player list for roll call.");
                        return;
                    }

                    for (unsigned int i = 0; i < playerList->size(); i++)
                    {
                        bz_BasePlayerRecord* playerRecord = bz_getPlayerByIndex(playerList->get(i));

                        if (playerRecord && isLeagueMember(playerRecord->playerID) && bz_getPlayerTeam(playerList->get(i)) != eObservers) // If player is not an observer
                        {
                            currentMatch.savePlayer(playerRecord, getTeamIdFromBZID(playerRecord->bzID.c_str()));

                            // @TODO Rewrite this function to be updated
                            // Check if there is any need to invalidate a roll call from a team
                            //validateTeamName(invalidateRollCall, teamOneError, currentPlayer, teamOneMotto, TEAM_ONE);
                            //validateTeamName(invalidateRollCall, teamTwoError, currentPlayer, teamTwoMotto, TEAM_TWO);
                        }

                        bz_freePlayerRecord(playerRecord);
                    }

                    // We were asked to invalidate the roll call because of some issue so let's check if there is still time for
                    // another roll call
                    if (invalidateRollCall && currentMatch.incrementMatchRollCall(60) < currentMatch.getMatchDuration())
                    {
                        logMessage(pluginSettings.getDebugLevel(), "debug", "Invalid player found on field at %s.", getMatchTime().c_str());

                        // There was an error with one of the members of either team, so request a team name update for all of
                        // the team members to try to fix any inconsistencies of different team names
                        //if (teamOneError) { requestTeamName(TEAM_ONE); }
                        //if (teamTwoError) { requestTeamName(TEAM_TWO); }

                        // Delay the next roll call by 60 seconds
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Match roll call time has been delayed by 60 seconds.");

                        // Clear the struct because it's useless data
                        currentMatch.clearPlayerRoster();
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Match participants have been cleared.");
                    }

                    // There is no need to invalidate the roll call so the team names must be right so save them in the struct
                    if (!invalidateRollCall)
                    {
                        currentMatch.setTeamOneID(teamOneID).setTeamOneName(teamOneMotto)
                                    .setTeamTwoID(teamTwoID).setTeamTwoName(teamTwoMotto);

                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Team One set to: %s", currentMatch.getTeamOneName().c_str());
                        logMessage(pluginSettings.getVerboseLevel(), "debug", "Team Two set to: %s", currentMatch.getTeamTwoName().c_str());
                    }
                }
            }
        }
        break;

        default: break;
    }
}