diff --git a/AKAListEntry.cpp b/AKAListEntry.cpp new file mode 100644 index 0000000..e84d5b2 --- /dev/null +++ b/AKAListEntry.cpp @@ -0,0 +1,72 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "AKAListEntry.h" +#include "GlobalStatistics.h" + +AKAListEntry::AKAListEntry() +{ +} + +AKAListEntry::~AKAListEntry() +{ +} + +wxString AKAListEntry::SQLTableName() +{ + wxString tableName="akadata"; + + return (tableName); +} + +wxString AKAListEntry::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "playerindex integer," + "%s" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("name","akaname",FIELD_WIDTH_PLAYER_NAME).GetData() + ); + + return SQL; +} + +bool AKAListEntry::WriteToDatabase() +{ + wxString SQL; + bool retVal=true; + int actualPlayerIndex; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + actualPlayerIndex=player.actualPlayerIndex; + + if (actualPlayerIndex +#include +#include +#include + +// Statsgen Includes + +class AKAListEntry; + +WX_DECLARE_OBJARRAY(AKAListEntry,ArrayOfAKAListEntry); +class AKAListEntry +{ + public: + AKAListEntry(); + ~AKAListEntry(); + int playerIndex; + wxString name; + + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(); +}; + + +#endif diff --git a/ActionData.cpp b/ActionData.cpp new file mode 100644 index 0000000..2523e40 --- /dev/null +++ b/ActionData.cpp @@ -0,0 +1,64 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "ActionData.h" +#include "GlobalStatistics.h" + +ActionData::ActionData() +{ +} + +ActionData::~ActionData() +{ +} + +wxString ActionData::SQLTableName() +{ + wxString tableName="actiondata"; + + return (tableName); +} + +wxString ActionData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "actionidx integer," + "playerindex integer," + "playerclass integer," + "playerteam integer," + "action integer" + ")", + SQLTableName().GetData()); + + return SQL; +} + +bool ActionData::WriteToDatabase(int roundIndex,int itemIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + + SQL.Printf("Insert into %s" + "(roundindex,actionidx,playerindex,playerclass,playerteam,action)" + "values('%d','%d','%d','%d','%d','%d')", + SQLTableName().GetData(), + roundIndex, + itemIndex, + player.actualPlayerIndex, + playerClass, + playerTeam, + action); + + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} diff --git a/ActionData.h b/ActionData.h new file mode 100644 index 0000000..0e1bd7e --- /dev/null +++ b/ActionData.h @@ -0,0 +1,34 @@ +#ifndef __ACTIONDATA +#define __ACTIONDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class ActionData; + +WX_DECLARE_OBJARRAY(ActionData,ArrayOfActionData); +class ActionData +{ + public: + ActionData(); + virtual ~ActionData(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int itemIndex); + + wxDateTime actionTime; + int gameType; + int mapName; + int playerIndex; + int playerClass; + int playerTeam; + int action; + +}; + + +#endif diff --git a/AliasCacheEntry.cpp b/AliasCacheEntry.cpp new file mode 100644 index 0000000..63b964b --- /dev/null +++ b/AliasCacheEntry.cpp @@ -0,0 +1,23 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "AliasCacheEntry.h" + +int AliasCacheEntry::Compare(AliasCacheEntry *item1,AliasCacheEntry *item2) +{ + int guidResult; + int retVal; + + guidResult=item1->guid.Cmp(item2->guid); + if (guidResult==0) + { + retVal=item1->name.Cmp(item2->name); + } + else + { + retVal=guidResult; + } + return (retVal); +} diff --git a/AliasCacheEntry.h b/AliasCacheEntry.h new file mode 100644 index 0000000..5295cca --- /dev/null +++ b/AliasCacheEntry.h @@ -0,0 +1,23 @@ +#ifndef __ALIASCACHEENTRY +#define __ALIASCACHEENTRY + +// wxWindows includes +#include +#include +#include +#include + +class AliasCacheEntry; + +WX_DEFINE_SORTED_ARRAY(AliasCacheEntry *,ArrayOfAliasCacheEntry); +class ArrayOfAliasCacheEntry; +class AliasCacheEntry +{ + public: + static int Compare(AliasCacheEntry *item1,AliasCacheEntry *item2); + wxString name; + wxString guid; + int index; +}; + +#endif diff --git a/AliasDialog.cpp b/AliasDialog.cpp new file mode 100644 index 0000000..eafff3b --- /dev/null +++ b/AliasDialog.cpp @@ -0,0 +1,152 @@ +// Statsgen Includes +#include "AliasDialog.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(AliasDialog, GenericOKCancelDialog) + EVT_BUTTON(WINDOW_ID_BUTTON_AUTO,AliasDialog::OnAuto) +END_EVENT_TABLE() + +AliasDialog::AliasDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) : GenericOKCancelDialog + (parent, + id, + title, + pos, + size, + style, + name) +{ + panel=new AliasEditorPanel(); + panel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); +} + +bool AliasDialog::DisplayDialog() +{ + return (GenericOKCancelDialog::DisplayDialog((wxPanel *)panel)); +} + +AliasDialog::~AliasDialog() +{ +} + +void AliasDialog::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxSizeEvent event; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + + STATSGEN_DEBUG_FUNCTION_START("AliasDialog","CreateDialog") + autoButton.Create(this, + WINDOW_ID_BUTTON_AUTO, + _T(WINDOW_ID_BUTTON_AUTO_TEXT), + wxDefaultPosition); + GenericOKCancelDialog::CreateDialog(); + //OnResize(event); + STATSGEN_DEBUG_FUNCTION_END +} + +void AliasDialog::OnResize(wxSizeEvent &event) +{ + wxString msg; + int saveWidth; + wxSize itemSize; + + wxPoint itemPosition; + STATSGEN_DEBUG_FUNCTION_START("AliasDialog","OnResize") + + GenericOKCancelDialog::OnResize(event); + + STATSGEN_DEBUG(DEBUG_ALWAYS,"Generic Resize Done") + // Auto button + itemSize=quitButton.GetSize(); + itemPosition=quitButton.GetPosition(); + itemPosition.x+=(itemSize.GetWidth()+BUTTON_WIDTH_GAP); + STATSGEN_DEBUG_CODE(msg.Printf("AUTO POSITION X=[%d] Y=[%d]",itemPosition.x,itemPosition.y);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + itemSize=autoButton.GetSize(); + STATSGEN_DEBUG_CODE(msg.Printf("AUTO SIZE=[%d] HEIGHT=[%d]",itemSize.GetWidth(),itemSize.GetWidth());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + autoButton.SetPosition(itemPosition); + + STATSGEN_DEBUG_FUNCTION_END +} + +void AliasDialog::OnAuto(wxCommandEvent &event) +{ + wxString msg; + wxArrayInt shownPlayers; + PlayerCacheEntry cacheEntry; + int cacheIndex; + int shownIndex; + int shownCount; + ArrayOfPlayerCacheEntry shownPlayerCache; + wxString parentGUID; + wxString parentName; + wxString childGUID; + wxString childName; + AliasListEntry aliasEntry; + + panel->GetShownPlayers(shownPlayers); + shownCount=shownPlayers.GetCount(); + for (shownIndex=0;shownIndexRefreshAliasTree(); + // TEMP FOR TEST + //globalStatistics.WriteAliasList(); + //globalStatistics.configData.CommitChanges(); + // TEMP FOR TEST + +} + +void AliasDialog::OnSave(wxCommandEvent &event) +{ + wxString msg; + + // Write the Alias List to disk + globalStatistics.WriteAliasList(); + // Do any standard Save + GenericOKCancelDialog::OnSave(event); +} + diff --git a/AliasDialog.h b/AliasDialog.h new file mode 100644 index 0000000..7e44f1d --- /dev/null +++ b/AliasDialog.h @@ -0,0 +1,39 @@ +#ifndef __ALIASDIALOG +#define __ALIASDIALOG + +#include +#include + +// Statsgen Includes +#include "GenericOKCancelDialog.h" +#include "AliasEditorPanel.h" +#include "WindowIDs.h" + +class AliasDialog : public GenericOKCancelDialog +{ + public: + AliasDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + + virtual ~AliasDialog(); + + virtual void OnResize(wxSizeEvent& event); + virtual void OnAuto(wxCommandEvent& event); + virtual void OnSave(wxCommandEvent& event); + virtual void CreateDialog(); + virtual bool DisplayDialog(); + + protected: + + private: + AliasEditorPanel *panel; + wxButton autoButton; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/AliasEditorPanel.cpp b/AliasEditorPanel.cpp new file mode 100644 index 0000000..bf51655 --- /dev/null +++ b/AliasEditorPanel.cpp @@ -0,0 +1,512 @@ +// wx includes +#include +#include +#include +#include + +// Statsgen Includes +#include "AliasEditorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(AliasEditorPanel, wxPanel) + EVT_SIZE(AliasEditorPanel::OnResize) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_ALIASTREE, + AliasEditorPanel::OnAliasRightClick) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_PLAYERCACHE, + AliasEditorPanel::OnPlayerRightClick) + EVT_MENU(ALIAS_POPUP_DELETE_PARENT,AliasEditorPanel::OnPopupMenu) + EVT_MENU(ALIAS_POPUP_DELETE_CHILD,AliasEditorPanel::OnPopupMenu) + EVT_MENU(ALIAS_POPUP_REPARENT,AliasEditorPanel::OnPopupMenu) + EVT_MENU(PLAYER_POPUP_NEW_ALIAS,AliasEditorPanel::OnPopupMenu) + EVT_MENU(PLAYER_POPUP_ADD_ALIAS,AliasEditorPanel::OnPopupMenu) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,AliasEditorPanel::OnTextChange) +END_EVENT_TABLE() + +AliasEditorPanel::AliasEditorPanel() +{ + playerCache=NULL; + aliasList=NULL; + + // Lets load up the current Alias List into + // the global statistics - we can transfer + // it across into the tree during creation + globalStatistics.ReadAliasList(); +} + +bool AliasEditorPanel::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + wxString dummyConfigKey="/tmp/tmp"; + wxString labelText="Player Filter"; + long treeCtrlStyle=wxTR_HAS_BUTTONS; + wxString configKey; + +wxPanel::Create( parent, id, + pos, + size, + style, + name); + playerCache=new PlayerCachePanel(dummyConfigKey,labelText); + playerCache->SetFilterType(PlayerCachePanel::FILTER_TYPE_NO_CASE); + playerCache->Create(this, + WINDOW_ID_PLAYERCACHE, + wxDefaultPosition, + wxDefaultSize); + aliasList=new wxTreeCtrl(this, + WINDOW_ID_ALIASTREE, + wxDefaultPosition, + wxDefaultSize, + treeCtrlStyle, + wxDefaultValidator); + aliasConfigs=new GroupedConfigItemsPanel("Alias"); + aliasConfigs->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE,wxDefaultPosition,wxDefaultSize); + configKey=globalStatistics.AutomaticAliasConfigKey(); + aliasConfigs->AddBoolean("Use Automatic Aliasing During Log Processing", + configKey, + false); + configKey="/tmp/aliasfilter"; + aliasConfigs->Add("Alias List Player Filter", + configKey, + "", + -1); + playerCache->SetFilterCallBack(FilterNameCallBack); + RefreshAliasTree(); + + return (true); +} + +void AliasEditorPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int playerCacheWidth; + int playerCacheHeight; + int panelWidth; + int panelHeight; + int aliasWidth; + int aliasHeight; + int aliasConfigsHeight; + int aliasConfigsWidth; + wxString msg; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + playerCacheWidth=(panelWidth*3)/5; + playerCacheHeight=panelHeight; + aliasWidth=panelWidth-playerCacheWidth; + aliasHeight=panelHeight; + + if (aliasList!=NULL) + { + aliasConfigsHeight=20; + aliasConfigsWidth=panelWidth; + aliasConfigs->SetSize(0,0,aliasConfigsWidth,aliasConfigsHeight); + itemSize=aliasConfigs->GetSize(); + aliasConfigsHeight=itemSize.GetHeight()+20; + aliasConfigsHeight=aliasConfigs->PreferredHeight(); + aliasHeight-=aliasConfigsHeight; + playerCacheHeight-=aliasConfigsHeight; + aliasConfigs->SetSize(0,0,aliasConfigsWidth,aliasConfigsHeight); + aliasList->SetSize(0,aliasConfigsHeight,aliasWidth,aliasHeight); + playerCache->SetSize(aliasWidth,aliasConfigsHeight,playerCacheWidth,playerCacheHeight); + } + +} + +wxTreeItemId AliasEditorPanel::AddPlayerToTree( + wxTreeItemId &parentItem, + wxString &guid, + wxString &name) +{ + wxString playerString; + wxString foundPlayerString; + wxTreeItemId childItem; + wxTreeItemIdValue cookie; + bool found=false; + + playerString.Printf("(%s) %s", + guid.GetData(), + name.GetData()); + + found=false; + + childItem=aliasList->GetFirstChild(parentItem,cookie); + while (childItem.IsOk()) + { + foundPlayerString=aliasList->GetItemText(childItem); + if (foundPlayerString.Cmp(playerString)==0) + { + found=true; + break; + } + childItem=aliasList->GetNextChild(parentItem,cookie); + } + if (!found) + { + childItem=aliasList->AppendItem(parentItem,playerString); + } + + return (childItem); +} + +void AliasEditorPanel::AddAlias(AliasListEntry &aliasEntry) +{ + wxTreeItemId rootItem; + wxTreeItemId parentItem; + wxTreeItemId childItem; + + rootItem=aliasList->GetRootItem(); + parentItem=AddPlayerToTree( rootItem, + aliasEntry.primaryGUID, + aliasEntry.primaryName); + childItem=AddPlayerToTree( parentItem, + aliasEntry.aliasGUID, + aliasEntry.aliasName); + aliasList->Expand(rootItem); +} + +void AliasEditorPanel::RefreshAliasTree() +{ + AliasListEntry aliasEntry; + int aliasCount; + int aliasIndex; + wxTreeItemId rootItem; + wxString rootText="Alias List"; + wxString decolouredAlias; + wxString decolouredName; + bool dontFilter; + + aliasList->Hide(); + aliasList->DeleteAllItems(); + + rootItem=aliasList->AddRoot(rootText); + aliasCount=globalStatistics.aliasList.GetCount(); + for (aliasIndex=0;aliasIndex0) + { + dontFilter=((decolouredAlias.Find(aliasFilter)>=0) || + (decolouredName.Find(aliasFilter)>=0)); + + } + if (dontFilter) + { + AddAlias(aliasEntry); + } + } + aliasList->Expand(rootItem); + aliasList->Show(); +} + +void AliasEditorPanel::GetShownPlayers(wxArrayInt &shownPlayers) +{ + playerCache->GetShownPlayers(shownPlayers); +} + +void AliasEditorPanel::OnAliasRightClick(wxTreeEvent &event) +{ + wxString msg; + wxTreeItemId rootItem; + wxTreeItemId parentItem; + wxTreeItemId clickedItem; + wxMenu popupMenu(_T("")); + wxString menuItem; + wxString parentString; + wxString childString; + + // What have we right clicked on - parent or child? + rootItem=aliasList->GetRootItem(); + clickedItem=event.GetItem(); + if (clickedItem!=rootItem) + { + parentItem=aliasList->GetItemParent(clickedItem); + if (parentItem==rootItem) + { + parentString=aliasList->GetItemText(clickedItem); + // Clicked on a parent + menuItem="Delete All Alias Entries for "+parentString; + popupMenu.Append(ALIAS_POPUP_DELETE_PARENT,menuItem); + } + else + { + // Clicked on a child + childString=aliasList->GetItemText(clickedItem); + parentString=aliasList->GetItemText(parentItem); + menuItem="Delete Alias Entry "+childString; + popupMenu.Append(ALIAS_POPUP_DELETE_CHILD,menuItem); + menuItem="Make "+childString+" the new parent"; + popupMenu.Append(ALIAS_POPUP_REPARENT,menuItem); + } + popupMenu.Append(ALIAS_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); + } +} + +void AliasEditorPanel::OnPlayerRightClick(wxListEvent &event) +{ + wxString msg; + wxString menuItem; + wxMenu popupMenu(_T("")); + + // Right clicked on an item in the Player Cache + menuItem="Create New Alias"; + popupMenu.Append(PLAYER_POPUP_NEW_ALIAS,menuItem); + menuItem="Add To Alias"; + popupMenu.Append(PLAYER_POPUP_ADD_ALIAS,menuItem); + popupMenu.Append(ALIAS_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void AliasEditorPanel::AliasItemSplit(wxTreeItemId &treeItem,AliasListEntry &aliasEntry) +{ + wxString combinedText; + wxTreeItemId rootItem; + wxTreeItemId parentItem; + wxTreeItemId childItem; + wxString guid; + + rootItem=aliasList->GetRootItem(); + parentItem=aliasList->GetItemParent(treeItem); + if (parentItem!=rootItem) + { + childItem=treeItem; + } + else + { + parentItem=treeItem; + } + + if (childItem.IsOk()) + { + combinedText=aliasList->GetItemText(childItem); + aliasEntry.aliasGUID=combinedText.BeforeFirst(' '); + aliasEntry.aliasGUID=aliasEntry.aliasGUID.AfterFirst('('); + aliasEntry.aliasGUID=aliasEntry.aliasGUID.BeforeLast(')'); + aliasEntry.aliasName=combinedText.AfterFirst(' '); + } + if (parentItem.IsOk()) + { + combinedText=aliasList->GetItemText(parentItem); + aliasEntry.primaryGUID=combinedText.BeforeFirst(' '); + aliasEntry.primaryGUID=aliasEntry.primaryGUID.AfterFirst('('); + aliasEntry.primaryGUID=aliasEntry.primaryGUID.BeforeLast(')'); + aliasEntry.primaryName=combinedText.AfterFirst(' '); + } +} + +void AliasEditorPanel::DeleteAlias(wxTreeItemId &parentItem, + wxTreeItemId &childItem) +{ + int childCount; + AliasListEntry aliasEntry; + wxString msg; + + AliasItemSplit(childItem,aliasEntry); + + aliasList->Delete(childItem); + childCount=aliasList->GetChildrenCount(parentItem); + if (childCount==0) + { + // No children - so delete parent + aliasList->Delete(parentItem); + } + globalStatistics.DeleteAlias(aliasEntry); +} + +void AliasEditorPanel::AddCacheToParent(wxTreeItemId &parentItem, + PlayerCacheEntry &cacheEntry) +{ + AliasListEntry aliasEntry; + + AliasItemSplit(parentItem,aliasEntry); + aliasEntry.aliasGUID=cacheEntry.guid; + aliasEntry.aliasName=cacheEntry.name; + AddAlias(aliasEntry); + globalStatistics.AddAlias(aliasEntry); +} + +void AliasEditorPanel::AddAliasTree(wxTreeItemId &parentItem) +{ + wxTreeItemId childItem; + wxTreeItemIdValue cookie; + AliasListEntry aliasEntry; + + STATSGEN_DEBUG_FUNCTION_START("AliasEditorPanel","AddAliasTree") + + childItem=aliasList->GetFirstChild(parentItem,cookie); + while (childItem.IsOk()) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Adding alias to global area") + AliasItemSplit(childItem,aliasEntry); + globalStatistics.AddAlias(aliasEntry); + childItem=aliasList->GetNextChild(parentItem,cookie); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void AliasEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + wxString msg; + int id; + wxArrayInt selectedPlayers; + wxTreeItemId selectedAlias; + wxTreeItemId parentItem; + wxTreeItemId childItem; + wxTreeItemId rootItem; + wxTreeItemIdValue cookie; + PlayerCacheEntry cacheEntry; + int cacheCount; + int cacheIndex; + int selectedIndex; + + STATSGEN_DEBUG_FUNCTION_START("AliasEditorPanel","OnPopupMenu") + int playerIndex; + AliasListEntry aliasEntry; + wxString parentString; + wxString childString; + + id=event.GetId(); + msg.Printf("AliasEditorPanel::OnPopupMenu():Event Received %d",id); + playerCache->GetSelectedPlayers(selectedPlayers); + cacheCount=selectedPlayers.GetCount(); + selectedAlias=aliasList->GetSelection(); + rootItem=aliasList->GetRootItem(); + switch (event.GetId()) + { + case ALIAS_POPUP_DELETE_PARENT: + STATSGEN_DEBUG(DEBUG_ALWAYS,"Delete Parent") + parentItem=selectedAlias; + childItem=aliasList->GetFirstChild(parentItem,cookie); + while (childItem.IsOk()) + { + AliasItemSplit(childItem,aliasEntry); + globalStatistics.DeleteAlias(aliasEntry); + childItem=aliasList->GetNextChild(parentItem,cookie); + } + aliasList->DeleteChildren(parentItem); + aliasList->Delete(parentItem); + playerCache->ApplyFilter(); + break; + case ALIAS_POPUP_DELETE_CHILD: + STATSGEN_DEBUG(DEBUG_ALWAYS,"Delete Child") + childItem=selectedAlias; + parentItem=aliasList->GetItemParent(childItem); + DeleteAlias(parentItem,childItem); + playerCache->ApplyFilter(); + break; + case ALIAS_POPUP_REPARENT: + STATSGEN_DEBUG(DEBUG_ALWAYS,"Reparent") + childItem=selectedAlias; + parentItem=aliasList->GetItemParent(childItem); + + // Let us delete aliases from the global area first + childItem=aliasList->GetFirstChild(parentItem,cookie); + while (childItem.IsOk()) + { + AliasItemSplit(childItem,aliasEntry); + globalStatistics.DeleteAlias(aliasEntry); + childItem=aliasList->GetNextChild(parentItem,cookie); + } + + // Now Reparent + childItem=selectedAlias; + parentString=aliasList->GetItemText(parentItem); + childString=aliasList->GetItemText(childItem); + aliasList->SetItemText(parentItem,childString); + aliasList->SetItemText(childItem,parentString); + // Now Add New Alias entries to global area + AddAliasTree(parentItem); + playerCache->ApplyFilter(); + break; + case PLAYER_POPUP_NEW_ALIAS: + STATSGEN_DEBUG(DEBUG_ALWAYS,"New Alias") + if (cacheCount>1) + { + // Need at least 2 entries selected to create a new alias + // First entry will be the parent + playerIndex=selectedPlayers.Item(0); + cacheEntry=globalStatistics.playerCache.Item(playerIndex); + // Add the root item to the tree + parentItem=AddPlayerToTree( rootItem, + cacheEntry.guid, + cacheEntry.name); + // Now add all the children + for (cacheIndex=1;cacheIndexApplyFilter(); + } + break; + case PLAYER_POPUP_ADD_ALIAS: + STATSGEN_DEBUG(DEBUG_ALWAYS,"Add Alias") + childItem=selectedAlias; + if (childItem.IsOk()) + { + parentItem=aliasList->GetItemParent(childItem); + if (parentItem==rootItem) + { + parentItem=childItem; + } + for (cacheIndex=0;cacheIndexApplyFilter(); + } + break; + } + STATSGEN_DEBUG_FUNCTION_END +} + +bool AliasEditorPanel::FilterNameCallBack(wxString &name) +{ + bool retVal=false; + AliasListEntry aliasEntry; + int aliasIndex; + int aliasCount; + + aliasCount=globalStatistics.aliasList.GetCount(); + for (aliasIndex=0;aliasIndex +#include + +// Statsgen Includes +#include "PlayerCachePanel.h" +#include "PlayerCacheEntry.h" +#include "AliasListEntry.h" +#include "GroupedConfigItemsPanel.h" +#include "WindowIDs.h" + +class AliasEditorPanel : public wxPanel +{ + public: + AliasEditorPanel(); + virtual bool Create(wxWindow *parent, + wxWindowID id=-1, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + void OnResize(wxSizeEvent &event); + void OnAliasRightClick(wxTreeEvent &event); + void OnPlayerRightClick(wxListEvent &event); + void OnPopupMenu(wxCommandEvent &event); + void RefreshAliasTree(); + void GetShownPlayers(wxArrayInt &shownPlayers); + + protected: + + + private: + enum + { + ALIAS_POPUP_CANCEL=0, + ALIAS_POPUP_DELETE_PARENT, + ALIAS_POPUP_DELETE_CHILD, + ALIAS_POPUP_REPARENT, + PLAYER_POPUP_NEW_ALIAS, + PLAYER_POPUP_ADD_ALIAS + }; + void AliasItemSplit(wxTreeItemId &treeItem, + AliasListEntry &aliasEntry); + void DeleteAlias(wxTreeItemId &parentItem, + wxTreeItemId &childItem); + void AddAlias(AliasListEntry &aliasEntry); + void AddCacheToParent(wxTreeItemId &parentItem, + PlayerCacheEntry &cacheEntry); + void AddAliasTree(wxTreeItemId &parentItem); +static bool FilterNameCallBack(wxString &name); + wxTreeItemId AddPlayerToTree(wxTreeItemId &parentItem, + wxString &guid, + wxString &name); + void OnTextChange(wxCommandEvent &event); + + PlayerCachePanel *playerCache; + wxTreeCtrl *aliasList; + GroupedConfigItemsPanel *aliasConfigs; + wxString aliasFilter; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/AliasListEntry.cpp b/AliasListEntry.cpp new file mode 100644 index 0000000..23ed3d4 --- /dev/null +++ b/AliasListEntry.cpp @@ -0,0 +1,171 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "AliasListEntry.h" +#include "GlobalStatistics.h" +#include "Progress.h" + +AliasListEntry::AliasListEntry() +{ +} + +AliasListEntry::~AliasListEntry() +{ +} + +void AliasListEntry::ReadFromFile(wxTextFile *fp,int index) +{ + wxString primaryLine; + wxString aliasLine; + + primaryLine=fp->GetLine(index*2); + aliasLine=fp->GetLine((index*2)+1); + + primaryGUID=primaryLine.BeforeFirst(','); + primaryName=primaryLine.AfterFirst(','); + aliasGUID=aliasLine.BeforeFirst(','); + aliasName=aliasLine.AfterFirst(','); +} + +void AliasListEntry::WriteToFile(FILE *fp) +{ + fprintf(fp,"%s,%s\n%s,%s\n", + primaryGUID.GetData(), + primaryName.GetData(), + aliasGUID.GetData(), + aliasName.GetData()); +} + +int AliasListEntry::UpdateInDatabase() +{ + Player primaryPlayer; + Player secondaryPlayer; + int primaryIndex=0; + int secondaryIndex=0; + bool primaryFound; + bool secondaryFound; + int updatedIndex=-1; + static wxArrayString tablesNeedingUpdate; + static wxArrayString fieldsNeedingUpdate; + wxString tableName; + wxString fieldName; + static int tableCount=0; + int tableIndex; + wxString sql; + bool cheat; + + if (tableCount==0) + { + tableName="actiondata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="akadata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="awardpoints"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="killdata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="killdata"; + fieldName="targetindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="playerinround"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="speechdata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="streakdata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="streakdata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="teamlossdata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="teamwindata"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableName="xppoints"; + fieldName="playerindex"; + tablesNeedingUpdate.Add(tableName); + fieldsNeedingUpdate.Add(fieldName); + + tableCount=tablesNeedingUpdate.GetCount(); + } + + primaryPlayer.name=primaryName; + secondaryPlayer.name=aliasName; + + if (primaryName.Cmp(aliasName)!=0) + { + primaryFound=primaryPlayer.UpdateFromDatabase(primaryIndex); + secondaryFound=secondaryPlayer.UpdateFromDatabase(secondaryIndex); + + if (primaryFound && secondaryFound) + { + // Both players are in the database - so we need to join them together + primaryPlayer.Add(secondaryPlayer); + updatedIndex=primaryPlayer.actualPlayerIndex; + for (tableIndex=0;tableIndex +#include +#include +#include + +// Statsgen Includes + +class AliasListEntry; + +WX_DECLARE_OBJARRAY(AliasListEntry,ArrayOfAliasListEntry); +class AliasListEntry +{ + public: + AliasListEntry(); + ~AliasListEntry(); + void WriteToFile(FILE *fp); + void ReadFromFile(wxTextFile *fp,int index); + int UpdateInDatabase(); + wxString primaryGUID; + wxString primaryName; + wxString aliasGUID; + wxString aliasName; +}; + + +#endif diff --git a/AwardDefinition.cpp b/AwardDefinition.cpp new file mode 100644 index 0000000..d68083e --- /dev/null +++ b/AwardDefinition.cpp @@ -0,0 +1,726 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "AwardDefinition.h" +#include "GlobalStatistics.h" + +void AwardDefinition::ReadConfig() +{ + wxString configBase; + wxString configKey; + wxString configValue; + wxString baseGroup; + + baseGroup="AWARDDEFINITION"+id; + + globalStatistics.configData.ReadList(baseGroup,"WEAPONKILLCODES",weaponKillComponents); + globalStatistics.configData.ReadList(baseGroup,"WEAPONDEATHCODES",weaponDeathComponents); + globalStatistics.configData.ReadList(baseGroup,"WEAPONTKCODES",weaponTKComponents); + globalStatistics.configData.ReadList(baseGroup,"LOCATIONKILLCODES",locationKillComponents); + globalStatistics.configData.ReadList(baseGroup,"LOCATIONDEATHCODES",locationDeathComponents); + globalStatistics.configData.ReadList(baseGroup,"LOCATIONTKCODES",locationTKComponents); + globalStatistics.configData.ReadList(baseGroup,"ACTIONCODES",actionComponents); + globalStatistics.configData.ReadList(baseGroup,"MISCCODES",miscComponents); + globalStatistics.configData.ReadList(baseGroup,"XPCODES",xpComponents); + globalStatistics.configData.ReadList(baseGroup,"GAMETYPECODES",allowedGameTypes); + + configBase.Printf("/%s/",baseGroup.GetData()); + configKey=configBase+"Name"; + globalStatistics.configData.ReadTextValue(configKey,&name,""); + configKey=configBase+"Image"; + globalStatistics.configData.ReadTextValue(configKey,&image,""); + configKey=configBase+"Weighted"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"N"); + weighted=(configValue.CmpNoCase("Y")==0); +} + +AwardDefinition::AwardDefinition(wxString &idIn) +{ + + id=idIn; + + ReadConfig(); + + +} + +AwardDefinition::~AwardDefinition() +{ +} + +wxString AwardDefinition::SQLTableNameComponent(const char *componentType) +{ + wxString tableName="awarddefinition"; + + tableName+=componentType; + + return (tableName); +} + +wxString AwardDefinition::SQLTableName() +{ + wxString tableName="awarddefinition"; + + return (tableName); +} + +wxString AwardDefinition::SQLCreateTableComponent(const char *component) +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "awardindex integer," + "componentindex integer," + "%s," + "posneg varchar(1)," + "%s," + "%s" + ")", + SQLTableNameComponent(component).GetData(), + StatsgenDatabase::StringFieldDefinition("id","awardid",FIELD_WIDTH_KEY_ID).GetData(), + StatsgenDatabase::StringFieldDefinition("name","awardname",FIELD_WIDTH_KEY_REALNAME).GetData(), + StatsgenDatabase::StringFieldDefinition("image","awardimage",FIELD_WIDTH_KEY_IMAGE).GetData() + ); + + return SQL; +} + +wxString AwardDefinition::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "awardindex integer," + "%s," + "%s," + "%s," + "weighted varchar(1)" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("id","awardcomponentid",FIELD_WIDTH_AWARD_ID).GetData(), + StatsgenDatabase::StringFieldDefinition("name","awardcomponentname",FIELD_WIDTH_AWARD_NAME).GetData(), + StatsgenDatabase::StringFieldDefinition("image","awardcomponentimage",FIELD_WIDTH_AWARD_IMAGE).GetData() + ); + + return SQL; +} + +bool AwardDefinition::WriteToDatabaseComponent(int itemIndex, + const char *component, + wxArrayString &componentList, + const char *idPrefix) +{ + wxString SQL; + bool retVal=true; + int componentCount; + int componentIndex; + wxString componentRealName; + wxString componentImage; + wxString configKey; + wxString thisID; + wxString componentID; + char posneg; + wxArrayString collectedIDs; + int idCount; + int idIndex; + + componentCount=componentList.GetCount(); + for (componentIndex=0;componentIndex0)&& + (globalStatistics.configData.IsWeaponGroupKey(thisID))) + { + collectedIDs=globalStatistics.configData.WeaponGroupKeys(thisID); + } + else + { + collectedIDs.Add(thisID); + } + idCount=collectedIDs.GetCount(); + for (idIndex=0;idIndex0) + { + componentID.Printf("%s_%s",idPrefix,thisID.GetData()); + configKey.Printf("/RealNames/%s",componentID.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&componentRealName,(char *)componentID.GetData()); + configKey.Printf("/Images/%s",componentID.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&componentImage); + } + else + { + componentID.Printf("%s",thisID.GetData()); + } + SQL.Printf("Insert into %s" + "(awardindex,componentindex,id,posneg,image,name)" + "values('%d','%d','%s','%c','%s','%s')", + SQLTableNameComponent(component).GetData(), + itemIndex, + componentIndex, + componentID.GetData(), + posneg, + componentImage.GetData(), + StatsgenDatabase::SafeForInsert(componentRealName).GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + } + } + return retVal; +} + +bool AwardDefinition::WriteToDatabase(int itemIndex) +{ + wxString SQL; + bool retVal=true; + char weightedChar; + + WriteToDatabaseComponent(itemIndex,"weaponkill",weaponKillComponents,"weapon"); + WriteToDatabaseComponent(itemIndex,"weapondeath",weaponDeathComponents,"weapon"); + WriteToDatabaseComponent(itemIndex,"weapontk",weaponTKComponents,"weapon"); + WriteToDatabaseComponent(itemIndex,"locationkill",locationKillComponents,"location"); + WriteToDatabaseComponent(itemIndex,"locationdeath",locationDeathComponents,"location"); + WriteToDatabaseComponent(itemIndex,"locationtk",locationTKComponents,"location"); + WriteToDatabaseComponent(itemIndex,"action",actionComponents,"action"); + WriteToDatabaseComponent(itemIndex,"misc",miscComponents,""); + WriteToDatabaseComponent(itemIndex,"xp",xpComponents,"xp"); + + if (weighted) + { + weightedChar='Y'; + } + else + { + weightedChar='N'; + } + SQL.Printf("Insert into %s" + "(awardindex,id,image,name,weighted)" + "values('%d','%s','%s','%s','%c')", + SQLTableName().GetData(), + itemIndex, + id.GetData(), + image.GetData(), + StatsgenDatabase::SafeForInsert(name).GetData(), + weightedChar); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} + +void AwardDefinition::SplitCode(wxString &code,bool *positive,bool *teamkill) +{ + char signChar; + + signChar='+'; + if (code.Length()>0) + { + signChar=code[0]; + code=code.Mid(1); + } + if (signChar=='+') + { + *positive=true; + } + else + { + *positive=false; + } + if (signChar=='T') + { + *teamkill=true; + } + else + { + *teamkill=false; + } +} + +int AwardDefinition::ActionScore(bool *noScore,wxString &key) +{ + int count; + int index; + wxString code; + int points; + bool positive; + bool teamkill; + + points=0; + *noScore=true; + count=actionComponents.GetCount(); + for (index=0;index0) + { + for (index=0;index +#include +#include + +// Statsgen Includes + +class AwardDefinition; + +WX_DECLARE_OBJARRAY(AwardDefinition,ArrayOfAwardDefinition); +class AwardDefinition +{ + public: + void ReadConfig(); + void WriteConfig(); + AwardDefinition(wxString &idIn); +// bool Allowed(wxString &gameType); + virtual ~AwardDefinition(); + static wxString SQLCreateTable(); + static wxString SQLTableNameComponent(const char *component); + static wxString SQLCreateTableComponent(const char *component); + static wxString SQLTableName(); + bool WriteToDatabase(int itemIndex); + bool WriteToDatabaseComponent(int itemIndex,const char *component,wxArrayString &componentList,const char *prefix); + int WeaponScore(bool *noScore,wxString &key,bool kill,bool teamkill); + int XPScore(bool *noScore,wxString &key,float points); + int LocationScore(bool *noScore,wxString &key,bool kill,bool teamkill); + int ActionScore(bool *noScore,wxString &key); + int MiscScore(bool *noScore,char *key,int count); + void SplitCode(wxString &code,bool *positive,bool *teamkill); + + void AddWeaponComponent(wxString &code,bool kill,bool positive,bool teamkill); + void AddLocationComponent(wxString &code,bool kill,bool positive,bool teamkill); + void AddActionComponent(wxString &code,bool positive); + void AddMiscComponent(wxString &code,bool positive); + void AddXPComponent(wxString &code,bool positive); + + void RemoveWeaponComponent(wxString &code,bool killList,bool teamkillList); + void RemoveLocationComponent(wxString &code,bool killList,bool teamkillList); + void RemoveActionComponent(wxString &code); + void RemoveMiscComponent(wxString &code); + void RemoveXPComponent(wxString &code); + + wxArrayString allowedGameTypes; + wxString image; + wxString name; + bool weighted; + wxArrayString weaponKillComponents; + wxArrayString weaponDeathComponents; + wxArrayString weaponTKComponents; + wxArrayString locationKillComponents; + wxArrayString locationDeathComponents; + wxArrayString locationTKComponents; + wxArrayString actionComponents; + wxArrayString xpComponents; + wxArrayString miscComponents; + + wxString id; + +}; + + +#endif diff --git a/AwardEditorPanel.cpp b/AwardEditorPanel.cpp new file mode 100644 index 0000000..762fda3 --- /dev/null +++ b/AwardEditorPanel.cpp @@ -0,0 +1,978 @@ +// Statsgen Includes +#include "AwardEditorPanel.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(AwardEditorPanel, wxPanel) + EVT_SIZE(AwardEditorPanel::OnResize) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_AWARDCHOICESPANEL,AwardEditorPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_AWARDDEFINITIONPANEL,AwardEditorPanel::OnRightClick) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,AwardEditorPanel::OnConfigChanged) + EVT_MENU(AWARD_DEFINITION_DELETE_COMPONENT,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_POSITIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_NEGATIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_KILL_POSITIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_KILL_NEGATIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_DEATH_POSITIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_DEATH_NEGATIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_TK_POSITIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_TK_NEGATIVE,AwardEditorPanel::OnPopupMenu) + EVT_MENU(AWARD_CHOICES_ADD_KILL_AND_DEATH,AwardEditorPanel::OnPopupMenu) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(AwardChoicesPanel, wxPanel) + EVT_SIZE(AwardChoicesPanel::OnResize) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_WEAPONLIST,AwardChoicesPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_ACTIONLIST,AwardChoicesPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_LOCATIONLIST,AwardChoicesPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_MISCAWARDLIST,AwardChoicesPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_XPAWARDLIST,AwardChoicesPanel::OnRightClick) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(AwardDefinitionPanel, wxPanel) + EVT_SIZE(AwardDefinitionPanel::OnResize) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_WEAPONLIST,AwardDefinitionPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_ACTIONLIST,AwardDefinitionPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_LOCATIONLIST,AwardDefinitionPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_MISCAWARDLIST,AwardDefinitionPanel::OnRightClick) + EVT_TREE_ITEM_RIGHT_CLICK(WINDOW_ID_XPAWARDLIST,AwardDefinitionPanel::OnRightClick) +END_EVENT_TABLE() + +AwardEditorPanel::AwardEditorPanel( + wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn): + wxPanel(parent, + id, + pos, + size, + style, + name) + +{ + wxString configGroup; + wxString configKey; + wxSizeEvent dummyEvent; + wxString serverTypeConfigKey="/tmp/awardeditorservertype"; + int serverTypeIndex; + wxString serverTypeCode; + wxString serverTypeName; + wxArrayString serverTypeCodes; + wxArrayString serverTypeNames; + + STATSGEN_DEBUG_FUNCTION_START("AwardEditorPanel","Constructor") + awardID=awardIDIn; + serverTypeCode=""; + serverTypeName="Any"; + serverTypeCodes.Add(serverTypeCode); + serverTypeNames.Add(serverTypeName); + for (serverTypeIndex=0;serverTypeIndexCreate(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE,wxDefaultPosition,wxDefaultSize); + + overallConfig->AddSelection("Server Type Filter",serverTypeConfigKey,"",serverTypeCodes,serverTypeNames); + configKey.Printf("/%s/Name",configGroup.GetData()); + overallConfig->Add("Name", configKey,"",-1,NULL); + configKey.Printf("/%s/Image",configGroup.GetData()); + overallConfig->Add("Image URL", configKey,"",-1,NULL); + configKey.Printf("/%s/Weighted",configGroup.GetData()); + overallConfig->AddBoolean("Weighted", configKey,"N",NULL); + splitter=new wxSplitterWindow(this, -1, + wxDefaultPosition, + wxDefaultSize, + wxSP_3D); + + awardChoices=new AwardChoicesPanel( + splitter, + WINDOW_ID_AWARDCHOICESPANEL, + wxDefaultPosition, + wxDefaultSize, + 0, + _T(""), + awardID); + awardChoices->Enable(); + awardDefinition=new AwardDefinitionPanel( + splitter, + WINDOW_ID_AWARDDEFINITIONPANEL, + wxDefaultPosition, + wxDefaultSize, + 0, + _T(""), + awardID); + + awardDefinition->Enable(); + splitter->SplitHorizontally(awardChoices,awardDefinition); + splitter->SetSashGravity(0.5); + + OnResize(dummyEvent); + STATSGEN_DEBUG_FUNCTION_END +} + +AwardEditorPanel::~AwardEditorPanel() +{ + STATSGEN_DEBUG_FUNCTION_START("AwardEditorPanel","Destructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardEditorPanel::OnConfigChanged(wxCommandEvent &event) +{ + wxString serverTypeConfigKey="/tmp/awardeditorservertype"; + static wxString lastConfigValue=""; + wxString serverTypeConfigValue; + + globalStatistics.configData.ReadTextValue(serverTypeConfigKey,&serverTypeConfigValue); + + if (serverTypeConfigValue.Cmp(lastConfigValue)!=0) + { + lastConfigValue=serverTypeConfigValue; + if ((awardChoices!=NULL)&&(awardDefinition!=NULL)) + { + awardChoices->SetFilter(serverTypeConfigValue); + awardDefinition->SetFilter(serverTypeConfigValue); + } + } + +} + +void AwardEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + long selectedTree; + int selectedCodesCount; + int selectedCodesIndex; + wxString selectedCode; + int menuSelection=event.GetId(); + wxArrayString selectedCodes; + bool killList; + bool teamkillList; + + STATSGEN_DEBUG_FUNCTION_START("AwardEditorPanel","OnPopupMenu") + if (menuSelection==AWARD_DEFINITION_DELETE_COMPONENT) + { + // Award Definition + selectedTree=awardDefinition->selectedDefinitionTree; + selectedCodes=awardDefinition->selectedCodes; + } + else + { + // Award Choice + selectedTree=awardChoices->selectedChoiceTree; + selectedCodes=awardChoices->selectedCodes; + } + selectedCodesCount=selectedCodes.GetCount(); + for (selectedCodesIndex=0;selectedCodesIndexawardDefinition->SplitCode(selectedCode,&killList,&teamkillList); + awardDefinition->RemoveWeaponComponent(selectedCode,killList,teamkillList); + break; + case AWARD_CHOICES_ADD_KILL_POSITIVE: + case AWARD_CHOICES_ADD_KILL_NEGATIVE: + case AWARD_CHOICES_ADD_DEATH_POSITIVE: + case AWARD_CHOICES_ADD_DEATH_NEGATIVE: + case AWARD_CHOICES_ADD_TK_POSITIVE: + case AWARD_CHOICES_ADD_TK_NEGATIVE: + awardDefinition->AddWeaponComponent( + selectedCode, + (menuSelection==AWARD_CHOICES_ADD_KILL_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_KILL_NEGATIVE), + (menuSelection==AWARD_CHOICES_ADD_KILL_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_DEATH_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_TK_POSITIVE), + (menuSelection==AWARD_CHOICES_ADD_TK_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_TK_NEGATIVE)); + + break; + case AWARD_CHOICES_ADD_KILL_AND_DEATH: + awardDefinition->AddWeaponComponent(selectedCode,true,true,false); + awardDefinition->AddWeaponComponent(selectedCode,false,false,false); + break; + } + break; + case WINDOW_ID_LOCATIONLIST: + switch (menuSelection) + { + case AWARD_DEFINITION_DELETE_COMPONENT: + awardDefinition->awardDefinition->SplitCode(selectedCode,&killList,&teamkillList); + awardDefinition->RemoveLocationComponent(selectedCode,killList,teamkillList); + break; + case AWARD_CHOICES_ADD_KILL_POSITIVE: + case AWARD_CHOICES_ADD_KILL_NEGATIVE: + case AWARD_CHOICES_ADD_DEATH_POSITIVE: + case AWARD_CHOICES_ADD_DEATH_NEGATIVE: + case AWARD_CHOICES_ADD_TK_POSITIVE: + case AWARD_CHOICES_ADD_TK_NEGATIVE: + awardDefinition->AddLocationComponent( + selectedCode, + (menuSelection==AWARD_CHOICES_ADD_KILL_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_KILL_NEGATIVE), + (menuSelection==AWARD_CHOICES_ADD_KILL_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_TK_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_DEATH_POSITIVE), + (menuSelection==AWARD_CHOICES_ADD_TK_POSITIVE)|| + (menuSelection==AWARD_CHOICES_ADD_TK_NEGATIVE)); + + break; + case AWARD_CHOICES_ADD_KILL_AND_DEATH: + awardDefinition->AddLocationComponent(selectedCode,true,true,false); + awardDefinition->AddLocationComponent(selectedCode,false,false,false); + break; + } + break; + case WINDOW_ID_ACTIONLIST: + switch (menuSelection) + { + case AWARD_DEFINITION_DELETE_COMPONENT: + awardDefinition->awardDefinition->SplitCode(selectedCode,&killList,&teamkillList); + awardDefinition->RemoveActionComponent(selectedCode); + break; + case AWARD_CHOICES_ADD_POSITIVE: + case AWARD_CHOICES_ADD_NEGATIVE: + awardDefinition->AddActionComponent( + selectedCode, + (menuSelection==AWARD_CHOICES_ADD_POSITIVE)); + break; + } + break; + case WINDOW_ID_MISCAWARDLIST: + switch (menuSelection) + { + case AWARD_DEFINITION_DELETE_COMPONENT: + awardDefinition->awardDefinition->SplitCode(selectedCode,&killList,&teamkillList); + awardDefinition->RemoveMiscComponent(selectedCode); + break; + case AWARD_CHOICES_ADD_POSITIVE: + case AWARD_CHOICES_ADD_NEGATIVE: + awardDefinition->AddMiscComponent( + selectedCode, + (menuSelection==AWARD_CHOICES_ADD_POSITIVE)); + break; + } + break; + case WINDOW_ID_XPAWARDLIST: + switch (menuSelection) + { + case AWARD_DEFINITION_DELETE_COMPONENT: + awardDefinition->awardDefinition->SplitCode(selectedCode,&killList,&teamkillList); + awardDefinition->RemoveXPComponent(selectedCode); + break; + case AWARD_CHOICES_ADD_POSITIVE: + case AWARD_CHOICES_ADD_NEGATIVE: + awardDefinition->AddXPComponent( + selectedCode, + (menuSelection==AWARD_CHOICES_ADD_POSITIVE)); + break; + } + break; + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardEditorPanel::OnRightClick(wxTreeEvent &event) +{ + wxMenu popupMenu(_T("")); + long panelId=event.GetId(); + long selectedChoiceTree=awardChoices->selectedChoiceTree; + + STATSGEN_DEBUG_FUNCTION_START("AwardEditorPanel","OnRightClick") + if (panelId==WINDOW_ID_AWARDCHOICESPANEL) + { + switch (selectedChoiceTree) + { + case WINDOW_ID_WEAPONLIST: + case WINDOW_ID_LOCATIONLIST: + popupMenu.Append(AWARD_CHOICES_ADD_KILL_POSITIVE,_T("Add Positive Effect Kills")); + popupMenu.Append(AWARD_CHOICES_ADD_KILL_NEGATIVE,_T("Add Negative Effect Kills")); + popupMenu.Append(AWARD_CHOICES_ADD_DEATH_POSITIVE,_T("Add Positive Effect Deaths")); + popupMenu.Append(AWARD_CHOICES_ADD_DEATH_NEGATIVE,_T("Add Negative Effect Deaths")); + popupMenu.Append(AWARD_CHOICES_ADD_TK_POSITIVE,_T("Add Positive Effect Team Kills")); + popupMenu.Append(AWARD_CHOICES_ADD_TK_NEGATIVE,_T("Add Negative Effect Team Kills")); + popupMenu.Append(AWARD_CHOICES_ADD_KILL_AND_DEATH,_T("Add Kill And Death Combination")); + break; + case WINDOW_ID_ACTIONLIST: + popupMenu.Append(AWARD_CHOICES_ADD_POSITIVE,_T("Add Objective Positive Effect")); + popupMenu.Append(AWARD_CHOICES_ADD_NEGATIVE,_T("Add Objective Negative Effect")); + break; + case WINDOW_ID_MISCAWARDLIST: + popupMenu.Append(AWARD_CHOICES_ADD_POSITIVE,_T("Add Miscellaneous Positive Effect")); + popupMenu.Append(AWARD_CHOICES_ADD_NEGATIVE,_T("Add Miscellaneous Negative Effect")); + break; + case WINDOW_ID_XPAWARDLIST: + popupMenu.Append(AWARD_CHOICES_ADD_POSITIVE,_T("Add XP Positive Effect")); + popupMenu.Append(AWARD_CHOICES_ADD_NEGATIVE,_T("Add XP Negative Effect")); + break; + } + } + else + { + popupMenu.Append(AWARD_DEFINITION_DELETE_COMPONENT,_T("Delete Award Component(s)")); + } + + popupMenu.Append(POPUP_CANCEL,_T("Cancel")); + + PopupMenu(&popupMenu); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardEditorPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + wxSize itemSize; + int panelWidth; + int panelHeight; + int overallConfigWidth; + int overallConfigHeight; + int choiceHeight; + int choiceWidth; + + STATSGEN_DEBUG_FUNCTION_START("AwardEditorPanel","OnResize") + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + overallConfigWidth=panelWidth; + overallConfigHeight=panelHeight; + + + overallConfigHeight=100; + choiceHeight=(panelHeight-overallConfigHeight); + choiceWidth=panelWidth; + + splitter->SetSize(0,overallConfigHeight, + choiceWidth,choiceHeight); + splitter->SetSashPosition(choiceHeight/2); + + overallConfig->SetSize(0,0, + overallConfigWidth, + overallConfigHeight); + STATSGEN_DEBUG_FUNCTION_END +} + +AwardChoicesPanel::AwardChoicesPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn): + wxPanel(parent, + id, + pos, + size, + style, + name) + +{ + wxTreeItemId rootItem; + long listStyle; + wxString filterConfig="/tmp/awardeditorservertype"; + + + STATSGEN_DEBUG_FUNCTION_START("AwardChoicesPanel","Constructor") + awardID=awardIDIn; + globalStatistics.configData.ReadTextValue(filterConfig,&filter); + + listStyle=wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_EXTENDED | wxTR_MULTIPLE; + + weaponList=new wxTreeCtrl(this, WINDOW_ID_WEAPONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + actionList=new wxTreeCtrl(this, WINDOW_ID_ACTIONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + locationList=new wxTreeCtrl(this, WINDOW_ID_LOCATIONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + miscList=new wxTreeCtrl(this, WINDOW_ID_MISCAWARDLIST, wxDefaultPosition,wxDefaultSize, listStyle); + xpList=new wxTreeCtrl(this, WINDOW_ID_XPAWARDLIST, wxDefaultPosition,wxDefaultSize, listStyle); + + weaponList->AddRoot(_T("")); + actionList->AddRoot(_T("")); + xpList->AddRoot(_T("")); + locationList->AddRoot(_T("")); + rootItem=miscList->AddRoot(_T("")); + + label=new wxStaticText(this,-1,_T("Choose From The Following Award Components")); + weaponList->Hide(); + locationList->Hide(); + actionList->Hide(); + xpList->Hide(); + miscList->Hide(); + PopulateList(weaponList,"WEAPON","weapon"); + PopulateList(actionList,"ACTION","action"); + PopulateList(xpList,"XP","xp"); + PopulateList(locationList,"LOCATION","location"); + + wxArrayString miscAwardComponents; + wxString awardComponent; + + awardComponent="Speech";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Team Win";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Team Loss";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Suicides";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Kills";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Deaths";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + awardComponent="Team Kills";miscAwardComponents.Add(awardComponent); + miscList->AppendItem(rootItem,awardComponent,-1,-1,new StringTreeItemData(awardComponent)); + //miscList->InsertItems(miscAwardComponents,0); + miscList->Expand(rootItem); + weaponList->Show(); + locationList->Show(); + actionList->Show(); + miscList->Show(); + xpList->Show(); + + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardChoicesPanel::SetFilter(wxString &filterString) +{ + filter=filterString; + PopulateList(weaponList,"WEAPON","weapon"); + PopulateList(actionList,"ACTION","action"); + PopulateList(xpList,"XP","xp"); + PopulateList(locationList,"LOCATION","location"); +} + +void AwardChoicesPanel::PopulateList(wxTreeCtrl *listBox, + const char *group, + const char *realnamePrefix) +{ + wxString logEntryGroup; + wxArrayString keys; + wxArrayString values; + wxArrayString realNames; + wxString key; + int keyCount; + int keyIndex; + wxString realName; + wxString configKey; + wxTreeItemId rootItem; + wxArrayString weaponGroups; + STATSGEN_DEBUG_FUNCTION_START("AwardChoicesPanel","PopulateList") + + if (strcmp("WEAPON",group)==0) + { + weaponGroups=globalStatistics.configData.ReadWeaponGroups(); + } + listBox->Hide(); + rootItem=listBox->GetRootItem(); + listBox->DeleteChildren(rootItem); + logEntryGroup.Printf("LogEntries%s",group); + globalStatistics.configData.ReadGroup(logEntryGroup, keys, values); + WX_APPEND_ARRAY(keys,weaponGroups); + keyCount=keys.GetCount(); + for (keyIndex=0;keyIndex0) + { + filter = filter.Lower(); + wxString filterKey; + filterKey=key.Lower(); + if (!filterKey.StartsWith(filter)) + { + continue; + } + } + configKey.Printf("/RealNames/%s_%s", + realnamePrefix, + key.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&realName, + (char *)key.GetData()); + realNames.Add(realName); + listBox->AppendItem(rootItem,realName,-1,-1,new StringTreeItemData(key)); + } + listBox->Show(); + STATSGEN_DEBUG_FUNCTION_END +} + +AwardChoicesPanel::~AwardChoicesPanel() +{ + STATSGEN_DEBUG_FUNCTION_START("AwardChoicesPanel","Destructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardChoicesPanel::OnRightClick(wxTreeEvent &event) +{ + StringTreeItemData *itemData; + wxArrayTreeItemIds selections; + wxString codeSelected; + wxTreeItemId selection; + int selectionCount; + int selectionIndex; + wxTreeCtrl *selectedTree=NULL; + + STATSGEN_DEBUG_FUNCTION_START("AwardChoicesPanel","OnRightClick") + selectedCodes.Clear(); + + selectedChoiceTree=event.GetId(); + switch (selectedChoiceTree) + { + case WINDOW_ID_WEAPONLIST: + selectedTree=weaponList; + break; + case WINDOW_ID_ACTIONLIST: + selectedTree=actionList; + break; + case WINDOW_ID_LOCATIONLIST: + selectedTree=locationList; + break; + case WINDOW_ID_MISCAWARDLIST: + selectedTree=miscList; + break; + case WINDOW_ID_XPAWARDLIST: + selectedTree=xpList; + break; + } + if (selectedTree!=NULL) + { + selectedTree->GetSelections(selections); + } + selectionCount=selections.GetCount(); + for (selectionIndex=0;selectionIndexGetItemData(selection); + codeSelected=itemData->GetString(); + selectedCodes.Add(codeSelected); + } + + event.SetId(this->GetId()); + GetParent()->AddPendingEvent(event); + + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardChoicesPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + wxSize itemSize; + int panelWidth; + int panelHeight; + int choiceHeight; + int choiceWidth; + int labelHeight; + int labelWidth; + int labelX; + + STATSGEN_DEBUG_FUNCTION_START("AwardChoicesPanel","OnResize") + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label->GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + labelX=(panelWidth-labelWidth)/2; + choiceHeight=panelHeight-labelHeight; + choiceWidth=panelWidth/5; + + label->SetSize(labelX,0, labelWidth,labelHeight); + weaponList->SetSize(0,labelHeight, choiceWidth,choiceHeight); + locationList->SetSize(choiceWidth*1,labelHeight, choiceWidth,choiceHeight); + actionList->SetSize(choiceWidth*2,labelHeight, choiceWidth,choiceHeight); + miscList->SetSize(choiceWidth*3,labelHeight, choiceWidth,choiceHeight); + xpList->SetSize(choiceWidth*4,labelHeight, choiceWidth,choiceHeight); + STATSGEN_DEBUG_FUNCTION_END + +} + +AwardDefinitionPanel::AwardDefinitionPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn): + wxPanel(parent, + id, + pos, + size, + style, + name) + +{ + long listStyle; + wxString filterConfig="/tmp/awardeditorservertype"; + + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","Constructor") + + globalStatistics.configData.ReadTextValue(filterConfig,&filter); + awardID=awardIDIn; + + awardDefinition=new AwardDefinition(awardID); + + listStyle=wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_EXTENDED | wxTR_MULTIPLE; + + weaponList=new wxTreeCtrl(this, WINDOW_ID_WEAPONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + actionList=new wxTreeCtrl(this, WINDOW_ID_ACTIONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + locationList=new wxTreeCtrl(this, WINDOW_ID_LOCATIONLIST, wxDefaultPosition,wxDefaultSize, listStyle); + miscList=new wxTreeCtrl(this, WINDOW_ID_MISCAWARDLIST, wxDefaultPosition,wxDefaultSize, listStyle); + xpList=new wxTreeCtrl(this, WINDOW_ID_XPAWARDLIST, wxDefaultPosition,wxDefaultSize, listStyle); + + weaponList->AddRoot(_T("")); + actionList->AddRoot(_T("")); + locationList->AddRoot(_T("")); + miscList->AddRoot(_T("")); + xpList->AddRoot(_T("")); + + label=new wxStaticText(this,-1,_T("Currently Defined Components For This Award")); + + weaponList->Hide(); + locationList->Hide(); + actionList->Hide(); + miscList->Hide(); + xpList->Hide(); + PopulateList(weaponList,awardDefinition->weaponKillComponents,"weapon","KILL"); + PopulateList(weaponList,awardDefinition->weaponDeathComponents,"weapon","DEATH"); + PopulateList(weaponList,awardDefinition->weaponTKComponents,"weapon","TK"); + PopulateList(locationList,awardDefinition->locationKillComponents,"location","KILL"); + PopulateList(locationList,awardDefinition->locationDeathComponents,"location","DEATH"); + PopulateList(locationList,awardDefinition->locationTKComponents,"location","TK"); + PopulateList(actionList,awardDefinition->actionComponents,"action",""); + PopulateList(xpList,awardDefinition->xpComponents,"xp",""); + PopulateList(miscList,awardDefinition->miscComponents,"",""); + weaponList->Show(); + locationList->Show(); + actionList->Show(); + miscList->Show(); + xpList->Show(); + STATSGEN_DEBUG_FUNCTION_END + +} + +AwardDefinitionPanel::~AwardDefinitionPanel() +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","Destructor") + if (awardDefinition!=NULL) + { + delete(awardDefinition); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::SetFilter(wxString &filterString) +{ + filter=filterString; + wxTreeItemId weaponRootItem=weaponList->GetRootItem(); + wxTreeItemId locationRootItem=locationList->GetRootItem(); + wxTreeItemId actionRootItem=actionList->GetRootItem(); + wxTreeItemId xpRootItem=xpList->GetRootItem(); + + weaponList->Hide(); + weaponList->DeleteChildren(weaponRootItem); + locationList->Hide(); + locationList->DeleteChildren(locationRootItem); + actionList->Hide(); + actionList->DeleteChildren(actionRootItem); + xpList->Hide(); + xpList->DeleteChildren(xpRootItem); + PopulateList(weaponList,awardDefinition->weaponKillComponents,"weapon","KILL"); + PopulateList(weaponList,awardDefinition->weaponDeathComponents,"weapon","DEATH"); + PopulateList(weaponList,awardDefinition->weaponTKComponents,"weapon","TK"); + PopulateList(locationList,awardDefinition->locationKillComponents,"location","KILL"); + PopulateList(locationList,awardDefinition->locationDeathComponents,"location","DEATH"); + PopulateList(locationList,awardDefinition->locationTKComponents,"location","TK"); + PopulateList(actionList,awardDefinition->actionComponents,"action",""); + PopulateList(xpList,awardDefinition->xpComponents,"xp",""); +} + +void AwardDefinitionPanel::AddWeaponComponent(wxString &code,bool kill,bool positive,bool teamkill) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","AddWeaponComponent") + awardDefinition->AddWeaponComponent(code,kill,positive,teamkill); + weaponList->DeleteAllItems(); + weaponList->AddRoot(_T("")); + PopulateList(weaponList,awardDefinition->weaponKillComponents,"weapon","KILL"); + PopulateList(weaponList,awardDefinition->weaponDeathComponents,"weapon","DEATH"); + PopulateList(weaponList,awardDefinition->weaponTKComponents,"weapon","TK"); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::RemoveWeaponComponent(wxString &code,bool killList,bool teamkillList) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","RemoveWeaponComponent") + awardDefinition->RemoveWeaponComponent(code,killList,teamkillList); + weaponList->DeleteAllItems(); + weaponList->AddRoot(_T("")); + PopulateList(weaponList,awardDefinition->weaponKillComponents,"weapon","KILL"); + PopulateList(weaponList,awardDefinition->weaponDeathComponents,"weapon","DEATH"); + PopulateList(weaponList,awardDefinition->weaponTKComponents,"weapon","TK"); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::AddLocationComponent(wxString &code,bool kill,bool positive,bool teamkill) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","AddLocationComponent") + awardDefinition->AddLocationComponent(code,kill,positive,teamkill); + locationList->DeleteAllItems(); + locationList->AddRoot(_T("")); + PopulateList(locationList,awardDefinition->locationKillComponents,"location","KILL"); + PopulateList(locationList,awardDefinition->locationDeathComponents,"location","DEATH"); + PopulateList(locationList,awardDefinition->locationTKComponents,"location","TK"); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::RemoveLocationComponent(wxString &code,bool killList,bool teamkillList) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","RemoveLocationComponent") + awardDefinition->RemoveLocationComponent(code,killList,teamkillList); + locationList->DeleteAllItems(); + locationList->AddRoot(_T("")); + PopulateList(locationList,awardDefinition->locationKillComponents,"location","KILL"); + PopulateList(locationList,awardDefinition->locationDeathComponents,"location","DEATH"); + PopulateList(locationList,awardDefinition->locationTKComponents,"location","TK"); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::AddActionComponent(wxString &code,bool positive) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","AddActionComponent") + awardDefinition->AddActionComponent(code,positive); + actionList->DeleteAllItems(); + actionList->AddRoot(_T("")); + PopulateList(actionList,awardDefinition->actionComponents,"action",""); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::RemoveActionComponent(wxString &code) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","RemoveActionComponent") + awardDefinition->RemoveActionComponent(code); + actionList->DeleteAllItems(); + actionList->AddRoot(_T("")); + PopulateList(actionList,awardDefinition->actionComponents,"action",""); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::AddMiscComponent(wxString &code,bool positive) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","AddMiscComponent") + awardDefinition->AddMiscComponent(code,positive); + miscList->DeleteAllItems(); + miscList->AddRoot(_T("")); + PopulateList(miscList,awardDefinition->miscComponents,"",""); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::RemoveMiscComponent(wxString &code) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","RemoveMiscComponent") + awardDefinition->RemoveMiscComponent(code); + miscList->DeleteAllItems(); + miscList->AddRoot(_T("")); + PopulateList(miscList,awardDefinition->miscComponents,"",""); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + wxSize itemSize; + int panelWidth; + int panelHeight; + int choiceHeight; + int choiceWidth; + int labelWidth; + int labelHeight; + int labelX; + + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","OnResize") + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label->GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + labelX=(panelWidth-labelWidth)/2; + + choiceHeight=panelHeight-labelHeight; + choiceWidth=panelWidth/5; + + label->SetSize(labelX,0,labelWidth,labelHeight); + weaponList->SetSize(0,labelHeight, choiceWidth,choiceHeight); + locationList->SetSize(choiceWidth*1,labelHeight, choiceWidth,choiceHeight); + actionList->SetSize(choiceWidth*2,labelHeight, choiceWidth,choiceHeight); + miscList->SetSize(choiceWidth*3,labelHeight, choiceWidth,choiceHeight); + xpList->SetSize(choiceWidth*4,labelHeight, choiceWidth,choiceHeight); + + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::PopulateList(wxTreeCtrl *listBox, + wxArrayString &codes, + const char *realnamePrefix, + const char *suffix) +{ + wxString code; + int codeCount; + int codeIndex; + wxString realName; + wxString configKey; + bool positive; + bool teamkilldummy; + wxString prefixedCode; + wxTreeItemId rootItem=listBox->GetRootItem(); + char suffixChar; + + + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","PopulateList") + listBox->Hide(); + if (strcmp(suffix,"TK")==0) + { + suffixChar='T'; + } + else + { + if (strcmp(suffix,"KILL")==0) + { + suffixChar='+'; + } + else + { + suffixChar='-'; + } + } + + codeCount=codes.GetCount(); + for (codeIndex=0;codeIndexSplitCode(code,&positive,&teamkilldummy); + + if (strlen(realnamePrefix)>0) + { + wxString filterCode; + + filterCode = code.Lower(); + filter=filter.Lower(); + if ((filter.Length()>0)&&(!globalStatistics.configData.IsWeaponGroupKey(filterCode))) + { + if (!filterCode.StartsWith(filter)) + { + continue; + } + } + configKey.Printf("/RealNames/%s_%s", + realnamePrefix, + code.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&realName, + (char *)code.GetData()); + } + else + { + realName=code; + } + if (positive) + { + realName="(+)"+realName; + } + else + { + realName="(-)"+realName; + } + if (strlen(suffix)>0) + { + realName+="("; + realName+=suffix; + realName+=")"; + } + prefixedCode=suffixChar+prefixedCode; + listBox->AppendItem(rootItem,realName,-1,-1,new StringTreeItemData(prefixedCode)); + } + listBox->Expand(rootItem); + listBox->Show(); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::OnRightClick(wxTreeEvent &event) +{ + StringTreeItemData *itemData; + wxArrayTreeItemIds selections; + wxString codeSelected; + wxTreeItemId selection; + int selectionCount; + int selectionIndex; + wxTreeCtrl *selectedTree=NULL; + + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","OnRightClick") + selectedCodes.Clear(); + + selectedDefinitionTree=event.GetId(); + switch (selectedDefinitionTree) + { + case WINDOW_ID_WEAPONLIST: + selectedTree=weaponList; + break; + case WINDOW_ID_ACTIONLIST: + selectedTree=actionList; + break; + case WINDOW_ID_LOCATIONLIST: + selectedTree=locationList; + break; + case WINDOW_ID_MISCAWARDLIST: + selectedTree=miscList; + break; + case WINDOW_ID_XPAWARDLIST: + selectedTree=xpList; + break; + } + if (selectedTree!=NULL) + { + selectedTree->GetSelections(selections); + } + selectionCount=selections.GetCount(); + for (selectionIndex=0;selectionIndexGetItemData(selection); + codeSelected=itemData->GetString(); + selectedCodes.Add(codeSelected); + } + + event.SetId(this->GetId()); + GetParent()->AddPendingEvent(event); + + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::AddXPComponent(wxString &code,bool positive) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","AddXPComponent") + awardDefinition->AddXPComponent(code,positive); + xpList->DeleteAllItems(); + xpList->AddRoot(_T("")); + PopulateList(xpList,awardDefinition->xpComponents,"xp",""); + STATSGEN_DEBUG_FUNCTION_END +} + +void AwardDefinitionPanel::RemoveXPComponent(wxString &code) +{ + STATSGEN_DEBUG_FUNCTION_START("AwardDefinitionPanel","RemoveXPComponent") + awardDefinition->RemoveXPComponent(code); + xpList->DeleteAllItems(); + xpList->AddRoot(_T("")); + PopulateList(xpList,awardDefinition->xpComponents,"xp",""); + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/AwardEditorPanel.h b/AwardEditorPanel.h new file mode 100644 index 0000000..01f3262 --- /dev/null +++ b/AwardEditorPanel.h @@ -0,0 +1,145 @@ +#ifndef __AWARDEDITORPANEL +#define __AWARDEDITORPANEL + +#include +#include +#include +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" +#include "AwardDefinition.h" + +class AwardDefinitionPanel : public wxPanel +{ + public: + AwardDefinitionPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn); + virtual ~AwardDefinitionPanel(); + + void AddWeaponComponent(wxString &code,bool kill,bool positive,bool teamkill); + void AddLocationComponent(wxString &code,bool kill,bool positive,bool teamkill); + void AddActionComponent(wxString &code,bool positive); + void AddMiscComponent(wxString &code,bool positive); + void AddXPComponent(wxString &code,bool positive); + + void RemoveWeaponComponent(wxString &code,bool killList,bool teamkillList); + void RemoveLocationComponent(wxString &code,bool killList,bool teamkillList); + void RemoveActionComponent(wxString &code); + void RemoveMiscComponent(wxString &code); + void RemoveXPComponent(wxString &code); + + void OnResize(wxSizeEvent& event); + void OnRightClick(wxTreeEvent& event); + void PopulateList(wxTreeCtrl *listBox, + wxArrayString &codeList, + const char *realnamePrefix, + const char *suffix); + + wxArrayString selectedCodes; + long selectedDefinitionTree; + AwardDefinition *awardDefinition; + wxTreeCtrl *weaponList; + wxTreeCtrl *locationList; + wxTreeCtrl *actionList; + wxTreeCtrl *miscList; + wxTreeCtrl *xpList; + wxStaticText *label; + void SetFilter(wxString &filterString); + + protected: + + private: + wxString awardID; + wxString filter; + + DECLARE_EVENT_TABLE() +}; + +class AwardChoicesPanel : public wxPanel +{ + public: + AwardChoicesPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn); + virtual ~AwardChoicesPanel(); + + void OnResize(wxSizeEvent& event); + void OnRightClick(wxTreeEvent& event); + + wxArrayString selectedCodes; + long selectedChoiceTree; + void SetFilter(wxString &filterString); + + protected: + + private: + void PopulateList(wxTreeCtrl *listBox, + const char *group, + const char *realnamePrefix); + + wxString awardID; + wxTreeCtrl *weaponList; + wxTreeCtrl *locationList; + wxTreeCtrl *actionList; + wxTreeCtrl *miscList; + wxTreeCtrl *xpList; + wxStaticText *label; + wxString filter; + + DECLARE_EVENT_TABLE() +}; + +class AwardEditorPanel : public wxPanel +{ + public: + AwardEditorPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxString &awardIDIn); + virtual ~AwardEditorPanel(); + + void OnResize(wxSizeEvent& event); + void OnRightClick(wxTreeEvent& event); + void OnPopupMenu(wxCommandEvent& event); + void OnConfigChanged(wxCommandEvent &event); + + protected: + + private: + wxString awardID; + GroupedConfigItemsPanel *overallConfig; + AwardChoicesPanel *awardChoices; + AwardDefinitionPanel *awardDefinition; + + wxSplitterWindow *splitter; + DECLARE_EVENT_TABLE() +}; + +class StringTreeItemData : public wxTreeItemData +{ +public: + StringTreeItemData(const wxString& desc) : m_desc(desc) { } + + wxString GetString() const { return m_desc; } + +private: + wxString m_desc; +}; + +#endif diff --git a/BaseConfigItemGUI.h b/BaseConfigItemGUI.h new file mode 100644 index 0000000..e61edb0 --- /dev/null +++ b/BaseConfigItemGUI.h @@ -0,0 +1,25 @@ +#ifndef __BASECONFIGITEMGUI +#define __BASECONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GUITriggerList.h" + +class BaseConfigItemGUI : public wxPanel +{ + public: + virtual void SetLabelWidth(int width)=0; + virtual int GetLabelWidth()=0; + void SetTriggerCondition(GUITriggerList &listIn); + bool UpdateFromTrigger(); + int PreferredHeight(); + protected: + wxString configKey; + GUITriggerList triggerList; +}; + +#endif diff --git a/BaseConfigItemGui.cpp b/BaseConfigItemGui.cpp new file mode 100644 index 0000000..94d978b --- /dev/null +++ b/BaseConfigItemGui.cpp @@ -0,0 +1,25 @@ +// wxWindows includes +#include + +// Statsgen includes +#include "BaseConfigItemGUI.h" +#include "WindowIDs.h" +#include "GlobalStatistics.h" + +void BaseConfigItemGUI::SetTriggerCondition(GUITriggerList &listIn) +{ + triggerList=listIn; +} + +bool BaseConfigItemGUI::UpdateFromTrigger() +{ + bool retVal; + + retVal=triggerList.PerformTrigger(this); + return (retVal); +} + +int BaseConfigItemGUI::PreferredHeight() +{ + return (20); +} diff --git a/BooleanConfigItemGUI.cpp b/BooleanConfigItemGUI.cpp new file mode 100644 index 0000000..c82be8f --- /dev/null +++ b/BooleanConfigItemGUI.cpp @@ -0,0 +1,176 @@ +// Statsgen Includes +#include "BooleanConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "Progress.h" + +BEGIN_EVENT_TABLE(BooleanConfigItemGUI, wxPanel) + EVT_SIZE(BooleanConfigItemGUI::OnResize) + EVT_CHECKBOX(WINDOW_ID_TEXTCTRL_CONFIGVALUE,BooleanConfigItemGUI::OnTextChange) +END_EVENT_TABLE() + +BooleanConfigItemGUI::BooleanConfigItemGUI() +{ + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","Constructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void BooleanConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","OnTextChange") + + if (textEdit.GetValue()) + { + value="Y"; + } + else + { + value="N"; + } + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + STATSGEN_DEBUG(DEBUG_ALWAYS,"Popping event"); + GetParent()->AddPendingEvent(newEvent); + } + STATSGEN_DEBUG_FUNCTION_END +} + +BooleanConfigItemGUI::~BooleanConfigItemGUI() +{ + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","Destructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void BooleanConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","SetConfigKey") + configKey=configKeyIn; + if (configKey.Length()>0) + { +STATSGEN_DEBUG(DEBUG_ALWAYS,"ConfigKeyLength>0") + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); +STATSGEN_DEBUG(DEBUG_ALWAYS,"textEdit.SetValue") + textEdit.SetValue( (value.CmpNoCase("Y")==0)); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void BooleanConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn) +{ + wxSizeEvent event; + + configKey=configKeyIn; + labelText=labelTextIn; + defaultValue=defaultValueIn; + + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","Set") + //SetConfigKey(configKey); + + STATSGEN_DEBUG(DEBUG_ALWAYS,"label.Create") + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + _T("")); + SetConfigKey(configKey); + + OnResize(event); + STATSGEN_DEBUG_FUNCTION_END +} + +wxString BooleanConfigItemGUI::GetValue() +{ + wxString value; + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","GetValue") + + if (textEdit.GetValue()) + { + value="Y"; + } + else + { + value="N"; + } + STATSGEN_DEBUG_FUNCTION_END + return (value); +} + +int BooleanConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","GetLabelWidth") + + itemSize=label.GetSize(); + STATSGEN_DEBUG_FUNCTION_END + return (itemSize.GetWidth()); +} + +void BooleanConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","SetLabelWidth") + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); + STATSGEN_DEBUG_FUNCTION_END +} + +void BooleanConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + + STATSGEN_DEBUG_FUNCTION_START("BooleanConfigItemGUI","OnResize") + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + textEdit.SetSize(labelWidth,0,textWidth,textHeight); + STATSGEN_DEBUG_FUNCTION_END +} diff --git a/BooleanConfigItemGUI.h b/BooleanConfigItemGUI.h new file mode 100644 index 0000000..f095e03 --- /dev/null +++ b/BooleanConfigItemGUI.h @@ -0,0 +1,39 @@ +#ifndef __BOOLEANCONFIGITEMGUI +#define __BOOLEANCONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class BooleanConfigItemGUI : public BaseConfigItemGUI +{ + public: + BooleanConfigItemGUI(); + virtual ~BooleanConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxCheckBox textEdit; + wxStaticText label; + wxString labelText; + wxString defaultValue; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/BoxedDropDown.cpp b/BoxedDropDown.cpp new file mode 100644 index 0000000..998c4fa --- /dev/null +++ b/BoxedDropDown.cpp @@ -0,0 +1,112 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "BoxedDropDown.h" +#include "WindowIDs.h" +#include "ErrorData.h" + +BoxedDropDown::BoxedDropDown() +{ + STATSGEN_DEBUG_FUNCTION_START("BoxedDropDown","BoxedDropDown") + allEntriesAllowed=true; + STATSGEN_DEBUG_FUNCTION_END +} + +void BoxedDropDown::AllEntriesAllowed(bool allEntries) +{ + allEntriesAllowed=allEntries; +} + +BoxedDropDown::~BoxedDropDown() +{ + STATSGEN_DEBUG_FUNCTION_START("BoxedDropDown","~BoxedDropDown") + STATSGEN_DEBUG_FUNCTION_END +} + +bool BoxedDropDown::CreateDialog(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + bool retVal=true; + wxString label; + wxArrayString dropDownEntries; + wxSize itemSize; + wxPoint itemPosition; + wxString msg; + int dropDownWidth; + int dropDownHeight; + int boxWidth; + int boxHeight; + wxString defaultSelection="??"; + wxString dialogName="BoxedDropDown"; + + STATSGEN_DEBUG_FUNCTION_START("BoxedDropDown","CreateDialog") + label=GetLabel(); + DropDownEntries(dropDownEntries,defaultSelection); + if (allEntriesAllowed) + { + dropDownEntries.Insert(AllName(),0); + defaultSelection=AllName(); + } + STATSGEN_DEBUG(DEBUG_ALWAYS,"Create") + Create(parent,id,pos,size,style,name); + STATSGEN_DEBUG(DEBUG_ALWAYS,"staticBox.Create") + staticBox.Create(this,-1,label); + STATSGEN_DEBUG(DEBUG_ALWAYS,"dropDown.Create") + //dropDown=new wxComboBox(&staticBox, + dropDown=new wxComboBox(this, + id, + defaultSelection, + wxDefaultPosition, + wxDefaultSize, + dropDownEntries, + wxCB_DROPDOWN | + wxCB_READONLY, + wxDefaultValidator, + dialogName); + STATSGEN_DEBUG(DEBUG_ALWAYS,"dropDown.SetValue") + dropDown->SetValue(defaultSelection); + STATSGEN_DEBUG(DEBUG_ALWAYS,"dropDown.GetSize") + itemSize=dropDown->GetSize(); + dropDownHeight=itemSize.GetHeight(); + dropDownWidth=itemSize.GetWidth(); + + boxWidth=dropDownWidth+STATIC_BOX_LEFT_GAP+STATIC_BOX_RIGHT_GAP; + boxHeight=dropDownHeight+STATIC_BOX_TOP_GAP+STATIC_BOX_BOTTOM_GAP; + + itemPosition.x=0; + itemPosition.y=0; + STATSGEN_DEBUG(DEBUG_ALWAYS,"staticBox.set size") + staticBox.SetPosition(itemPosition); + staticBox.SetSize(wxSize(boxWidth,boxHeight)); + + itemPosition.x=STATIC_BOX_LEFT_GAP; + itemPosition.y=STATIC_BOX_TOP_GAP; + STATSGEN_DEBUG(DEBUG_ALWAYS,"dropDown.SetPosition") + dropDown->SetPosition(itemPosition); + + STATSGEN_DEBUG(DEBUG_ALWAYS,"SetSize") + SetSize(wxSize(boxWidth+00,boxHeight+00)); + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + + +wxString BoxedDropDown::GetSelectedCode() +{ + wxString name; + wxString code; + + name=dropDown->GetValue(); + + code=FindCodeFromName(name); + + return (code); +} + diff --git a/BoxedDropDown.h b/BoxedDropDown.h new file mode 100644 index 0000000..bde6e90 --- /dev/null +++ b/BoxedDropDown.h @@ -0,0 +1,41 @@ +#ifndef __BOXEDDROPDOWN +#define __BOXEDDROPDOWN + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class BoxedDropDown : public wxPanel +{ + public: + BoxedDropDown(); + void AllEntriesAllowed(bool allEntries); + virtual ~BoxedDropDown(); + bool CreateDialog(wxWindow *parent, + wxWindowID id, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + wxString GetSelectedCode(); + + protected: + virtual wxString GetLabel()=0; + virtual wxString AllCode()=0; + virtual wxString AllName()=0; + virtual wxString FindCodeFromName(wxString &code)=0; + virtual void DropDownEntries(wxArrayString &entries, + wxString &defaultSelection)=0; + + private: + bool allEntriesAllowed; + wxStaticBox staticBox; + wxComboBox *dropDown; + +}; + + +#endif diff --git a/COD5LogFileReader.cpp b/COD5LogFileReader.cpp new file mode 100644 index 0000000..5d75c24 --- /dev/null +++ b/COD5LogFileReader.cpp @@ -0,0 +1,153 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "COD5LogFileReader.h" +#include "GlobalStatistics.h" +#include "ErrorData.h" + +void COD5LogFileReader::AddDefaultNonAction(const char *action) +{ + wxString key; + + key=action; + + if (nonActions.Index(key)==wxNOT_FOUND) + { + nonActions.Add(key); + } +} + +COD5LogFileReader::COD5LogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn) : LogFileReader(filenameIn,serverTypeIn) +{ + STATSGEN_DEBUG_FUNCTION_START("COD5LogFileReader","Constructor"); + wxString configGroup; + + configGroup="COD5NonActions"; + + globalStatistics.configData.ReadList(configGroup,nonActions); + + AddDefaultNonAction("J"); // Join + AddDefaultNonAction("Q"); // Quit + AddDefaultNonAction("W"); // Team Win + AddDefaultNonAction("L"); // Team Loss + AddDefaultNonAction("T"); // Team Tie + + globalStatistics.configData.WriteList(configGroup,nonActions); + STATSGEN_DEBUG_FUNCTION_END +} + +bool COD5LogFileReader::DecodeAction(wxString &line,DecodedAction &decode) +{ + bool retVal=false; + int tokenCount; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("COD5LogFileReader","DecodeAction") + decode.action=GetLineToken(line,";",1,&tokenCount).Upper(); + if (tokenCount == 4) + { + decode.playerID=GetLineToken(line,";",2,&tokenCount); + decode.playerRoundID=GetLineToken(line,";",3,&tokenCount); + decode.playerName=GetLineToken(line,";",4,&tokenCount); + decode.playerTeam=""; + UpdatePlayerRoundInfo2(decode.playerID, + playerIDs, + playerTeamList, + decode.playerTeam); + retVal=(nonActions.Index(decode.action)==wxNOT_FOUND); + + + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool COD5LogFileReader::DecodeTeamWin(wxString &line,DecodedTeamWin &decode) +{ + bool retVal=false; + int tokenCount; + int tokenIndex=0; + wxString name; + wxString id; + wxString roundID; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeTeamWin"); + roundID=""; + + retVal=DecodeTeamWinLoss("W;",line,id,roundID,name,decode.teamName); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Normal Team Win Found") + decode.Clear(); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + + +bool COD5LogFileReader::DecodeTeamWinLoss(const char *key,wxString &line,wxString &id, wxString &roundID,wxString &name, wxString &team) +{ + bool retVal=false; + int tokenCount; + + STATSGEN_DEBUG_FUNCTION_START("COD5LogFileReader","DecodeTeamWinLoss"); + + if (line.StartsWith(key)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Team Win or Loss Found") + id=GetLineToken(line,";",2,&tokenCount); + if (tokenCount == 4) + { + roundID=GetLineToken(line,";",3,&tokenCount); + name=GetLineToken(line,";",4,&tokenCount); + UpdatePlayerRoundInfo2(id, + playerIDs, + playerTeamList, + team); + retVal=true; + + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool COD5LogFileReader::DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode) +{ + bool retVal=false; + int tokenCount; + int tokenIndex=0; + wxString name; + wxString id; + wxString roundID; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeTeamLoss"); + roundID=""; + + retVal=DecodeTeamWinLoss("L;",line,id,roundID,name,decode.teamName); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Normal Team Loss Found") + decode.Clear(); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} diff --git a/COD5LogFileReader.h b/COD5LogFileReader.h new file mode 100644 index 0000000..986efad --- /dev/null +++ b/COD5LogFileReader.h @@ -0,0 +1,32 @@ +#ifndef __COD5LOGFILEREADER +#define __COD5LOGFILEREADER + +// wxWindows includes +#include +#include +#include +#include +#include + +// statsgen includes +#include "LogFileReader.h" + +class COD5LogFileReader : public LogFileReader +{ + public: + COD5LogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn); + virtual bool DecodeAction(wxString &line,DecodedAction &decode); + bool DecodeTeamWin(wxString &line,DecodedTeamWin &decode); + bool DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode); + bool DecodeTeamWinLoss(const char *key,wxString &line,wxString &id,wxString &roundID, wxString &name, wxString &team); + protected: + + protected: + wxArrayString nonActions; + + private: + void AddDefaultNonAction(const char *action); + +}; + +#endif diff --git a/CODBanFile.cpp b/CODBanFile.cpp new file mode 100644 index 0000000..33253d2 --- /dev/null +++ b/CODBanFile.cpp @@ -0,0 +1,73 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "GlobalStatistics.h" +#include "Progress.h" +#include "CODBanFile.h" + +CODBanFile::CODBanFile(wxFileName &filenameIn) +{ + filename=filenameIn; + LoadFile(); +} + +CODBanFile::~CODBanFile() +{ +} + +void CODBanFile::LoadFile() +{ + int banCount; + int banIndex; + wxTextFile fp; + bool retVal; + wxString status; + wxString line; + wxString name; + wxString guid; + + status="Reading Ban File"; progress->SetStatus(status); + retVal=fp.Open(filename.GetFullPath()); + + names.Clear(); + + if (retVal) + { + banCount=fp.GetLineCount(); + for (banIndex=0;banIndex0) + { + guid=line.BeforeFirst(' '); + name=line.AfterFirst(' '); + + names.Add(name); + } + } + } +} + +void CODBanFile::AddToDropList() +{ + int banCount; + int banIndex; + wxString name; + + banCount=names.GetCount(); + for (banIndex=0;banIndex +#include +#include + +// Statsgen Includes + +class CODBanFile +{ + public: + CODBanFile(wxFileName &filenameIn); + virtual ~CODBanFile(); + void AddToDropList(); + + private: + void LoadFile(); + wxFileName filename; + + wxArrayString names; + +}; + + +#endif diff --git a/Cheater.cpp b/Cheater.cpp new file mode 100644 index 0000000..bb35258 --- /dev/null +++ b/Cheater.cpp @@ -0,0 +1,91 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "Cheater.h" +#include "GlobalStatistics.h" + +Cheaters::Cheaters() +{ + names.Clear(); +} + +Cheaters::~Cheaters() +{ +} + +void Cheaters::CreateDatabase() +{ + wxString SQL; + + SQL=SQLCreateTable(); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + +} + +wxString Cheaters::SQLTableName() +{ + wxString tableName; + + tableName="cheaters"; + + return (tableName); +} + +wxString Cheaters::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "name string" + ")", + SQLTableName().GetData()); + + return SQL; +} + +bool Cheaters::WriteToDatabase() +{ + wxString SQL; + bool retVal=true; + int nameCount; + int nameIndex; + wxString name; + + nameCount=names.GetCount(); + for (nameIndex=0;nameIndex +#include + +// Statsgen Includes + +class Cheaters +{ + public: + Cheaters(); + virtual ~Cheaters(); + + bool WriteToDatabase(); + void CreateDatabase(); + void Clear(); + static wxString SQLTableName(); + static wxString SQLCreateTable(); + void Add(wxString &name); + wxArrayString names; + +}; + + +#endif diff --git a/Clan.cpp b/Clan.cpp new file mode 100644 index 0000000..4c73bb3 --- /dev/null +++ b/Clan.cpp @@ -0,0 +1,117 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "Clan.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +void Clan::ReadConfig() +{ + wxString configBase; + wxString configKey; + wxString configValue; + wxString baseGroup; + + baseGroup="Clan"+id; + + configBase.Printf("/%s/",baseGroup.GetData()); + configKey=configBase+"TagColoured"; + globalStatistics.configData.ReadTextValue(configKey,&tag,""); + configKey=configBase+"FullName"; + globalStatistics.configData.ReadTextValue(configKey,&name,""); + configKey=configBase+"WebAddress"; + globalStatistics.configData.ReadTextValue(configKey,&webAddress,""); + configKey=configBase+"BannerAddress"; + globalStatistics.configData.ReadTextValue(configKey,&banner,""); + configKey=configBase+"RegExp"; + globalStatistics.configData.ReadTextValue(configKey,®ExpString,""); + regExp=new wxRegEx(); + regExp->Compile(regExpString); +} + +Clan::Clan(wxString &idIn) +{ + + id=idIn; + + ReadConfig(); + + +} + +Clan::~Clan() +{ + delete (regExp); +} + +wxString Clan::SQLTableName() +{ + wxString tableName="clan"; + + return (tableName); +} + +wxString Clan::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "clanindex integer," + "%s," + "%s," + "%s," + "%s" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("tag","clantag",FIELD_WIDTH_CLAN_TAG).GetData(), + StatsgenDatabase::StringFieldDefinition("name","clanname",FIELD_WIDTH_CLAN_NAME).GetData(), + StatsgenDatabase::StringFieldDefinition("webaddress","clannweb",FIELD_WIDTH_CLAN_WEBADDRESS).GetData(), + StatsgenDatabase::StringFieldDefinition("banner","clanbanner",FIELD_WIDTH_CLAN_BANNER).GetData() +); + + return SQL; +} + +bool Clan::WriteToDatabase(int itemIndex) +{ + wxString SQL; + bool retVal=true; + + SQL.Printf("Insert into %s" + "(clanindex,tag,name,webaddress,banner)" + "values('%d','%s','%s','%s','%s')", + SQLTableName().GetData(), + itemIndex, + tag.GetData(), + name.GetData(), + webAddress.GetData(), + banner.GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} + +void Clan::WriteConfig() +{ + wxString configBase; + wxString configKey; + wxString configValue; + wxString baseGroup; + + baseGroup="Clan"+id; + +} + +bool Clan::IsMember(wxString &name) +{ + wxString decoloured; + bool retVal; + + decoloured=DecolouriseName(name); + retVal=regExp->Matches(decoloured); + return (retVal); +} + diff --git a/Clan.h b/Clan.h new file mode 100644 index 0000000..d33d1f5 --- /dev/null +++ b/Clan.h @@ -0,0 +1,39 @@ +#ifndef __CLANDEFINITION +#define __CLANDEFINITION + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen Includes + +class Clan; + +WX_DECLARE_OBJARRAY(Clan,ArrayOfClan); +class Clan +{ + public: + void ReadConfig(); + void WriteConfig(); + Clan(wxString &idIn); + virtual ~Clan(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int itemIndex); + bool IsMember(wxString &name); + + wxString tag; + wxString name; + wxString webAddress; + wxString banner; + wxString regExpString; + wxRegEx *regExp; + + wxString id; + +}; + + +#endif diff --git a/ClanEditorPanel.cpp b/ClanEditorPanel.cpp new file mode 100644 index 0000000..2e24764 --- /dev/null +++ b/ClanEditorPanel.cpp @@ -0,0 +1,161 @@ +// wx includes +#include +#include +#include +#include + +// Statsgen Includes +#include "ClanEditorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(ClanEditorPanel, GenericConfigPanel) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_PLAYERCACHE, + ClanEditorPanel::OnPlayerRightClick) + EVT_MENU(PLAYER_POPUP_SELECT,ClanEditorPanel::OnPopupMenu) +END_EVENT_TABLE() + +ClanEditorPanel::ClanEditorPanel(wxString &configGroupIn, + wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) : + GenericConfigPanel( + parent, + id, + pos, + size, + style, + name) +{ + playerCache=NULL; + configGroup=configGroupIn; + + wxString labelText="Regular Expression"; + wxString configKey; + + GroupedConfigItemsPanel *clanPanel; + + clanPanel=new GroupedConfigItemsPanel("Clan Details"); + clanPanel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey.Printf("/%s/TagColoured",configGroup.GetData()); + clanPanel->Add("Coloured Tag",configKey,"",-1); + configKey.Printf("/%s/FullName",configGroup.GetData()); + clanPanel->Add("Coloured Name",configKey,"",-1); + configKey.Printf("/%s/WebAddress",configGroup.GetData()); + clanPanel->Add("Web Address",configKey,"",-1); + configKey.Printf("/%s/BannerAddress",configGroup.GetData()); + clanPanel->Add("Banner Image Address",configKey,"",-1); + + AddConfigGroup(clanPanel); + + configKey.Printf("/%s/RegExp",configGroup.GetData()); + playerCache=new PlayerCachePanel(configKey,labelText); + + playerCache->SetFilterType(PlayerCachePanel::FILTER_TYPE_REGEXP); + playerCache->Create(this, + WINDOW_ID_PLAYERCACHE, + wxDefaultPosition, + wxDefaultSize); + AddConfigGroup(playerCache); +} + +void ClanEditorPanel::OnPlayerRightClick(wxListEvent &event) +{ + wxString msg; + wxString menuItem; + wxMenu popupMenu(_T("")); + wxArrayInt selectedPlayers; + int cacheCount; + + // Right clicked on an item in the Player Cache + playerCache->GetSelectedPlayers(selectedPlayers); + cacheCount=selectedPlayers.GetCount(); + + if (cacheCount>1) + { + menuItem="Auto Regular Expression"; + popupMenu.Append(PLAYER_POPUP_SELECT,menuItem); + } + popupMenu.Append(PLAYER_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void ClanEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + wxString msg; + int id; + wxArrayInt selectedPlayers; + PlayerCacheEntry cacheEntry; + int cacheCount; + int cacheIndex; + int selectedIndex; + int playerIndex; + wxString longestMatch; + wxString decolouredName; + int length; + int charIndex; + + id=event.GetId(); + msg.Printf("ClanEditorPanel::OnPopupMenu():Event Received %d",id); + playerCache->GetSelectedPlayers(selectedPlayers); + cacheCount=selectedPlayers.GetCount(); + switch (event.GetId()) + { + case PLAYER_POPUP_SELECT: + if (cacheCount>1) + { + playerIndex=selectedPlayers.Item(0); + cacheEntry=globalStatistics.playerCache.Item(playerIndex); + longestMatch=DecolouriseName(cacheEntry.name); + for (cacheIndex=1;cacheIndexdecolouredName.Length()) + { + length=decolouredName.Length(); + } + + // now we need to scan each character + // in the longest match and the decoloured name + // and match when we reach a new character + for (charIndex=0;charIndex0) + { + // found a common piece of string + // convert it to a regular expression + wxString regularExpression="^"; + length=longestMatch.Length(); + for (charIndex=0;charIndexSetFilter(regularExpression); + } + else + { + wxMessageBox(_T("Could not find a common match in names")); + } + } + } + break; + } +} diff --git a/ClanEditorPanel.h b/ClanEditorPanel.h new file mode 100644 index 0000000..40792d9 --- /dev/null +++ b/ClanEditorPanel.h @@ -0,0 +1,40 @@ +#ifndef __CLANEDITORPANEL +#define __CLANEDITORPANEL + +#include +#include + +// Statsgen Includes +#include "PlayerCachePanel.h" +#include "PlayerCacheEntry.h" +#include "GenericConfigPanel.h" +#include "WindowIDs.h" + +class ClanEditorPanel : public GenericConfigPanel +{ + public: + ClanEditorPanel(wxString &configGroup, + wxWindow *parent, + wxWindowID id=-1, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + void OnPlayerRightClick(wxListEvent &event); + void OnPopupMenu(wxCommandEvent &event); + + protected: + + + private: + enum + { + PLAYER_POPUP_SELECT=1000, + PLAYER_POPUP_CANCEL + }; + PlayerCachePanel *playerCache; + wxString configGroup; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ConfigData.cpp b/ConfigData.cpp new file mode 100644 index 0000000..3177b66 --- /dev/null +++ b/ConfigData.cpp @@ -0,0 +1,870 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "ConfigData.h" +#include "ErrorData.h" +#include "StaticFunctions.h" +#include "GlobalStatistics.h" + +ConfigData::ConfigData() +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigData","Constructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigData::Initiate() +{ + wxFileName baseDirectory(wxGetApp().argv[0]); + wxFileName tempIniFile; + + STATSGEN_DEBUG_FUNCTION_START("ConfigData","Initiate") + + tempIniFile=baseDirectory; + tempIniFile.MakeAbsolute(); + tempIniFile.SetFullName("statsgen2.ini"); + + Initiate(tempIniFile); + + STATSGEN_DEBUG_FUNCTION_END +} + +ConfigData::~ConfigData() +{ + weaponGroupCache.Close(); + Close(); +} + +void ConfigData::Close() +{ + if (configFile!=NULL) + { + delete configFile; + } + configFile=NULL; +} + +int ConfigData::FindConfigCacheEntry(wxString &key) +{ + int cacheIndex; + int foundIndex; + int cacheCount; + ConfigItem configItem; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("ConfigData","FindConfigCacheEntry") + STATSGEN_DEBUG(DEBUG_RARELY,key); + cacheCount=configKeys.GetCount(); + foundIndex=-1; + for (cacheIndex=0;cacheIndexWrite(configItem.key,configItem.value); + } + else + { + cacheIndex++; + } + } + + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Written non-committed data to config") + // We have stepped through every cache entry and written + // them to the config file now remove any groups that are + // in the deleted groups list + groupCount=groupsDeleted.GetCount(); + STATSGEN_DEBUG_CODE(errorMessage.Printf("delete groups list=%d",groupCount);) + STATSGEN_DEBUG(DEBUG_SOMETIMES,errorMessage) + for (groupIndex=0;groupIndexDeleteGroup(group); + } + groupsDeleted.Clear(); + // - flush the file to ensure + // it all is actually written + configFile->Flush(); + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigData::EmptyCache() +{ + configKeys.Clear(); +} + +bool ConfigData::ReadTextValue(wxString &key,wxString *value) +{ + int cacheIndex; + bool retVal=false; + ConfigItem configItem; + wxString errorMessage; + + // Here we need to read a config item from the + // config cache. If we cannot find the config item + // we can then attempt to read it from the config file + // itself. + cacheIndex=FindConfigCacheEntry(key); + if (cacheIndex>=0) + { + // Found an entry in the cache + configItem=configKeys.Item(cacheIndex); + *value=configItem.value; + retVal=true; + } + else + { + // Not found it in the cache + // search for it in the actual config file + if (!configFile->Read(key,value)) + { + // Not in the cache or the real file + retVal=false; + } + else + { + // Found it in the real file + // Add it to the cache now + configItem.key=key; + configItem.value=(*value); + configItem.committed=true; + configKeys.Add(configItem); + retVal=true; + } + } + + return (retVal); +} + +bool ConfigData::ReadTextValue(char *key,wxString *value) +{ + wxString keyString; + + keyString=key; + return(ReadTextValue(keyString, value)); +} + +bool ConfigData::ReadTextValue(wxString &key,wxString *value,char *defaultValue) +{ + bool retVal; + + retVal=ReadTextValue(key,value); + if (retVal==false) + { + WriteTextValue(key,defaultValue); + *value=defaultValue; + } + else + { + if (strlen(defaultValue)>0) + { + if (value->Length()==0) + { + WriteTextValue(key,defaultValue); + *value=defaultValue; + } + } + } + + return (retVal); +} + +bool ConfigData::ReadTextValue(char *key,wxString *value,char *defaultValue) +{ + wxString keyString; + + keyString=key; + return(ReadTextValue(keyString, value, defaultValue)); +} + +void ConfigData::WriteTextValue(wxString &key,wxString &value) +{ + int cacheIndex; + ConfigItem configItem; + + // First try and find it in the cache + cacheIndex=FindConfigCacheEntry(key); + if (cacheIndex>=0) + { + // Found a cache entry - just remove it + // We are gonna add a new cache entry + // regardless + configKeys.RemoveAt(cacheIndex); + } + + configItem.key=key; + configItem.value=value; + configItem.committed=false; + configKeys.Add(configItem); +} + +void ConfigData::WriteTextValue(wxString &key,char *value) +{ + wxString valueString; + + valueString=value; + WriteTextValue(key,valueString); +} + +void ConfigData::WriteTextValue(char *key,wxString &value) +{ + wxString keyString; + + keyString=key; + WriteTextValue(keyString,value); +} + +void ConfigData::WriteTextValue(char *key,char *value) +{ + wxString valueString; + wxString keyString; + + valueString=value; + keyString=key; + WriteTextValue(keyString,valueString); +} + +bool ConfigData::ReadGroup(wxString &group, + wxArrayString &keys, + wxArrayString &values) +{ + bool retVal=true; + long cookie=-1; + bool moreConfigItems; + wxString configItem; + wxString msg; + wxString configPath; + wxString configValue; + wxString configKey; + int index; + int count; + + keys.Clear(); + values.Clear(); + + STATSGEN_DEBUG_FUNCTION_START("ConfigData","ReadGroup") + STATSGEN_DEBUG(DEBUG_RARELY,group) + + configPath="/"+group+"/"; + configFile->SetPath(configPath); + moreConfigItems=configFile->GetFirstEntry(configItem,cookie); + while (moreConfigItems) + { + keys.Add(configItem); + moreConfigItems=configFile->GetNextEntry(configItem,cookie); + } + + count=keys.GetCount(); + for (index=0;indexSetExpandingEnvVars(false); + + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigData::Export(wxArrayString &upgradeList, + ConfigData &sourceConfig, + char *description, + char *group, + int exportType, + int exportAnswerType, + char *recommendation) +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigData","Export") + + wxArrayString keys; + wxArrayString values; + int keyCount; + int keyIndex; + wxString configKey; + wxString configValue; + wxString outputConfigKey; + wxString groupStr; + + groupStr=group; + upgradeList.Add(groupStr); + sourceConfig.ReadGroup(group,keys,values); + keyCount=keys.GetCount(); + outputConfigKey="/"; + outputConfigKey+=group; + outputConfigKey+="/UPGRADEDESCRIPTION"; + WriteTextValue(outputConfigKey,description); + outputConfigKey="/"; + outputConfigKey+=group; + outputConfigKey+="/UPGRADERECOMMENDATION"; + WriteTextValue(outputConfigKey,recommendation); + outputConfigKey="/"; + outputConfigKey+=group; + outputConfigKey+="/UPGRADEANSWERTYPE"; + configValue.Printf("%d",exportAnswerType); + WriteTextValue(outputConfigKey,configValue); + + for (keyIndex=0;keyIndex0)) + { + outputConfigKey="/"; + outputConfigKey+=group; + outputConfigKey+="/"; + outputConfigKey+=configKey; + WriteTextValue(outputConfigKey,configValue); + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigData::ReadGroupList(wxArrayString &listOfGroups) +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigData","ReadGroupList") + wxString groupName; + long index=0; + bool moreEntries; + + // ReadGroupList does not work properly - for some reason after 2 reads it + // no longer gets a list + // + Close(); + Initiate(); + + listOfGroups.Clear(); + moreEntries=configFile->GetFirstGroup(groupName,index); + + while (moreEntries) + { + listOfGroups.Add(groupName); + moreEntries=configFile->GetNextGroup(groupName,index); + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigData::UpgradeDetails(wxString &description,wxString &upgradeType) +{ + wxString configKeyDescription="/UPGRADELIST/Description"; + wxString configKeyType="/UPGRADELIST/UpgradeType"; + wxString configGroup="UPGRADELIST"; + wxArrayString groups; + + description=""; + upgradeType=""; + + ReadList((char *)configGroup.GetData(),groups); + ReadTextValue(configKeyDescription,&description); + ReadTextValue(configKeyType,&upgradeType); + if (groups.GetCount()>0) + { + upgradeType=UPGRADE_TYPE_CONFIG; + } + else + { + if (upgradeType.Length()==0) + { + upgradeType=UPGRADE_TYPE_UNKNOWN; + } + } + + if (description.Length()==0) + { + description=iniFilename.GetFullName(); + } +} + +wxArrayString ConfigData::ReadWeaponGroups() +{ + wxArrayString groups; + int groupCount; + int groupIndex; + wxString group; + wxArrayString weaponGroups; + + ReadGroupList(groups); + + groupCount=groups.GetCount(); + for (groupIndex=0;groupIndexGetCount(); + } + for (groupIndex=0;groupIndexItem(groupIndex); + retVal|=WeaponMatches(weaponKey,group); + if (retVal) + { + break; + } + } + } + else + { + retVal=(weaponKey.CmpNoCase(weaponGroupOrKey)==0); + } + return (retVal); +} + diff --git a/ConfigData.h b/ConfigData.h new file mode 100644 index 0000000..85e84a8 --- /dev/null +++ b/ConfigData.h @@ -0,0 +1,116 @@ +#ifndef __CONFIGDATA +#define __CONFIGDATA + +// wxWindows includes +#include +#include +#include +#include +#include + +// Statsgen Includes +#include "ConfigItem.h" + +#define CONFIG_EXPORT_SET_ONLY 0 +#define CONFIG_EXPORT_ALL 1 + +#define CONFIG_ANSWER_TYPE_ASK 0 +#define CONFIG_ANSWER_TYPE_USE_LAST 1 + +#define UPGRADE_TYPE_CONFIG "Configuration File" +#define UPGRADE_TYPE_DATABASE "Database Contents" +#define UPGRADE_TYPE_UNKNOWN "Unknown" + +#define CONFIG_WEAPON_GROUP_PREFIX "weapongroup_" + +class WeaponGroupCache +{ + public: + WeaponGroupCache(); + ~WeaponGroupCache(); + void Open(); + void Close(); + bool WeaponMatches(wxString &weaponKey,wxString &weaponGroupOrKey); + wxArrayString *ReadWeaponGroup(wxString &weaponGroupOrKey); + private: + bool cacheOpen; + wxArrayString weaponGroups; + wxArrayPtrVoid weaponGroupsContents; + +}; + +class ConfigData +{ + public: + ConfigData(); + void Initiate(); + void Initiate(wxFileName &iniFilename); + virtual ~ConfigData(); + void UpgradeDetails(wxString &description,wxString &upgradeType); + void Export(wxArrayString &upgradeList, + ConfigData &sourceConfig, + char *description, + char *group, + int exportType, + int exportAnswerType, + char *recommendation); + + void CommitChanges(); + void RollbackChanges(); + void EmptyCache(); + bool ReadTextValue(char *key,wxString *value); + bool ReadTextValue(wxString &key,wxString *value); + bool ReadTextValue(char *key,wxString *value,char *defaultValue); + bool ReadTextValue(wxString &key,wxString *value,char *defaultValue); + void WriteTextValue(wxString &key,wxString &value); + void WriteTextValue(char *key,wxString &value); + void WriteTextValue(wxString &key,char *value); + void WriteTextValue(char *key,char *value); + bool ReadList(char *group,wxArrayString &list); + bool ReadList(wxString &group,wxArrayString &list); + + bool ReadList(char *group,wxString &subGroup,wxArrayString &list); + bool ReadList(wxString &group,wxString &subGroup,wxArrayString &list); + bool ReadList(char *group,char *subGroup,wxArrayString &list); + bool ReadList(wxString &group,char *subGroup,wxArrayString &list); + + bool WriteList(char *group,wxArrayString &list); + bool WriteList(wxString &group,wxArrayString &list); + + bool WriteList(char *group,char *subGroup,wxArrayString &list); + bool WriteList(wxString &group,char *subGroup,wxArrayString &list); + + bool WriteList(char *group,wxString &subGroup,wxArrayString &list); + bool WriteList(wxString &group,wxString &subGroup,wxArrayString &list); + bool ReadGroup(char *group, + wxArrayString &keys, + wxArrayString &values); + bool ReadGroup(wxString &group, + wxArrayString &keys, + wxArrayString &values); + bool DeleteGroup(wxString &group); + bool DeleteGroup(char *group); + void ReadGroupList(wxArrayString &listOfGroups); + wxArrayString ReadWeaponGroups(); + wxArrayString ReadWeaponGroup(wxString &weaponGroup); + bool WeaponMatches(wxString &weaponKey,wxString &weaponGroupOrKey); + bool IsWeaponGroupKey(wxString &key); + wxArrayString WeaponGroupKeys(wxString &key); + void Close(); + void OpenWeaponGroupCache(); + void CloseWeaponGroupCache(); + + private: + int FindConfigCacheEntry(wxString &key); + + private: + void PurgeDeletedEntry(wxString &configKey); + + ArrayOfConfigItem configKeys; + wxArrayString groupsDeleted; + wxFileConfig *configFile; + wxFileName iniFilename; + WeaponGroupCache weaponGroupCache; +}; + +#endif diff --git a/ConfigEditorGUI.cpp b/ConfigEditorGUI.cpp new file mode 100644 index 0000000..a7d16b7 --- /dev/null +++ b/ConfigEditorGUI.cpp @@ -0,0 +1,463 @@ +// Statsgen Includes +#include "ConfigEditorGUI.h" +#include "GlobalStatistics.h" +#include "BoxedDropDown.h" +#include "LogFileReader.h" + +BEGIN_EVENT_TABLE(ConfigEditorGUI, wxDialog) + EVT_SIZE(ConfigEditorGUI::OnResize) + EVT_LIST_ITEM_ACTIVATED(WINDOW_ID_LISTBOX_CONFIGITEMS, + ConfigEditorGUI::OnListItemSelected) + EVT_LIST_ITEM_SELECTED(WINDOW_ID_LISTBOX_CONFIGITEMS, + ConfigEditorGUI::OnListItemSelected) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,ConfigEditorGUI::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,ConfigEditorGUI::OnQuit) + // EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,ConfigEditorGUI::OnTextChange) + EVT_COMBOBOX(WINDOW_ID_BOXED_DROPDOWN_FILTER1,ConfigEditorGUI::OnFilterChanged) + EVT_COMBOBOX(WINDOW_ID_BOXED_DROPDOWN_FILTER2,ConfigEditorGUI::OnFilterChanged) +END_EVENT_TABLE() + +ConfigEditorGUI::ConfigEditorGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + BoxedDropDown *filter1In, + BoxedDropDown *filter2In, + GroupedConfigItemsPanel *configPanelIn, + bool drawImagesIn): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","ConfigEditorGUI") + // Zero things out + configKeys.Clear(); + configDisplayNames.Clear(); + filter1=filter1In; + filter2=filter2In; + configPanel=configPanelIn; + drawImages=drawImagesIn; + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + wxString label="Enter Data"; + wxString defaultValue=""; + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","OnTextChange") + + value=valueText.GetValue(); + //globalStatistics.configData.WriteTextValue(lastSelectedKey, + // value); + valueText.SetConfigKey(lastSelectedKey); + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void ConfigEditorGUI::OnSave(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void ConfigEditorGUI::OnListItemSelected(wxListEvent& event) +{ + wxString msg; + int configIndex; + wxString value; + wxString label="Enter Data"; + wxString defaultValue=""; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","OnListItemSelected") + configIndex=(int)event.GetData(); + lastSelectedKey=configKeys.Item(configIndex); + valueText.SetConfigKey(lastSelectedKey); + if (drawImages) + { + wxString configKey; + wxString localOutputFolder; + wxString imageFilename; + + configKey="/General/LocalOutput"; + globalStatistics.configData.ReadTextValue(configKey,&localOutputFolder); + imageFilename=localOutputFolder; + imageFilename+="\\"; + imageFilename+=valueText.GetValue(); + if (wxFileExists(imageFilename)) + { + wxImage imageFile; + + imageFile.LoadFile(imageFilename); + //imagePanel->SetSize(imagePanelX,imagePanelY, + // imagePanelWidth,imagePanelHeight); + imagePanel->Scale(1.0); + imagePanel->SetImage(imageFile); + + imagePanel->Proportion(imagePanelWidth,imagePanelHeight); + imageFile.Destroy(); + } + else + { + imagePanel->Clear(); + } + } + //globalStatistics.configData.ReadTextValue(lastSelectedKey,&value); + //valueText.SetValue(value); + STATSGEN_DEBUG_FUNCTION_END + +} + +ConfigEditorGUI::~ConfigEditorGUI() +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","~ConfigEditorGUI") + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::PopulateConfigItems() +{ + wxListItem listColumn; + int count; + int index; + long listIndex; + wxString name; + wxString msg; + wxString filterString1=""; + wxString filterString2=""; + int tokenCount; + wxString keyPart1; + wxString keyPart2; + wxString key; + bool filtered; + wxSizeEvent event; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","PopulateConfigItems") + if (filter1!=NULL) + { + filterString1=filter1->GetSelectedCode(); + } + if (filter2!=NULL) + { + filterString2=filter2->GetSelectedCode(); + } + + configItems.DeleteAllColumns(); + configItems.DeleteAllItems(); + listColumn.SetText(_T("Key")); + listColumn.SetWidth(100); + configItems.InsertColumn(0,listColumn); + + count=configKeys.GetCount(); + for (index=0;index0) && + (filterString1.CmpNoCase(keyPart1)!=0)) + { + filtered=true; + } + if ((filterString2.Length()>0) && + (filterString2.CmpNoCase(keyPart2)!=0)) + { + filtered=true; + } + if (globalStatistics.configData.IsWeaponGroupKey(key)) + { + filtered=false; + } + if (!filtered) + { + listIndex=configItems.InsertItem((long)index,name,0); + configItems.SetItemData(listIndex,index); + } + } + OnResize(event); + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::CreateDialog() +{ + wxString configKey=""; + wxString configValue=""; + wxString label="Enter Data"; + wxString defaultValue=""; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + int configItemsStyle=wxLC_REPORT | + wxLC_SINGLE_SEL | + wxLC_SORT_ASCENDING; + wxString configItemsTitle="List Box"; + wxString valueTextValue=""; + wxPoint valueTextPosition=wxDefaultPosition; + wxSize valueTextSize=wxDefaultSize; + int valueTextStyle=0; + wxString valueTextName="Value"; + wxString key; + wxString value; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","CreateDialog") + configItems.Create(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + configItemsPosition, + configItemsSize, + configItemsStyle, + wxDefaultValidator, + configItemsTitle); + + + STATSGEN_DEBUG(DEBUG_ALWAYS,"configItems.Create") + //valueText.Create(this, + // WINDOW_ID_TEXTCTRL_CONFIGVALUE, + // valueTextValue, + // valueTextPosition, + // valueTextSize, + // valueTextStyle, + // wxDefaultValidator, + // valueTextName); + valueText.Create(this,-1,valueTextPosition,valueTextSize); + STATSGEN_DEBUG(DEBUG_ALWAYS,"valueText.Create") + valueText.Set(configKey,label,defaultValue,-1); + STATSGEN_DEBUG(DEBUG_ALWAYS,"valueText.Set") + + if (filter1!=NULL) + { + filter1->CreateDialog(this, + WINDOW_ID_BOXED_DROPDOWN_FILTER1); + } + STATSGEN_DEBUG(DEBUG_ALWAYS,"filter1.CreateDialog") + if (filter2!=NULL) + { + filter2->CreateDialog(this, + WINDOW_ID_BOXED_DROPDOWN_FILTER2); + } + STATSGEN_DEBUG(DEBUG_ALWAYS,"filter.Created") + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + STATSGEN_DEBUG(DEBUG_ALWAYS,"buttons.Created") + if (drawImages) + { + imagePanel=new ImagePanel(this, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("imagepanel")); + } + + PopulateConfigItems(); + STATSGEN_DEBUG_FUNCTION_END + +} + +void ConfigEditorGUI::DisplayDialog() +{ + int dialogRetVal; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","DisplayDialog") + // Called when we want to pop the dialog box + // into existance for the first time + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + // We have been asked to save the changes + // just commit the config changes + globalStatistics.configData.CommitChanges(); + break; + case WINDOW_ID_BUTTON_QUIT: + default: + // We have been asked to quit without saving + // rollback the config changes + globalStatistics.configData.RollbackChanges(); + break; + } + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::AddConfigKey( + wxString &group, + wxString &configKey, + bool useRealName) +{ + wxString displayName; + wxString key; + wxString fullKey; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","AddConfigKey") + fullKey="/"+group+"/"+configKey; + configKeys.Add(fullKey); + configBaseKeys.Add(configKey); + if (useRealName) + { + key="/RealNames/"+configKey; + globalStatistics.configData.ReadTextValue(key, + &displayName, + (char *)configKey.GetData()); + displayName+=("("); + displayName+=(configKey); + displayName+=(")"); + } + else + { + displayName=configKey; + } + + configDisplayNames.Add(displayName); + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + wxSize itemSize; + wxPoint itemPosition; + int configItemsHeight; + int configItemsWidth; + int valueTextWidth; + int valueTextHeight; + + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","OnResize") + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x=saveWidth+BUTTON_WIDTH_GAP+BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + + // List Box - fills all left side of screen (45 %) + configItemsWidth=(dialogWidth*45)/100; + configItemsHeight=(dialogHeight- + quitHeight- + DIALOG_BOTTOM_BORDER_SIZE- + BUTTON_HEIGHT_GAP); + configItems.SetSize(0,0,configItemsWidth,configItemsHeight); + configItems.SetColumnWidth(0,configItemsWidth); + + // Filters are at the top right of the screen + itemPosition.x=dialogWidth/2; + itemPosition.y=5; + + int filterIndex; + BoxedDropDown *currentFilter=NULL; + + for (filterIndex=0;filterIndex<2;filterIndex++) + { + switch (filterIndex) + { + case 0: + currentFilter=filter1; + break; + case 1: + currentFilter=filter2; + break; + } + if (currentFilter!=NULL) + { + currentFilter->SetPosition(itemPosition); + itemSize=currentFilter->GetSize(); + itemPosition.y+=(itemSize.GetHeight()); + itemPosition.y+=5; + } + } + + if (drawImages) + { + imagePanelX =dialogWidth/2; + imagePanelY =itemPosition.y; + imagePanelWidth =configItemsWidth; + imagePanelHeight =300; + + itemPosition.y+=imagePanelHeight; + imagePanel->SetSize(imagePanelX,imagePanelY, + imagePanelWidth,imagePanelHeight); + imagePanel->Proportion(imagePanelWidth,imagePanelHeight); + } + if (configPanel!=NULL) + { + configPanel->SetPosition(itemPosition); + itemSize=configPanel->GetSize(); + configPanel->SetSize(dialogWidth/2, + itemPosition.y, + configItemsWidth, + itemSize.GetHeight()); + itemSize=configPanel->GetSize(); + itemPosition.y+=(itemSize.GetHeight()); + itemPosition.y+=5; + } + + // Text ctrl is underneath any filters + itemSize=valueText.GetSize(); + valueTextWidth=configItemsWidth; + valueTextHeight=itemSize.GetHeight(); + valueText.SetSize(dialogWidth/2, + itemPosition.y, + valueTextWidth, + valueTextHeight); + + STATSGEN_DEBUG_FUNCTION_END +} + +void ConfigEditorGUI::OnFilterChanged(wxCommandEvent& event) +{ + STATSGEN_DEBUG_FUNCTION_START("ConfigEditorGUI","OnFilterChanged") + PopulateConfigItems(); + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/ConfigEditorGUI.h b/ConfigEditorGUI.h new file mode 100644 index 0000000..6a0ba8e --- /dev/null +++ b/ConfigEditorGUI.h @@ -0,0 +1,73 @@ +#ifndef __CONFIGEDITORGUI +#define __CONFIGEDITORGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BoxedDropDown.h" +#include "TextConfigItemGUI.h" +#include "GroupedConfigItemsPanel.h" +#include "ImagePanel.h" + +class ConfigEditorGUI : public wxDialog +{ + public: + ConfigEditorGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + BoxedDropDown *filter1, + BoxedDropDown *filter2, + GroupedConfigItemsPanel *panelIn, + bool drawImages); + virtual ~ConfigEditorGUI(); + + void OnQuit(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + void OnListItemSelected(wxListEvent& event); + void OnResize(wxSizeEvent& event); + void OnTextChange(wxCommandEvent& event); + void OnFilterChanged(wxCommandEvent& event); + + void AddConfigKey( + wxString &group, + wxString &configKey, + bool useRealName); + void DisplayDialog(); + + protected: + void CreateDialog(); + + wxArrayString configKeys; + wxArrayString configBaseKeys; + wxArrayString configDisplayNames; + wxListCtrl configItems; + //wxTextCtrl valueText; + TextConfigItemGUI valueText; + wxButton saveButton; + wxButton quitButton; + BoxedDropDown *filter1; + BoxedDropDown *filter2; + GroupedConfigItemsPanel *configPanel; + bool drawImages; + ImagePanel *imagePanel; + int imagePanelWidth; + int imagePanelHeight; + int imagePanelX; + int imagePanelY; + + private: + void PopulateConfigItems(); + + wxString lastSelectedKey; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ConfigItem.cpp b/ConfigItem.cpp new file mode 100644 index 0000000..dce3db6 --- /dev/null +++ b/ConfigItem.cpp @@ -0,0 +1,16 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "ConfigItem.h" + +ConfigItem::ConfigItem() +{ +} + +ConfigItem::~ConfigItem() +{ +} + diff --git a/ConfigItem.h b/ConfigItem.h new file mode 100644 index 0000000..15b3a0f --- /dev/null +++ b/ConfigItem.h @@ -0,0 +1,24 @@ +#ifndef __CONFIGITEM +#define __CONFIGITEM + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class ConfigItem; + +WX_DECLARE_OBJARRAY(ConfigItem,ArrayOfConfigItem); +class ConfigItem +{ + public: + ConfigItem(); + virtual ~ConfigItem(); + wxString key; + wxString value; + bool committed; +}; + +#endif diff --git a/ContentTypes.cpp b/ContentTypes.cpp new file mode 100644 index 0000000..a27eae4 --- /dev/null +++ b/ContentTypes.cpp @@ -0,0 +1,53 @@ +#include "wx/wx.h" + +#include "ContentTypes.h" + +ContentTypes::ContentTypes( ) +{ + contentTypes[_("txt")] = _("text/plain"); + contentTypes[_("html")] = _("text/html"); + contentTypes[_("htm")] = _("text/html"); + contentTypes[_("css")] = _("text/css"); + contentTypes[_("js")] = _("text/javascript"); + contentTypes[_("xml")] = _("text/xml"); + + contentTypes[_("gif")] = _("image/gif"); + contentTypes[_("jpg")] = _("image/jpeg"); + contentTypes[_("png")] = _("image/png"); + + contentTypes[_("zip")] = _("application/zip"); + contentTypes[_("pdf")] = _("application/pdf"); + contentTypes[_("swf")] = _("application/x-shockwave-flash"); + + contentTypes[_("mp3")] = _("audio/mpeg"); + contentTypes[_("wav")] = _("audio/wav"); + contentTypes[_("wma")] = _("audio/x-ms-wma"); + contentTypes[_("aac")] = _("audio/aac"); + + contentTypes[_("qt")] = _("video/quicktime"); + contentTypes[_("mov")] = _("video/quicktime"); + contentTypes[_("3gp")] = _("video/3gpp"); + contentTypes[_("avi")] = _("video/avi"); + contentTypes[_("wmv")] = _("video/x-ms-wmv"); + + contentTypes[_("wml")] = _("text/vnd.wap.wml"); + contentTypes[_("jad")] = _("text/vnd.sun.j2me.app-descriptor"); + contentTypes[_("jar")] = _("application/java-archive"); +} + + +ContentTypes::~ContentTypes() +{ +} + +wxString ContentTypes::GetContentType( const wxString& fileExt ) +{ + wxString value = wxEmptyString; + ContentTypesHash::iterator it; + it = contentTypes.find( fileExt ); + if( it != contentTypes.end() ) + value = it->second; + + return value; +} + diff --git a/ContentTypes.h b/ContentTypes.h new file mode 100644 index 0000000..d6f7f54 --- /dev/null +++ b/ContentTypes.h @@ -0,0 +1,24 @@ +#ifndef _CONTENTTYPES_H_ +#define _CONTENTTYPES_H_ + +#include "wx/wx.h" + +// hash map for content types +WX_DECLARE_STRING_HASH_MAP( wxString, ContentTypesHash ); + +class ContentTypes +{ + + +public: + wxString GetContentType( const wxString& fileExt ); + ContentTypes( ); + virtual ~ContentTypes(); + +private: + ContentTypesHash contentTypes; + +}; + +#endif + diff --git a/DefaultTemplate1.cpp b/DefaultTemplate1.cpp new file mode 100644 index 0000000..fec653f --- /dev/null +++ b/DefaultTemplate1.cpp @@ -0,0 +1,1890 @@ +#include +void ExportTemplateFile(wxString &directory,wxArrayString &fileLines,char *filename); +void ExportTemplateFull(wxString &directory) +{ + wxString filename; + wxArrayString fileLines; + wxString fileLine; + fileLines.Clear(); + fileLine="$$include templatevariables.include$$";fileLines.Add(fileLine); + fileLine="$$MinPlayersInRound=ReadConfig(\"/General/MinPlayersInRound\")$$";fileLines.Add(fileLine); + fileLine="$$MinRoundsPerPlayer=ReadConfig(\"/General/MinRoundsPerPlayer\")$$";fileLines.Add(fileLine); + fileLine="$$MAXMAINPAGEWEAPONS=ReadTemplateConfig(\"MAXMAINPAGEWEAPONS\",\"10\",\"Number of Weapons to display on the main page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXMAINPAGECLASSES=ReadTemplateConfig(\"MAXMAINPAGECLASSES\",\"10\",\"Number of Player Classes to display on the main page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXMAINPAGEMAPS=ReadTemplateConfig(\"MAXMAINPAGEMAPS\",\"10\",\"Number of Maps to display on the main page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXMAINPAGEGAMETYPES=ReadTemplateConfig(\"MAXMAINPAGEGAMETYPES\",\"10\",\"Number of Game Types to display on the main page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXMAINPAGELOCATIONS=ReadTemplateConfig(\"MAXMAINPAGELOCATIONS\",\"10\",\"Number of Kill Locations to display on the main page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXAWARDPLAYERS=ReadTemplateConfig(\"AWARDPLAYERS\",\"10\",\"Number of players to display for each award\")$$";fileLines.Add(fileLine); + fileLine="$$MAXPLAYERLISTENTRIES=ReadTemplateConfig(\"MAXPLAYERLISTENTRIES\",\"1000\",\"Maximum number of players to display on the Leaderboard\")$$";fileLines.Add(fileLine); + fileLine="$$MAXSPEECHLINES=ReadTemplateConfig(\"MAXSPEECHLINES\",\"10\",\"Number of speech entries to display on a players page\")$$";fileLines.Add(fileLine); + fileLine="$$MAXNEMESIS=ReadTemplateConfig(\"MAXNEMESIS\",\"10\",\"Number of enemies to display on a players page\")$$";fileLines.Add(fileLine); + fileLine="$$HOMEPAGEHREF=ReadTemplateConfig(\"HOMEPAGEHREF\",\"http://www.statsgen.co.uk\",\"Your home page html address\")$$";fileLines.Add(fileLine); + fileLine="$$HOMEPAGEBANNER=ReadTemplateConfig(\"HOMEPAGEBANNER\",\"images/banner.jpg\",\"A link to your clans banner image, displayed at the top of every stats page\")$$";fileLines.Add(fileLine); + fileLine="$$gameservertypes=\"COD4\"$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"skill\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"score\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"skillweighted\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"scoreweighted\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"kills\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"deaths\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"suicides\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamkills\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamwins\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamlosses\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestkillstreak\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestdeathstreak\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestteamkillstreak\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"duration\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"rounds\"$$$$include playerlistallowed.include$$";fileLines.Add(fileLine); + fileLine="$$include keytables.include$$";fileLines.Add(fileLine); + fileLine="$$include keytableskills.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Main Page\")$$$$include mainpage.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Awards Page\")$$$$include awards.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Ratio List\")$$$$messagecentrekey=\"TopKillDeathRatio\"$$$$title=\"^7KILL : DEATH RATIO\"$$$$sortkey=\"ratio\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Skill List\")$$$$messagecentrekey=\"TopSkill\"$$$$title=\"^7SKILL\"$$$$sortkey=\"skill\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Score List\")$$$$messagecentrekey=\"TopScore\"$$$$title=\"^7SCORE\"$$$$sortkey=\"score\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Weighted Skill List\")$$$$messagecentrekey=\"TopWeightedSkill\"$$$$title=\"^7SKILL WEIGHTED \"$$$$sortkey=\"skillweighted\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Weighted Score List\")$$$$messagecentrekey=\"TopWeightedScore\"$$$$title=\"^7SCORE WEIGHTED \"$$$$sortkey=\"scoreweighted\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Kill List\")$$$$messagecentrekey=\"TopKills\"$$$$title=\"^7KILLS\"$$$$sortkey=\"kills\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Death List\")$$$$messagecentrekey=\"TopDeaths\"$$$$title=\"^7DEATHS\"$$$$sortkey=\"deaths\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Kill List\")$$$$messagecentrekey=\"TopTeamKills\"$$$$title=\"^7TEAM KILLS\"$$$$sortkey=\"teamkills\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Win List\")$$$$messagecentrekey=\"TopTeamWins\"$$$$title=\"^7TEAM WINS\"$$$$sortkey=\"teamwins\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Loss List\")$$$$messagecentrekey=\"TopTeamLosses\"$$$$title=\"^7TEAM LOSSES\"$$$$sortkey=\"teamlosses\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Kill Streak List\")$$$$messagecentrekey=\"TopKillStreak\"$$$$title=\"^7KILL STREAK\"$$$$sortkey=\"longestkillstreak\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Kill Streak List\")$$$$messagecentrekey=\"TopTeamKillStreak\"$$$$title=\"^7TEAM KILL STREAK\"$$$$sortkey=\"longestteamkillstreak\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Death Streak List\")$$$$messagecentrekey=\"TopDeathStreak\"$$$$title=\"^7DEATH STREAK\"$$$$sortkey=\"longestdeathstreak\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Suicide List\")$$$$messagecentrekey=\"TopSuicides\"$$$$title=\"^7SUICIDES\"$$$$sortkey=\"suicides\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Time Played List\")$$$$messagecentrekey=\"TopTimePlayed\"$$$$title=\"^7TIME PLAYED\"$$$$sortkey=\"duration\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Rounds Played List\")$$$$messagecentrekey=\"TopRoundsPlayed\"$$$$title=\"^7ROUNDS\"$$$$sortkey=\"rounds\"$$$$include playerlists.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"score\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"skill\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"skillweighted\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"scoreweighted\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"kills\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"deaths\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"ratio\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamkills\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamwins\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"teamlosses\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestkillstreak\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestteamkillstreak\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"longestdeathstreak\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"suicides\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"duration\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$sortkey=\"rounds\"$$$$updatestatus(\"Clan List\")$$$$include clanlist.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Info Page\")$$$$include info.include$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Players\")$$";fileLines.Add(fileLine); + fileLine="$$playercount=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as player index as index select count(*) as playercount from changedplayers$$$$playercount=player.playercount$$$$endloop playercount$$";fileLines.Add(fileLine); + fileLine="$$loop row as player index as playerindex select *,coalesce(cast(kills as float)/cast(deaths as float),kills) as ratio from player where playerindex in (select idx from changedplayers) and dropped=\"N\"$$";fileLines.Add(fileLine); + fileLine=" $$updatestatus(\"Player %%playerindex%% of %%playercount%%\")$$";fileLines.Add(fileLine); + fileLine=" $$include player.include$$";fileLines.Add(fileLine); + fileLine="$$endloop player$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Rounds\")$$$$include roundlist.include$$";fileLines.Add(fileLine); + fileLine="$$roundcount=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as round index as index select count(*) as roundcount from changedrounds$$$$roundcount=round.roundcount$$$$endloop roundcount$$";fileLines.Add(fileLine); + fileLine="$$loop row as round index as roundindex select * from rounds,servers where roundidx in (select idx from changedrounds) and dropped=\"N\" and rounds.serverindex=servers.serveridx$$";fileLines.Add(fileLine); + fileLine=" $$updatestatus(\"Round %%roundindex%% of %%roundcount%%\")$$";fileLines.Add(fileLine); + fileLine=" $$include round.include$$";fileLines.Add(fileLine); + fileLine="$$endloop round$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"full.template"); + fileLines.Clear(); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_sd\",\"One side defends two sites while the other side tries to plant a bomb at either. Which do you defend? Which do you Attack?\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_tdm\",\"Two Teams, lots of bullets, whichever team gets the most kills wins.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_dom\",\"Capture and hold control points, the more control points you hold the more your team's score increases.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_sab\",\"Each side has a target to attack with a common bomb, constant respawning makes teamwork essential.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_dm\",\"Every soldier for themselves in an all out bloodfest.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_ctf\",\"Each team tries to capture the enemies flag while also defending their own.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD5_koth\",\"Locate and capture a target then defend it from the enemy for as long as possible.\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_outskirts\",\"Red Army vs Wehrmacht

A large map with a village on the side of a hill. Buildings everywhere mean that no place is safe. A large central clock tower looks a good sniping spot but isn't that too obvious?\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_seelow\",\"Red Army vs Wehrmacht

A large map set on a hillside with a central covered train line offering good shooting positions for both the top and bottom of the hill. Two large open tunnels under the train line offer quick, but dangerous routes between the top and bottom of the hill. One has a river flowing through it running next to a wheelhouse. A covered tunnel allows for a safer, but more obvious route.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_roundhouse\",\"Red Army vs Wehrmacht

A large engineering yard with a central wheel house surrounded by high vantage point walkways, towers and buildings\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_courtyard\",\"Imperial Army vs Marine Raiders

A medium sized flat map with lots of open topped corridors to navigate while trying to avoid being shot.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_asylum\",\"Red Army vs Wehrmacht

A cramped and claustrophic map set in an old destroyed insane asylum with a central courtyard overlooked by windows. The distant moans of previous inhabitants haunt the players as they attempt to stay alive.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_downfall\",\"Red Army vs Wehrmacht

The final battle of the German Reich. A long map with high steps on either side giving sniper and rifle vantage points over the middle of the map. Trenches on the left and right offer cover for shorter range fire. Three sets of central bunkers are separated by deadly open spaces.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_shrine\",\"Imperial Army vs Marine Raiders

A long map with an open central area leading into a Japanese shrine makes taking control of this map very difficult as there are lots of sniping and rifling positions on all sides.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_suburban\",\"Red Army vs Wehrmacht

A tight close quarters battle is guaranteed in this shattered village above a train line. Destroyed buildings and abandoned goods carriages offer protection and shooting strongholds.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_airfield\",\"Imperial Army vs Marine Raiders

A large open map with an underground tunnel partially connecting two halves. A crashed plane, boxes and destroyed vehicles offer cover for skilled riflers as well as several enclosed buildings.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_makin\",\"Imperial Army vs Marine Raiders

A Japanese fishing village at night on a beach at the edge of the jungle with the tide in gives lots of close quarter killing opportunities.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_makin_day\",\"Imperial Army vs Marine Raiders

A Japanese fishing village on a beach at the edge of the jungle while the tide has gone out gives lots of close quarter killing opportunities.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_hangar\",\"Imperial Army vs Marine Raiders

An aircraft hangar surrounded by multiple buildings. The hangar may see a safe place to hole up but getting trapped in there may be the last thing you do.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_castle\",\"Imperial Army vs Marine Raiders

Two high vantage points look down upon a central Japanese garden with cherry blossoms in full bloom.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_kneedeep\",\"Imperial Army vs Marine Raiders

A Japanese village set amongst a sprawling swamp. Many huts provide perfect hiding holes for cautious soldier.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_nachtfeuer\",\"Red Army vs Wehrmacht

Night, a city on fire, and soldiers fighting through the cramped conditions to become victorious.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_subway\",\"Red Army vs Wehrmacht

Two ends of an underground trainstation. Tunnels on either side give duplicate routes from one end to the other.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD5_mp_dome\",\"Red Army vs Wehrmacht

A close quarters battle atop the Reichstadt dome gives you know time to think but plenty of time to die.\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_backlot\",\"Opfor vs Marines

A destroyed town with many buildings surrounding a central area. A multi-floor factory offers many rifling points.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_bloc\",\"Spetsnaz vs S.A.S.

Eastern European block of flats surround each side of a courtyard with a central statue. A swimming pool to the rear provides a last stand hiding spot.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_bog\",\"Opfor vs Marines

A dirty, rainy, open piece of ground with an abandoned bus and multiple storage crates offering cover. Shops on the left give additional hiding spots.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_broadcast\",\"Opfor vs Marines

A television studio with many rooms offering close quarters combat. A central computer room with overlooking balcony offers a quick, but dangerous, route to the whole building. Roof access from the large carpark gives fast access to the interior.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_carentan\",\"Spetsnaz vs S.A.S.

An Asian take on an old favourite. A 3 story building in the center of the map gives control over most of the map and is essential to capture.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_cargoship\",\"Spetsnaz vs S.A.S.

Battle across the deck of a rain-drenched cargo ship. Storage crates offer cover and climing points for this close-quarter bloodfest.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_citystreets\",\"Opfor vs Marines

A market square surrounded by buildings with long streets down two sides. Don't fall down the well!\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_convoy\",\"Opfor vs Marines

A central road on a ridge separates two areas with many buildings which offer good rifling spots. Two sewer tunnels allow for hidden access from one side of the road to the other.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_countdown\",\"Spetsnaz vs S.A.S.

Missle silos and platforms fill the center of this map with multiple hangars around the edge.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_crash\",\"Opfor vs Marines

Black Hawk Down. A crashed helicopter in the center of a set of shops and houses with a tall multistory building with roof access overlooking the entire map\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_crash_snow\",\"Opfor vs Marines

Black Hawk Down, and Santa. A crashed helicopter in the center of a set of shops and houses with a tall multistory building with roof access overlooking the entire map\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_creek\",\"Spetsnaz vs S.A.S.

A deep ravine with a high ridge on either side provide the central point to this map. A tunnel allows access under the ridge into the ravine and houses at the top of one side of the ridge offer good sniping points.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_crossfire\",\"Opfor vs Marines

A long open street leads from top to bottom of this map. Snipers really make a casual stroll down the road possibly the last thing you do. Building access on either side offer a safer, but more convoluted route between the top and bottom.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_farm\",\"Spetsnaz vs S.A.S.

It's raining hard in this farmyard. Multiple greenhouses at one side. Building access on one side, grain silos on the other give access from top to bottom of the map.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_overgrown\",\"Spetsnaz vs S.A.S.

A central ravine with two bridges crossing it at the top and bottom giving the player access to either the street or the field side. Field side has a central farm house with attic access. A barnhouse also offers cover across most of the field making a walk through the hay a most dangerous prospect.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_pipeline\",\"Spetsnaz vs S.A.S.

Two multifloor factories form the main central area of this map. A train line on one side with abandoned carriages offering good hiding holes. A set of tunnels connect most parts of the map for that surprise attack.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_showdown\",\"Opfor vs Marines

A small square surrounded by second floor corridors. Fences block one side of the map to the other making it either - through the square or over the top.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_strike\",\"Opfor vs Marines

A central street surrounded on one one side by shops, one side a market square replete with statue. Overlooked by some multifloor buildings offering good rifling spots.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_map_COD4_mp_vacant\",\"Spetsnaz vs S.A.S.

A large open factory floor with multiple connected buildings. Outside the factory is a large area with many storage crates giving good cover.\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_sd\",\"One side defends two sites while the other side tries to plant a bomb at either. Which do you defend? Which do you Attack?\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_war\",\"Two Teams, lots of bullets, whichever team gets the most kills wins.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_dom\",\"Capture and hold control points, the more control points you hold the more your team's score increases.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_koth\",\"Locate and capture a target then defend it from the enemy for as long as possible.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_sab\",\"Each side has a target to attack with a common bomb, constant respawning makes teamwork essential.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD4_dm\",\"Every soldier for themselves in an all out bloodfest.\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD2_esd\",\"One side defends two sites while the other side tries to plant a bomb at either. Which do you defend? Which do you Attack? As dead players respawn teamwork is essential.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD2_ctf\",\"Each team tries to capture the enemies flag while also defending their own.\")$$";fileLines.Add(fileLine); + fileLine="$$ReadTemplateConfig(\"description_gametype_COD2_sd\",\"One side defends two sites while the other side tries to plant a bomb at either. Which do you defend? Which do you Attack?\")$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"templatevariables.include"); + fileLines.Clear(); + fileLine="$$%%sortkey%%allowed=\"N\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as player index as index select max(%%sortkey%%) - min(%%sortkey%%) as difference from view_player$$";fileLines.Add(fileLine); + fileLine=" $$if (player.difference EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$%%sortkey%%allowed=\"N\"$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$%%sortkey%%allowed=\"Y\"$$";fileLines.Add(fileLine); + fileLine=" $$%%sortkey%%allowed=ReadTemplateConfig(\"Display_%%sortkey%%\",%%sortkey%%allowed,\"Turn on or off the %%sortkey%% column on the leaderboard\")$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="$$endloop player$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerlistallowed.include"); + fileLines.Clear(); + fileLine="$$tablename=\"action\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"class\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"gametype\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"location\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"map\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"team\"$$$$include keytable.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"weapon\"$$$$include keytable.include$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"keytables.include"); + fileLines.Clear(); + fileLine="$$loop row as key index as index select * from %%tablename%%$$";fileLines.Add(fileLine); + fileLine=" $$%%tablename%%_%%key.idx%%_id=key.id$$";fileLines.Add(fileLine); + fileLine=" $$%%tablename%%_%%key.idx%%_realname=key.realname$$";fileLines.Add(fileLine); + fileLine=" $$%%tablename%%_%%key.idx%%_image=key.image$$";fileLines.Add(fileLine); + fileLine="$$endloop row$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"keytable.include"); + fileLines.Clear(); + fileLine="$$killstablename=\"gametype\"$$$$totalstable=\"killtotalgametypes\"$$$$include keytablekills.include$$";fileLines.Add(fileLine); + fileLine="$$killstablename=\"map\"$$$$totalstable=\"killtotalmaps\"$$$$include keytablekills.include$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"keytableskills.include"); + fileLines.Clear(); + fileLine="$$loop row as totalskey index as keyindex select * from %%killstablename%%$$";fileLines.Add(fileLine); + fileLine=" $$description=ReadTemplateConfig(\"description_%%killstablename%%_%%totalskey.id%%\",\"No description available\")$$";fileLines.Add(fileLine); + fileLine=" $$loop row as killscount index as countindex select sum(kills) as kills, sum(teamkills) as teamkills, sum(suicides) as suicides from %%totalstable%%$$";fileLines.Add(fileLine); + fileLine=" $$totalkills=killscount.kills$$";fileLines.Add(fileLine); + fileLine=" $$totalsuicides=killscount.suicides$$";fileLines.Add(fileLine); + fileLine=" $$totalteamkills=killscount.teamkills$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$openfile %%killstablename%%_%%totalskey.id%%.html$$$$updatestatus(\"%%killstablename%%_%%totalskey.id%%.html\")$$";fileLines.Add(fileLine); + fileLine=" $$include menu.include$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (%%killstablename%%_%%totalskey.idx%%_image !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
Name$$%%killstablename%%_%%totalskey.idx%%_realname$$
Total Kills$$totalkills$$
Total Suicides$$totalsuicides$$
Total Teamkills$$totalteamkills$$
$$description$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$playerdisplaydropped=\"N\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as kills index as killsindex select player.playerindex as playeridx,name,dropped,itemindex,%%totalstable%%.kills as totalkills,%%totalstable%%.deaths as totaldeaths,%%totalstable%%.suicides as totalsuicides,%%totalstable%%.teamkills as totalteamkills from %%totalstable%%,player where itemindex='%%totalskey.idx%%' and dropped='N' and player.playerindex=%%totalstable%%.playerindex order by totalkills desc,totaldeaths asc$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="
#PlayerKillsDeathsTeam KillsSuicides
$$killsindex$$$$playerdisplayplayerindex=kills.playeridx$$$$playerdisplayname=kills.name$$$$include playerdisplay.include$$$$kills.totalkills$$$$kills.totaldeaths$$$$kills.totalteamkills$$$$kills.totalsuicides$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$closefile$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"keytablekills.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" $$if (HOMEPAGEBANNER !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (HOMEPAGEHREF !EQUALS \"\")$$ ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"menu.include"); + fileLines.Clear(); + fileLine="$$tablename=\"playerdataavatars\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$if (playerdisplaydropped EQUALS \"Y\")$$";fileLines.Add(fileLine); + fileLine=" $$colouredtext2html(playerdisplayname)$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdataavatars !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="$$else$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$colouredtext2html(playerdisplayname)$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdataavatars !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerdisplay.include"); + fileLines.Clear(); + fileLine="$$%%tablename%%=\"\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as playerprofilecomponent index as playerprofilecomponentindex select * from %%tablename%% where playerindex='%%playerdataplayerindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$%%tablename%%=playerprofilecomponent.playerdata$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerprofilecomponent.include"); + fileLines.Clear(); + fileLine="$$openfile index.html$$";fileLines.Add(fileLine); + fileLine="$$pagetitle=\"%%gameservertypes%% Server Stats\"$$$$include menu.include$$";fileLines.Add(fileLine); + fileLine="$$loop row as server index as serverindex select * from servers$$";fileLines.Add(fileLine); + fileLine=" $$loop row as servervariable index as variableindex select * from servervariables where serveridx='%%server.serveridx%%'$$";fileLines.Add(fileLine); + fileLine=" $$%%lowercase(servervariable.variable)%%=servervariable.value$$";fileLines.Add(fileLine); + fileLine=" $$endloop servervariable$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$colouredtext2html(sv_hostname)$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$include servervariables.include$$";fileLines.Add(fileLine); + fileLine="
IP$$server.hostname$$$$if (server.gameport !EQUALS \"-1\")$$:$$server.gameport$$$$endif$$Logfile Size$$server.logfilesize$$
Rounds to Register$$MinRoundsPerPlayer$$Minimum Per Round$$MinPlayersInRound$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endloop server$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include mainpageweapons.include$$";fileLines.Add(fileLine); + fileLine=" $$include mainpageclasses.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include mainpagemaps.include$$";fileLines.Add(fileLine); + fileLine=" $$include mainpagegametypes.include$$";fileLines.Add(fileLine); + fileLine=" $$include mainpagelocations.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpage.include"); + fileLines.Clear(); + fileLine="$$IF (server.servertype EQUALS \"COD1\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Clients$$sv_maxclients$$";fileLines.Add(fileLine); + fileLine=" Private Clients$$sv_privateclients$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Ping$$sv_maxping$$";fileLines.Add(fileLine); + fileLine=" Max Rate$$sv_maxrate$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Version$$shortversion$$";fileLines.Add(fileLine); + fileLine="   ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Pure";fileLines.Add(fileLine); + fileLine=" Punkbuster";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (server.servertype EQUALS \"COD2\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Clients$$sv_maxclients$$";fileLines.Add(fileLine); + fileLine=" Private Clients$$sv_privateclients$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Ping$$sv_maxping$$";fileLines.Add(fileLine); + fileLine=" Max Rate$$sv_maxrate$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Version$$shortversion$$";fileLines.Add(fileLine); + fileLine=" Voice";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Pure";fileLines.Add(fileLine); + fileLine=" Punkbuster";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (server.servertype EQUALS \"COD4\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Clients$$sv_maxclients$$";fileLines.Add(fileLine); + fileLine=" Private Clients$$sv_privateclients$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Ping$$sv_maxping$$";fileLines.Add(fileLine); + fileLine=" Max Rate$$sv_maxrate$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Version$$shortversion$$";fileLines.Add(fileLine); + fileLine=" Voice";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Pure";fileLines.Add(fileLine); + fileLine=" Punkbuster";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (server.servertype EQUALS \"COD5\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Clients$$sv_maxclients$$";fileLines.Add(fileLine); + fileLine=" Private Clients$$sv_privateclients$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Max Ping$$sv_maxping$$";fileLines.Add(fileLine); + fileLine=" Max Rate$$sv_maxrate$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Version$$shortversion$$";fileLines.Add(fileLine); + fileLine=" Voice";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" Pure";fileLines.Add(fileLine); + fileLine=" Punkbuster";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (server.servertype EQUALS \"WOLFENSTEIN\")$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine="$$ENDIF$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"servervariables.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$loop row as stat index as statindex select count(*) as killcount,id,playerweapon,realname,image,(select count(*) from killdata as subkilldata where killdata.playerweapon=subkilldata.playerweapon and killtype='SUICIDE') as suicidecount,(select count(*) from killdata as subkilldata where killdata.playerweapon=subkilldata.playerweapon and killtype='TEAMKILL') as teamkillcount from killdata,weapon where killtype='KILL' and weapon.idx=killdata.playerweapon group by playerweapon order by killcount desc limit %%MAXMAINPAGEWEAPONS%%$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endloop stat$$";fileLines.Add(fileLine); + fileLine="
#WeaponKillsSuicides
$$statindex$$";fileLines.Add(fileLine); + fileLine=" $$if (stat.image !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="
$$stat.realname$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine="
$$stat.realname$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="
$$stat.killcount$$$$stat.suicidecount$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpageweapons.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as stat index as statindex select count(*) as killcount,id,playerclass,realname,image,(select count(*) from killdata as subkilldata where killdata.playerclass=subkilldata.playerclass and killtype='SUICIDE') as suicidecount,(select count(*) from killdata as subkilldata where killdata.playerclass=subkilldata.playerclass and killtype='TEAMKILL') as teamkillcount from killdata,class where killtype='KILL' and class.idx=killdata.playerclass group by playerclass order by killcount desc limit %%MAXMAINPAGECLASSES%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop stat$$";fileLines.Add(fileLine); + fileLine="
#TotalsKillsSuicides
$$statindex$$";fileLines.Add(fileLine); + fileLine="
$$stat.realname$$";fileLines.Add(fileLine); + fileLine="$$if (stat.image !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
$$stat.killcount$$$$stat.suicidecount$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpageclasses.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as map index as mapindex select count(mapname) as roundcount,sum(duration) as duration,mapname,id,realname,image from view_rounds,map where view_rounds.mapname=map.idx group by mapname order by roundcount desc limit %%MAXMAINPAGEMAPS%%$$";fileLines.Add(fileLine); + fileLine="$$kills=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$teamkills=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$suicides=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$totalplayers=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$averageplayers=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='KILL' and roundindex in (select roundidx from view_rounds where mapname='%%map.mapname%%')$$";fileLines.Add(fileLine); + fileLine="$$kills=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='TEAMKILL' and roundindex in (select roundidx from view_rounds where mapname='%%map.mapname%%')$$";fileLines.Add(fileLine); + fileLine="$$teamkills=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='SUICIDE' and roundindex in (select roundidx from view_rounds where mapname='%%map.mapname%%')$$";fileLines.Add(fileLine); + fileLine="$$suicides=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as totalplayers from playerinround where roundindex in (select roundidx from view_rounds where mapname='%%map.mapname%%')$$";fileLines.Add(fileLine); + fileLine="$$totalplayers=stats.totalplayers$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select %%totalplayers%%.0/%%map.roundcount%%.0 as averageplayers from rounds limit 1$$";fileLines.Add(fileLine); + fileLine="$$averageplayers=stats.averageplayers$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop maps$$";fileLines.Add(fileLine); + fileLine="
#MapRounds
Played
Average
Players
Total
Players
KillsSuicidesTime
Played
$$mapindex$$";fileLines.Add(fileLine); + fileLine="$$if (map.image !EQUALS \"\")$$
$$map.realname$$";fileLines.Add(fileLine); + fileLine="$$else$$
$$map.realname$$$$endif$$
";fileLines.Add(fileLine); + fileLine="
$$map.roundcount$$$$formatfloat(\"%.1f\",averageplayers)$$$$totalplayers$$$$kills$$$$suicides$$$$formatduration(\"%H:%M\",map.duration)$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpagemaps.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as gametype index as gametypeindex select count(gametype) as roundcount,sum(duration) as duration,gametype,id,realname,image from view_rounds,gametype where view_rounds.gametype=gametype.idx group by gametype order by roundcount desc limit %%MAXMAINPAGEGAMETYPES%%$$";fileLines.Add(fileLine); + fileLine="$$kills=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$teamkills=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$suicides=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$totalplayers=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$averageplayers=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select max(roundidx) as lastround from view_rounds where gametype='%%gametype.gametype%%'$$";fileLines.Add(fileLine); + fileLine="$$lastround=stats.lastround$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='KILL' and roundindex in (select roundidx from view_rounds where gametype='%%gametype.gametype%%')$$";fileLines.Add(fileLine); + fileLine="$$kills=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='TEAMKILL' and roundindex in (select roundidx from view_rounds where gametype='%%gametype.gametype%%')$$";fileLines.Add(fileLine); + fileLine="$$teamkills=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as killcount from killdata where killtype='SUICIDE' and roundindex in (select roundidx from view_rounds where gametype='%%gametype.gametype%%')$$";fileLines.Add(fileLine); + fileLine="$$suicides=stats.killcount$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select count(*) as totalplayers from playerinround where roundindex in (select roundidx from view_rounds where gametype='%%gametype.gametype%%')$$";fileLines.Add(fileLine); + fileLine="$$totalplayers=stats.totalplayers$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="$$loop stats as stats index as statsindex select %%totalplayers%%.0/%%gametype.roundcount%%.0 as averageplayers from rounds limit 1$$";fileLines.Add(fileLine); + fileLine="$$averageplayers=stats.averageplayers$$";fileLines.Add(fileLine); + fileLine="$$endloop stats$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop gametype$$";fileLines.Add(fileLine); + fileLine="
#GametypeRounds
Played
Average
Players
Total
Players
KillsSuicidesTime
Played
$$gametypeindex$$";fileLines.Add(fileLine); + fileLine="$$if (gametype.image !EQUALS \"\")$$
$$gametype.realname$$";fileLines.Add(fileLine); + fileLine="$$else$$
$$gametype.realname$$$$endif$$
";fileLines.Add(fileLine); + fileLine="
$$gametype.roundcount$$$$formatfloat(\"%.1f\",averageplayers)$$$$totalplayers$$$$kills$$$$suicides$$$$formatduration(\"%H:%M\",gametype.duration)$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpagegametypes.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as stat index as statindex select count(*) as killcount,id,targetlocation,realname,image,(select count(*) from killdata as subkilldata where killdata.targetlocation=subkilldata.targetlocation and killtype='SUICIDE') as suicidecount,(select count(*) from killdata as subkilldata where killdata.targetlocation=subkilldata.targetlocation and killtype='TEAMKILL') as teamkillcount from killdata,location where killtype='KILL' and location.idx=killdata.targetlocation group by targetlocation order by killcount desc limit %%MAXMAINPAGELOCATIONS%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop stat$$";fileLines.Add(fileLine); + fileLine="
#LocationKills
$$statindex$$$$stat.realname$$$$stat.killcount$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"mainpagelocations.include"); + fileLines.Clear(); + fileLine="$$openfile awardlist.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
AWARDS
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$awardprint=\"\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as awarddef index as awarddefindex select * from awarddefinition$$";fileLines.Add(fileLine); + fileLine=" $$updatestatus(\"Award: %%awarddef.name%%\")$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=\"0\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardpoints index as awardpointsindex select count(*) from view_awardpoints where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=awardpoints.0$$";fileLines.Add(fileLine); + fileLine=" $$endloop awardpoints$$";fileLines.Add(fileLine); + fileLine=" $$if (pointsrecorded !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$if (awardprint EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (awardprint EQUALS \"XX\")$$$$awardprint=\"\"$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$awardprint=\"%%awardprint%%X\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="$$endloop awarddef$$";fileLines.Add(fileLine); + fileLine="$$if (awardprint !EQUALS \"\")$$$$awardprint=\"\"$$$$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
$$awarddef.name$$
$$if (awarddef.image !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine=" $$else$$$$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (awarddef.weighted EQUALS \"Y\")$$";fileLines.Add(fileLine); + fileLine=" $$selectcommand=\"select coalesce(cast(sum(awardpoints.score)as float)/cast(count(awardpoints.score)as float),'-9999999') as awardscore,name as playername,awardpoints.playerindex from awardpoints,player where awardindex='%%awarddef.awardindex%%' and player.playerindex=awardpoints.playerindex and player.dropped='N' group by awardpoints.playerindex order by awardscore desc limit %%MAXAWARDPLAYERS%%\"$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$selectcommand=\"select sum(awardpoints.score) as awardscore,name as playername,awardpoints.playerindex from awardpoints,player where awardindex='%%awarddef.awardindex%%' and player.playerindex=awardpoints.playerindex and player.dropped='N' group by awardpoints.playerindex order by awardscore desc limit %%MAXAWARDPLAYERS%%\"$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardpoints index as awardpointsindex %%selectcommand%%$$";fileLines.Add(fileLine); + fileLine=" $$if (awardpointsindex EQUALS \"1\")$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(\"AWARD%%awarddef.id%%\",awardpoints.playername,formatfloat(\"%.2f\",awardpoints.awardscore))$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endloop awardpoints$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
#PlayerScore
$$awardpointsindex$$$$colouredtext2html(awardpoints.playername)$$$$formatfloat(\"%.2f\",awardpoints.awardscore)$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"awards.include"); + fileLines.Clear(); + fileLine="$$if (%%sortkey%%allowed !EQUALS \"N\")$$";fileLines.Add(fileLine); + fileLine="$$openfile playerlist_%%sortkey%%.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
$$colouredtext2html(title)$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (HOMEPAGETITLE !EQUALS \"\")$$ ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$else$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
$$HOMEPAGETITLE$$ Leaderboard
Leaderboard
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (killsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (deathsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (teamkillsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (suicidesallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (ratioallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestdeathstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestteamkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (roundsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (durationallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$firstrow=\"Y\"$$";fileLines.Add(fileLine); + fileLine="$$playerdisplaydropped=\"N\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as player index as playerindex select *,coalesce(cast(kills as float)/cast(deaths as float),kills) as ratio from player where dropped='N' order by %%sortkey%% desc limit %%MAXPLAYERLISTENTRIES%%$$";fileLines.Add(fileLine); + fileLine="$$if (playerindex EQUALS \"1\")$$";fileLines.Add(fileLine); + fileLine=" $$if (sortkey EQUALS \"duration\")$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(messagecentrekey,player.name,formatduration(\"%H:%M:%S\",player.%%sortkey%%))$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$if ((sortkey EQUALS \"score\") OR (sortkey EQUALS \"skill\"))$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(messagecentrekey,player.name,formatfloat(\"%.1f\",player.%%sortkey%%))$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$if (((sortkey EQUALS \"scoreweighted\") OR (sortkey EQUALS \"skillweighted\")) OR (sortkey EQUALS \"ratio\"))$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(messagecentrekey,player.name,formatfloat(\"%.2f\",player.%%sortkey%%))$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(messagecentrekey,player.name,player.%%sortkey%%)$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (killsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (deathsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (teamkillsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (suicidesallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (ratioallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestdeathstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestteamkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (roundsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (durationallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
#PlayerKillsDeathsTeam KillsSuicidesSkill
Weighted
Score
Weighted
SkillScoreRatioKill
Streak
Death
Streak
Team Kill
Streak
RoundsTime
Played
$$playerindex$$";fileLines.Add(fileLine); + fileLine="$$playerdisplayname=player.name$$";fileLines.Add(fileLine); + fileLine="$$playerdataplayerindex=player.playerindex$$";fileLines.Add(fileLine); + fileLine="$$include playerdisplay.include$$";fileLines.Add(fileLine); + fileLine="$$player.kills$$$$player.deaths$$$$player.teamkills$$$$player.suicides$$$$formatfloat(\"%.2f\",player.skillweighted)$$$$formatfloat(\"%.2f\",player.scoreweighted)$$$$formatfloat(\"%.1f\",player.skill)$$$$formatfloat(\"%.1f\",player.score)$$$$formatfloat(\"%.2f\",player.ratio)$$$$player.longestkillstreak$$$$player.longestdeathstreak$$$$player.longestteamkillstreak$$$$player.rounds$$$$formatduration(\"%H:%M:%S\",player.duration)$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerlists.include"); + fileLines.Clear(); + fileLine="$$if (%%sortkey%%allowed !EQUALS \"N\")$$";fileLines.Add(fileLine); + fileLine="$$openfile clanlist_%%sortkey%%.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$loop row as clanrow index as clanrowindex select * from clan where clanindex in (select clanindex from view_player where clanindex>=0)$$";fileLines.Add(fileLine); + fileLine="$$loop row as clanstats index as clanstatsindex select sum(rounds) as rounds,sum(score) as score,sum(skill) as skill,sum(duration) as duration, max(lastactiveround) as lastactiveround,sum(kills) as kills,sum(deaths) as deaths,sum(suicides) as suicides,max(longestkillstreak) as longestkillstreak,max(longestdeathstreak) as longestdeathstreak,max(longestteamkillstreak) as longestteamkillstreak,sum(teamwins) as teamwins, sum(teamkills) as teamkills, sum(teamlosses) as teamlosses from view_player where clanindex='%%clanrow.clanindex%%'$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (clanrow.webaddress !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop clanstats$$";fileLines.Add(fileLine); + fileLine="
Rounds$$clanstats.rounds$$Play Time$$formatduration(\"%H:%M:%S\",clanstats.duration)$$  
Score$$formatfloat(\"%.0f\",clanstats.score)$$Skill$$formatfloat(\"%.0f\",clanstats.skill)$$  
Kills$$clanstats.kills$$Deaths$$clanstats.deaths$$Suicides$$clanstats.suicides$$
Kill Streak$$clanstats.longestkillstreak$$Death Streak$$clanstats.longestdeathstreak$$  
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
SQUAD
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (killsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (deathsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (teamkillsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (suicidesallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (ratioallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestdeathstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestteamkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (roundsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (durationallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$playerdisplaydropped=\"N\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as player index as playerindex select *,coalesce(cast(kills as float)/cast(deaths as float),kills) as ratio from view_player where clanindex='%%clanrow.clanindex%%' order by %%sortkey%% desc$$";fileLines.Add(fileLine); + fileLine="$$playerdataplayerindex=player.playerindex$$";fileLines.Add(fileLine); + fileLine="$$playerdisplayname=player.name$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdataxfire\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdataclanrole\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (killsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (deathsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (teamkillsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (suicidesallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreweightedallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (skillallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (scoreallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (ratioallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestdeathstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (longestteamkillstreakallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (roundsallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$if (durationallowed !EQUALS \"N\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
#Clan MemberKillsDeathsKillsSuicidesSkill
Weighted
Score
Weighted
SkillScoreRatioKill
Streak
Death
Streak
Team Kill
Streak
RoundsTime
Played
X-FireRole
$$playerindex$$$$include playerdisplay.include$$$$player.kills$$$$player.deaths$$$$player.teamkills$$$$player.suicides$$$$formatfloat(\"%.2f\",player.skillweighted)$$$$formatfloat(\"%.2f\",player.scoreweighted)$$$$formatfloat(\"%.1f\",player.skill)$$$$formatfloat(\"%.1f\",player.score)$$$$formatfloat(\"%.2f\",player.ratio)$$$$player.longestkillstreak$$$$player.longestdeathstreak$$$$player.longestteamkillstreak$$$$player.rounds$$$$formatduration(\"%H:%M:%S\",player.duration)$$$$if (playerdataxfire !EQUALS \"\")$$$$playerdataxfire$$$$endif$$  $$if (playerdataclanrole !EQUALS \"\")$$$$playerdataclanrole$$$$endif$$  
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endloop clanrow$$";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"clanlist.include"); + fileLines.Clear(); + fileLine="$$openfile info.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
STATS INFO
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
SKILL CALCULATION
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as weight index as weightindex select * from SkillWeights where key like 'location_%' order by key desc$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
LocationValue
";fileLines.Add(fileLine); + fileLine=" $$if (weight.image !EQUALS \"\")$$$$endif$$$$weight.realname$$";fileLines.Add(fileLine); + fileLine=" $$weight.weight$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
SKILL CALCULATION
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$loop row as weight index as weightindex select * from SkillWeights where key like 'weapon_%' order by realname asc$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
WEAPONVALUE
 
$$if (weight.image !EQUALS \"\")$$
$$else$$
$$endif$$$$weight.realname$$
$$weight.weight$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$loop row as weight index as weightindex select * from SkillWeights where key like 'gametype_%' order by realname asc$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
Game TypeVALUE
 
$$if (weight.image !EQUALS \"\")$$
$$else$$
$$endif$$$$weight.realname$$
$$weight.weight$$
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
SCORE CALCULATION
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$loop row as weight index as weightindex select * from ScoreWeights order by key asc$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
TYPEVALUE
 
$$weight.realname$$$$weight.weight$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$loop row as awarddef index as awarddefindex select * from awarddefinition$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=\"0\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardpoints index as awardpointsindex select count(*) from awardpoints where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=awardpoints.0$$";fileLines.Add(fileLine); + fileLine=" $$endloop awardpoints$$";fileLines.Add(fileLine); + fileLine=" $$if (pointsrecorded !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$positivelocationkills=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positivelocationdeaths=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positivelocationtks=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positiveweaponkills=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positiveweapondeaths=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positiveweapontks=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positiveactions=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positivemisc=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$positivexp=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationkills=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationdeaths=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationtks=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativeweaponkills=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativeweapondeaths=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativeweapontks=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativeactions=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativemisc=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$negativexp=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionaction where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positiveactions=\"%%positiveactions%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativeactions=\"%%negativeactions%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionmisc where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positivemisc=\"%%positivemisc%%- %%awardcomponent.id%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativemisc=\"%%negativemisc%%- %%awardcomponent.id%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionxp where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positivexp=\"%%positivexp%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativexp=\"%%negativexp%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionlocationtk where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positivelocationtks=\"%%positivelocationtks%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationtks=\"%%negativelocationtks%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionlocationkill where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positivelocationkills=\"%%positivelocationkills%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationkills=\"%%negativelocationkills%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionlocationdeath where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positivelocationdeaths=\"%%positivelocationdeaths%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativelocationdeaths=\"%%negativelocationdeaths%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionweapontk where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positiveweapontks=\"%%positiveweapontks%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativeweapontks=\"%%negativeweapontks%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionweaponkill where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positiveweaponkills=\"%%positiveweaponkills%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativeweaponkills=\"%%negativeweaponkills%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardcomponent index as awardcomponentindex select * from awarddefinitionweapondeath where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$if (awardcomponent.posneg EQUALS \"+\")$$";fileLines.Add(fileLine); + fileLine=" $$positiveweapondeaths=\"%%positiveweapondeaths%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$negativeweapondeaths=\"%%negativeweapondeaths%%- %%awardcomponent.name%%
$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="
AWARDFACTORS
 
$$if (awarddef.image !EQUALS \"\")$$

$$else$$

$$endif$$$$awarddef.name$$$$if (awarddef.weighted EQUALS \"Y\")$$
(weighted)$$endif$$
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
POSITIVE EFFECT
WeaponsLocationsObjectivesOther
";fileLines.Add(fileLine); + fileLine=" $$if (positiveweaponkills !EQUALS \"\")$$Kills:
$$positiveweaponkills$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (positiveweapondeaths !EQUALS \"\")$$Deaths:
$$positiveweapondeaths$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (\"%%positiveweaponkills%%%%positiveweapondeaths%%\" EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (positivelocationkills !EQUALS \"\")$$Kills:
$$positivelocationkills$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (positivelocationdeaths !EQUALS \"\")$$Deaths:
$$positivelocationdeaths$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (\"%%positivelocationkills%%%%positivelocationdeaths%%\" EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (positiveactions !EQUALS \"\")$$$$positiveactions$$$$else$$ $$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (positivemisc !EQUALS \"\")$$$$positivemisc$$$$else$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
NEGATIVE EFFECT
WeaponsLocationsObjectivesOther
";fileLines.Add(fileLine); + fileLine=" $$if (negativeweaponkills !EQUALS \"\")$$Kills:
$$negativeweaponkills$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (negativeweapondeaths !EQUALS \"\")$$Deaths:
$$negativeweapondeaths$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (\"%%negativeweaponkills%%%%negativeweapondeaths%%\" EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (negativelocationkills !EQUALS \"\")$$Kills:
$$negativelocationkills$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (negativelocationdeaths !EQUALS \"\")$$Deaths:
$$negativelocationdeaths$$
$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (\"%%negativelocationkills%%%%negativelocationdeaths%%\" EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (negativeactions !EQUALS \"\")$$$$negativeactions$$$$else$$ $$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (negativemisc !EQUALS \"\")$$$$negativemisc$$$$else$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"info.include"); + fileLines.Clear(); + fileLine="$$openfile player_%%hash(player.name)%%.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
$$colouredtext2html(player.name)$$
";fileLines.Add(fileLine); + fileLine="$$include playerprofile.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
Rounds$$player.rounds$$Play Time$$formatduration(\"%H:%M:%S\",player.duration)$$  
Score$$formatfloat(\"%.0f\",player.score)$$ ($$formatfloat(\"%.2f\",player.scoreweighted)$$)Skill$$formatfloat(\"%.0f\",player.skill)$$ ($$formatfloat(\"%.2f\",player.skillweighted)$$)Ratio$$formatfloat(\"%.2f\",player.ratio)$$
Kills$$player.kills$$Deaths$$player.deaths$$Suicides$$player.suicides$$
Kill Streak$$player.longestkillstreak$$Death Streak$$player.longestdeathstreak$$Team Kills$$player.teamkills$$
";fileLines.Add(fileLine); + fileLine="$$include playeraka.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$include playerenemies.include$$";fileLines.Add(fileLine); + fileLine="$$include playerweapons.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$include playerlocations.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$include playerspeech.include$$";fileLines.Add(fileLine); + fileLine="$$include playerxp.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as gametypelist index as gametypelistindex select count(*),* from playerinround,rounds where playerindex='%%player.playerindex%%' and playerinround.roundindex=rounds.roundidx and rounds.dropped='N' group by gametype$$";fileLines.Add(fileLine); + fileLine=" $$gametype=gametypelist.gametype$$";fileLines.Add(fileLine); + fileLine=" $$gametyperealname=gametype_%%gametypelist.gametype%%_realname$$";fileLines.Add(fileLine); + fileLine=" $$gametypeimage=gametype_%%gametypelist.gametype%%_image$$";fileLines.Add(fileLine); + fileLine=" $$gametypeid=gametype_%%gametypelist.gametype%%_id$$";fileLines.Add(fileLine); + fileLine=" $$bestscore=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$worstscore=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$bestskill=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$worstskill=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$bestscoreround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$worstscoreround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$bestskillround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$worstskillround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from playerinround where playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by score desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$bestscore=round.score$$";fileLines.Add(fileLine); + fileLine=" $$bestscoreround=round.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from playerinround where playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by score asc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$worstscore=round.score$$";fileLines.Add(fileLine); + fileLine=" $$worstscoreround=round.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from playerinround where playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by skill desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$bestskill=round.skill$$";fileLines.Add(fileLine); + fileLine=" $$bestskillround=round.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from playerinround where playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by skill asc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$worstskill=round.skill$$";fileLines.Add(fileLine); + fileLine=" $$worstskillround=round.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" $$killstreak=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$killstreakender=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$killstreakround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$deathstreak=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$deathstreakender=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$deathstreakround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreak=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreakender=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreakround=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as streak index as streakindex select * from streakdata where streaktype='0' and playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by streaksize desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$killstreak=streak.streaksize$$";fileLines.Add(fileLine); + fileLine=" $$streakendindex=streak.streakender$$";fileLines.Add(fileLine); + fileLine=" $$killstreakround=streak.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$if (streakendindex !EQUALS \"-1\")$$";fileLines.Add(fileLine); + fileLine=" $$loop row as streakplayer index as streakplayerindex select * from player where playerindex='%%streakendindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$killstreakender=streakplayer.name$$";fileLines.Add(fileLine); + fileLine=" $$killstreakenderdropped=streakplayer.dropped$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" $$loop row as streak index as streakindex select * from streakdata where streaktype='1' and playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by streaksize desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$deathstreak=streak.streaksize$$";fileLines.Add(fileLine); + fileLine=" $$streakendindex=streak.streakender$$";fileLines.Add(fileLine); + fileLine=" $$deathstreakround=streak.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$if (streakendindex !EQUALS \"-1\")$$";fileLines.Add(fileLine); + fileLine=" $$loop row as streakplayer index as streakplayerindex select * from player where playerindex='%%streakendindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$deathstreakender=streakplayer.name$$";fileLines.Add(fileLine); + fileLine=" $$deathstreakenderdropped=streakplayer.dropped$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" $$loop row as streak index as streakindex select * from streakdata where streaktype='2' and playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by streaksize desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreak=streak.streaksize$$";fileLines.Add(fileLine); + fileLine=" $$streakendindex=streak.streakender$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreakround=streak.roundindex$$";fileLines.Add(fileLine); + fileLine=" $$if (streakendindex !EQUALS \"-1\")$$";fileLines.Add(fileLine); + fileLine=" $$loop row as streakplayer index as streakplayerindex select * from player where playerindex='%%streakendindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreakender=streakplayer.name$$";fileLines.Add(fileLine); + fileLine=" $$teamkillstreakenderdropped=streakplayer.dropped$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endloop gametypelist$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
Gametype
";fileLines.Add(fileLine); + fileLine=" $$if (gametypeimage !EQUALS \"\")$$
$$gametyperealname$$";fileLines.Add(fileLine); + fileLine=" $$else$$
$$gametyperealname$$$$endif$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (killstreak !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$playerdataplayerindex=\"-1\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (deathstreak !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (teamkillstreak !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="
Best Score$$formatfloat(\"%.1f\",bestscore)$$Round $$bestscoreround$$
Worst Score$$formatfloat(\"%.1f\",worstscore)$$Round $$worstscoreround$$
Most Skillful$$formatfloat(\"%.1f\",bestskill)$$Round $$bestskillround$$
Least Skillful$$formatfloat(\"%.1f\",worstskill)$$Round $$worstskillround$$
Longest Streaks
 #Ended ByIn Round
Kill$$killstreak$$  $$playerdisplaydropped=killstreakenderdropped$$$$playerdisplayname=killstreakender$$$$include playerdisplay.include$$  $$killstreakround$$
Death$$deathstreak$$  $$playerdisplaydropped=deathstreakenderdropped$$$$playerdisplayname=deathstreakender$$$$include playerdisplay.include$$  $$deathstreakround$$
TK$$teamkillstreak$$  $$playerdisplaydropped=teamkillstreakenderdropped$$$$playerdisplayname=teamkillstreakender$$$$include playerdisplay.include$$  $$teamkillstreakround$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" Rounds Played
";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from playerinround where playerindex='%%player.playerindex%%' and roundindex in (select roundidx from rounds where gametype='%%gametype%%' and dropped='N') order by roundindex asc$$";fileLines.Add(fileLine); + fileLine=" $$formatinteger(\"%05d\",round.roundindex)$$ ";fileLines.Add(fileLine); + fileLine=" $$endloop$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"player.include"); + fileLines.Clear(); + fileLine="$$playerdataplayerindex=player.playerindex$$$$tablename=\"playerdataavatars\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdatapicture\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdatarealname\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdataclanrole\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdataxfire\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdatawebsite\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdatamisc1\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$tablename=\"playerdatamisc2\"$$$$include playerprofilecomponent.include$$";fileLines.Add(fileLine); + fileLine="$$if (\"%%playerdataavatars%%%%playerdatapicture%%%%playerdatarealname%%%%playerdataclanrole%%%%playerdataxfire%%%%playerdatawebsite%%%%playerdatamisc1%%%%playerdatamisc2%%\" !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (playerdatarealname !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdataclanrole !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdatawebsite !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdataxfire !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdatamisc1 !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (playerdatamisc2 !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="
Real Name$$playerdatarealname$$ 
Clan Rank$$playerdataclanrole$$ 
Website$$playerdatawebsite$$ 
X-Fire$$playerdataxfire$$ 
Location$$playerdatamisc1$$ 
Quote$$playerdatamisc1$$ 
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$if (playerdatapicture !EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$if (playerdataavatars !EQUALS \"\")$$ $$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerprofile.include"); + fileLines.Clear(); + fileLine="$$AKALIST=\"\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as aka index as akaindex select name from akadata where playerindex='%%player.playerindex%%'$$";fileLines.Add(fileLine); + fileLine="$$AKALIST=\"%%AKALIST%%
%%colouredtext2html(aka.name)%%\"$$";fileLines.Add(fileLine); + fileLine="$$endloop aka$$";fileLines.Add(fileLine); + fileLine="$$if (AKALIST !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
AKA$$AKALIST$$
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playeraka.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as enemydata index as enemyindex select count(*) as counter,player.name as targetname,targetindex,dropped from killdata,player where player.playerindex=killdata.targetindex and killdata.playerindex='%%player.playerindex%%' and killtype='KILL' group by targetindex order by counter desc limit %%MAXNEMESIS%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$playerdisplaydropped=enemydata.dropped$$";fileLines.Add(fileLine); + fileLine="$$playerdisplayname=enemydata.targetname$$";fileLines.Add(fileLine); + fileLine="$$playerdataplayerindex=enemydata.targetindex$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop enemy$$";fileLines.Add(fileLine); + fileLine="
#Top VictimsYou
Killed
$$enemyindex$$$$include playerdisplay.include$$$$enemydata.counter$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as enemydata index as enemyindex select count(*) as counter,player.name as playername,player.playerindex as playeridx,dropped from killdata,player where killdata.playerindex=player.playerindex and targetindex='%%player.playerindex%%' AND killtype='KILL' group by playeridx order by counter desc limit %%MAXNEMESIS%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$playerdisplaydropped=enemydata.dropped$$";fileLines.Add(fileLine); + fileLine="$$coloured=colouredtext2html(enemydata.playername)$$";fileLines.Add(fileLine); + fileLine="$$playerdisplayname=enemydata.playername$$";fileLines.Add(fileLine); + fileLine="$$playerdataplayerindex=enemydata.playeridx$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop enemy$$";fileLines.Add(fileLine); + fileLine="
#Top EnemiesKilled
You
$$enemyindex$$$$include playerdisplay.include$$$$enemydata.counter$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerenemies.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as weaponlist index as weaponlistindex select count(*) as count,* from killdata where playerindex='%%player.playerindex%%' and killtype='KILL' group by playerweapon order by count desc limit 10$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop weaponlist$$";fileLines.Add(fileLine); + fileLine="
#Top WeaponsKills
$$weaponlistindex$$";fileLines.Add(fileLine); + fileLine="$$if (weapon_%%weaponlist.playerweapon%%_image !EQUALS \"\")$$
$$weapon_%%weaponlist.playerweapon%%_realname$$";fileLines.Add(fileLine); + fileLine="$$else$$
$$weapon_%%weaponlist.playerweapon%%_realname$$$$endif$$";fileLines.Add(fileLine); + fileLine="
$$weaponlist.count$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerweapons.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as stat index as statindex select count(*) as killcount,id,targetlocation,realname,image,(select count(*) from killdata as subkilldata where playerindex='%%player.playerindex%%' and killdata.targetlocation=subkilldata.targetlocation and killtype='SUICIDE') as suicidecount,(select count(*) from killdata as subkilldata where playerindex='%%player.playerindex%%' and killdata.targetlocation=subkilldata.targetlocation and killtype='TEAMKILL') as teamkillcount from killdata,location where playerindex='%%player.playerindex%%' and killtype='KILL' and location.idx=killdata.targetlocation group by targetlocation order by killcount desc limit %%MAXMAINPAGELOCATIONS%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop stat$$";fileLines.Add(fileLine); + fileLine="
#LocationKills
$$statindex$$";fileLines.Add(fileLine); + fileLine="$$stat.realname$$";fileLines.Add(fileLine); + fileLine="$$stat.killcount$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerlocations.include"); + fileLines.Clear(); + fileLine="$$loop row as speechdata index as speechindex select count(*) from speechdata where playerindex='%%player.playerindex%%'$$";fileLines.Add(fileLine); + fileLine="$$speechcount=speechdata.0$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="$$if (speechcount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as speechdata index as speechindex select count(*),* from speechdata where playerindex='%%player.playerindex%%' group by speech order by count(*) desc limit %%MAXSPEECHLINES%%$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$coloured=colouredtext2html(speechdata.speech)$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop speech$$";fileLines.Add(fileLine); + fileLine="
Last $$MAXSPEECHLINES$$ Quotes
$$coloured$$
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerspeech.include"); + fileLines.Clear(); + fileLine="$$if (XPAVAILABLE EQUALS \"Y\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as xp index as xpindex select * from VIEW_XPTOTALPOINTS where playerindex='%%player.playerindex%%'$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
Experience Points
$$xp.xpname$$$$formatfloat(\"%.3f\",xp.points)$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$ENDIF$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"playerxp.include"); + fileLines.Clear(); + fileLine="$$openfile roundlist.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="$$loop row as server index as serverindex select * from servers$$";fileLines.Add(fileLine); + fileLine=" $$loop row as servervariable index as variableindex select * from servervariables where serveridx='%%server.serveridx%%'$$";fileLines.Add(fileLine); + fileLine=" $$%%lowercase(servervariable.variable)%%=servervariable.value$$";fileLines.Add(fileLine); + fileLine=" $$endloop servervariable$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$colouredtext2html(sv_hostname)$$
";fileLines.Add(fileLine); + fileLine=" $$server.hostname$$$$if (server.gameport !EQUALS \"-1\")$$:$$server.gameport$$$$endif$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$lastgametypeid=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as round index as roundindex select * from view_rounds where serverindex = %%server.serveridx%% order by gametypeid,roundidx ASC$$";fileLines.Add(fileLine); + fileLine=" $$if (lastgametypeid !EQUALS round.gametypeid)$$";fileLines.Add(fileLine); + fileLine=" $$lastgametypeid=round.gametypeid$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="

$$round.gametyperealname$$
";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$formatinteger(\"%05d\",round.roundidx)$$";fileLines.Add(fileLine); + fileLine=" $$endloop round$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endloop server$$";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"roundlist.include"); + fileLines.Clear(); + fileLine="$$openfile round_%%round.roundidx%%.html$$";fileLines.Add(fileLine); + fileLine="$$include menu.include$$";fileLines.Add(fileLine); + fileLine="$$loop row as roundvariable index as variableindex select * from roundvariables where roundidx='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$%%lowercase(\"round_\",roundvariable.variable)%%=roundvariable.value$$";fileLines.Add(fileLine); + fileLine="$$endloop roundvariable$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from playerinround where roundindex='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$playercount=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop temprow$$";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from killdata where roundindex='%%round.roundidx%%' and killtype='KILL'$$";fileLines.Add(fileLine); + fileLine="$$kills=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop temprow$$";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from killdata where roundindex='%%round.roundidx%%' and killtype='SUICIDE'$$";fileLines.Add(fileLine); + fileLine="$$suicides=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop temprow$$";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from killdata where roundindex='%%round.roundidx%%' and killtype='TEAMKILL'$$";fileLines.Add(fileLine); + fileLine="$$teamkills=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop temprow$$";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from actiondata where roundindex='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$objectivecount=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop temprow$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (objectivecount > \"3\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="$$teamlosscount=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$teamwincount=\"0\"$$";fileLines.Add(fileLine); + fileLine="$$awolcount=\"0\"$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*),teamwinidx from teamwindata where roundindex='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$teamwincount=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*),teamlossidx from teamlossdata where roundindex='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$teamlosscount=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as temprow index as tempindex select count(*) from playerinround where roundindex='%%roundindex%%' and playerindex not in (select playerindex from teamwindata where roundindex='%%round.roundidx%%') and playerindex not in (select playerindex from teamlossdata where roundindex='%%round.roundidx%%')$$";fileLines.Add(fileLine); + fileLine="$$awolcount=temprow.0$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if ((teamwincount EQUALS \"0\") AND (teamlosscount EQUALS \"0\"))$$";fileLines.Add(fileLine); + fileLine="$$if (awolcount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$teamtype=\"awol\"$$";fileLines.Add(fileLine); + fileLine=" $$teamtitle=\"Players\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="$$else$$";fileLines.Add(fileLine); + fileLine="$$if (teamwincount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$teamtype=\"win\"$$";fileLines.Add(fileLine); + fileLine=" $$teamtitle=\"VICTORS\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (teamlosscount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$teamtype=\"loss\"$$";fileLines.Add(fileLine); + fileLine=" $$teamtitle=\"VANQUISHED\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (awolcount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$teamtype=\"awol\"$$";fileLines.Add(fileLine); + fileLine=" $$teamtitle=\"Leaving The Battlefield Early Soldiers?\"$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="
Round $$roundindex$$$$gametype_%%round.gametype%%_realname$$
$$map_%%round.mapname%%_realname$$";fileLines.Add(fileLine); + fileLine="$$if (map_%%round.mapname%%_image !EQUALS \"\")$$

$$endif$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (gametype_%%round.gametype%%_image !EQUALS \"\")$$$$endif$$";fileLines.Add(fileLine); + fileLine="$$include roundvariables.include$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if (objectivecount !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine="$$if (objectivecount < \"4\")$$";fileLines.Add(fileLine); + fileLine="$$loop row as objectives index as objectiveindex select count(*),dropped,player.playerindex,name,action from actiondata,player where player.playerindex=actiondata.playerindex and roundindex='%%round.roundidx%%' group by actiondata.playerindex,action$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop objectives$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="
Time Played$$formatduration(\"%M:%S\",round.duration)$$
Players$$playercount$$
Kills$$kills$$
Team Kills$$teamkills$$
Suicides$$suicides$$
";fileLines.Add(fileLine); + fileLine="$$if (action_%%objectives.action%%_image !EQUALS \"\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="$$action_%%objectives.action%%_realname$$";fileLines.Add(fileLine); + fileLine="
$$playerdisplayname=objectives.name$$$$playerdisplaydropped=objectives.dropped$$$$playerdisplayplayerindex=\"-1\"$$$$include playerdisplay.include$$
";fileLines.Add(fileLine); + fileLine="$$if (XPAVAILABLE EQUALS \"Y\")$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as xp index as xpindex select distinct(pointsindex) as pointsindex from view_xppoints where roundindex='%%round.roundidx%%'$$";fileLines.Add(fileLine); + fileLine="$$loop row as xppoints index as xppointsindex select * from view_xppoints where roundindex='%%round.roundidx%%' and pointsindex='%%xp.pointsindex%%' order by points desc limit 1$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop xp players$$";fileLines.Add(fileLine); + fileLine="$$endloop xp points type$$";fileLines.Add(fileLine); + fileLine="
Experience
Top $$xppoints.xpname$$$$colouredtext2html(xppoints.playername)$$$$formatfloat(\"%.3f\",xppoints.points)$$
";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$playerdisplayplayerindex=\"-1\"$$$$loop row as objectives index as objectiveindex select count(*) as actioncount,dropped,player.playerindex,name,action from actiondata,player where roundindex='%%round.roundidx%%' and player.playerindex=actiondata.playerindex group by player.playerindex,action$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop objectives$$";fileLines.Add(fileLine); + fileLine="
Objectives
ObjectivePlayerTimes
Achieved
$$action_%%objectives.action%%_realname$$$$playerdisplayname=objectives.name$$$$playerdisplaydropped=objectives.dropped$$$$playerdisplayplayerindex=\"-1\"$$$$include playerdisplay.include$$$$objectives.actioncount$$
";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include roundteam.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include roundteam.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include roundteam.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine=" $$include roundteam.include$$";fileLines.Add(fileLine); + fileLine="
";fileLines.Add(fileLine); + fileLine="$$include roundspeech.include$$";fileLines.Add(fileLine); + fileLine="$$closefile$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"round.include"); + fileLines.Clear(); + fileLine="$$IF (round.servertype EQUALS \"COD1\")$$";fileLines.Add(fileLine); + fileLine=" $$if (round_shortversion !EQUALS \"\")$$Version$$round_shortversion$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_sv_punkbuster !EQUALS \"\")$$Punkbuster$$image=Case(round_sv_punkbuster,\"0\",\"images/red.gif\",\"1\",\"images/green.gif\")$$$$if (image !EQUALS \"\")$$$$endif$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_friendlyfire !EQUALS \"\")$$Friendly Fire$$Case(round_scr_friendlyfire,scr_friendlyfire,scr_friendlyfire,\"0\",\"Off\",\"1\",\"On\",\"2\",\"Reflective\",\"3\",\"Shared\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_killcam !EQUALS \"\")$$Kill Cam$$endif$$";fileLines.Add(fileLine); + fileLine="$$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (round.servertype EQUALS \"COD2\")$$";fileLines.Add(fileLine); + fileLine=" $$if (round_shortversion !EQUALS \"\")$$Version$$round_shortversion$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_sv_punkbuster !EQUALS \"\")$$Punkbuster$$image=Case(round_sv_punkbuster,\"0\",\"images/red.gif\",\"1\",\"images/green.gif\")$$$$if (image !EQUALS \"\")$$$$endif$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_friendlyfire !EQUALS \"\")$$Friendly Fire$$Case(round_scr_friendlyfire,scr_friendlyfire,scr_friendlyfire,\"0\",\"Off\",\"1\",\"On\",\"2\",\"Reflective\",\"3\",\"Shared\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_killcam !EQUALS \"\")$$Kill Cam$$endif$$";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (round.servertype EQUALS \"COD4\")$$";fileLines.Add(fileLine); + fileLine=" $$if (round_shortversion !EQUALS \"\")$$Version$$round_shortversion$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_sv_punkbuster !EQUALS \"\")$$Punkbuster$$image=Case(round_sv_punkbuster,\"0\",\"images/red.gif\",\"1\",\"images/green.gif\")$$$$if (image !EQUALS \"\")$$$$endif$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_friendlyfire !EQUALS \"\")$$Friendly Fire$$Case(round_scr_friendlyfire,scr_friendlyfire,scr_friendlyfire,\"0\",\"Off\",\"1\",\"On\",\"2\",\"Reflective\",\"3\",\"Shared\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_killcam !EQUALS \"\")$$Kill Cam$$endif$$";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (round.servertype EQUALS \"COD5\")$$";fileLines.Add(fileLine); + fileLine=" $$if (round_shortversion !EQUALS \"\")$$Version$$round_shortversion$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_sv_punkbuster !EQUALS \"\")$$Punkbuster$$image=Case(round_sv_punkbuster,\"0\",\"images/red.gif\",\"1\",\"images/green.gif\")$$$$if (image !EQUALS \"\")$$$$endif$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_friendlyfire !EQUALS \"\")$$Friendly Fire$$Case(round_scr_friendlyfire,scr_friendlyfire,scr_friendlyfire,\"0\",\"Off\",\"1\",\"On\",\"2\",\"Reflective\",\"3\",\"Shared\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_killcam !EQUALS \"\")$$Kill Cam$$endif$$";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$IF (round.servertype EQUALS \"WOLFENSTEIN\")$$";fileLines.Add(fileLine); + fileLine=" $$if (round_shortversion !EQUALS \"\")$$Version$$round_shortversion$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_sv_punkbuster !EQUALS \"\")$$Punkbuster$$image=Case(round_sv_punkbuster,\"0\",\"images/red.gif\",\"1\",\"images/green.gif\")$$$$if (image !EQUALS \"\")$$$$endif$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_friendlyfire !EQUALS \"\")$$Friendly Fire$$Case(round_scr_friendlyfire,scr_friendlyfire,scr_friendlyfire,\"0\",\"Off\",\"1\",\"On\",\"2\",\"Reflective\",\"3\",\"Shared\")$$$$endif$$";fileLines.Add(fileLine); + fileLine=" $$if (round_scr_killcam !EQUALS \"\")$$Kill Cam$$endif$$";fileLines.Add(fileLine); + fileLine=" $$ELSE$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine=" $$ENDIF$$";fileLines.Add(fileLine); + fileLine="$$ENDIF$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"roundvariables.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="
$$teamtitle$$
$$include roundplayer.include$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"roundteam.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$if ((teamtype EQUALS \"win\") OR (teamtype EQUALS \"loss\"))$$";fileLines.Add(fileLine); + fileLine=" $$restriction=\"and playerinround.playerindex in (select playerindex from team%%teamtype%%data where roundindex='%%round.roundidx%%')\"$$";fileLines.Add(fileLine); + fileLine="$$else$$";fileLines.Add(fileLine); + fileLine=" $$restriction=\"and playerinround.playerindex not in (select playerindex from teamwindata where roundindex='%%round.roundidx%%') AND playerinround.playerindex not in (select playerindex from teamlossdata where roundindex='%%round.roundidx%%')\"$$";fileLines.Add(fileLine); + fileLine="$$endif$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$loop row as playerinround index as playerinroundindex select player.dropped as dropped,playerinround.score as score,playerinround.skill as skill,playerinround.playerindex as playerindex,playerinround.kills as kills,playerinround.deaths as deaths,playerinround.suicides as suicides, playerinround.teamkills as teamkills,playerinround.duration as duration,player.name as playername from playerinround,player where playerinround.playerindex = player.playerindex and roundindex='%%round.roundidx%%' %%restriction%% order by playerinround.score desc$$";fileLines.Add(fileLine); + fileLine=" $$topweaponname=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$topweaponimage=\"\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as playerkilldata index as playerkilldataindex select * from killdata where playerindex='%%playerinround.playerindex%%' and roundindex='%%round.roundidx%%' group by playerweapon order by count(*) desc limit 1$$";fileLines.Add(fileLine); + fileLine=" $$topweaponid=weapon_%%playerkilldata.playerweapon%%_id$$";fileLines.Add(fileLine); + fileLine=" $$topweaponname=weapon_%%playerkilldata.playerweapon%%_realname$$";fileLines.Add(fileLine); + fileLine=" $$topweaponimage=weapon_%%playerkilldata.playerweapon%%_image$$";fileLines.Add(fileLine); + fileLine=" $$endloop playerkilldata$$";fileLines.Add(fileLine); + fileLine=" $$playerdisplayname=playerinround.playername$$$$playerdataplayerindex=playerinround.playerindex$$$$playerdisplaydropped=playerinround.dropped$$";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop playerinround$$";fileLines.Add(fileLine); + fileLine="
#PlayerScoreSkillKillsDeathsSuicidesTeam
Kills
Time
Played
Main Weapon
$$playerinroundindex$$$$include playerdisplay.include$$$$formatfloat(\"%.1f\",playerinround.score)$$$$formatfloat(\"%.1f\",playerinround.skill)$$$$playerinround.kills$$$$playerinround.deaths$$$$playerinround.suicides$$$$playerinround.teamkills$$$$formatduration(\"%M:%S\",playerinround.duration)$$$$if (topweaponimage !EQUALS \"\")$$
$$endif$$$$topweaponname$$
";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"roundplayer.include"); + fileLines.Clear(); + fileLine="";fileLines.Add(fileLine); + fileLine="$$playerdataplayerindex=-1$$";fileLines.Add(fileLine); + fileLine="$$loop row as speech index as speechindex select speech,name,speechdata.playerindex,dropped from speechdata,player where roundindex='%%round.roundidx%%' and speechdata.playerindex=player.playerindex order by speechidx$$";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine=" ";fileLines.Add(fileLine); + fileLine="";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="
$$playerdisplayname=speech.name$$$$playerdisplaydropped=speech.dropped$$$$include playerdisplay.include$$$$colouredtext2html(speech.speech)$$
";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"roundspeech.include"); +} diff --git a/DefaultTemplate2.cpp b/DefaultTemplate2.cpp new file mode 100644 index 0000000..57ea746 --- /dev/null +++ b/DefaultTemplate2.cpp @@ -0,0 +1,79 @@ +#include +void ExportTemplateFile(wxString &directory,wxArrayString &fileLines,char *filename); +void ExportTemplateQuick(wxString &directory) +{ + wxString filename; + wxArrayString fileLines; + wxString fileLine; + fileLines.Clear(); + fileLine="$$roundsalreadyprocessed=ReadStatistic(\"roundsalreadyprocessed\")$$";fileLines.Add(fileLine); + fileLine="$$MinPlayersInRound=ReadConfig(\"/General/MinPlayersInRound\")$$";fileLines.Add(fileLine); + fileLine="$$MinRoundsPerPlayer=ReadConfig(\"/General/MinRoundsPerPlayer\")$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Main Page\")$$$$include quickmainpage.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Awards\")$$$$include quickawards.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Skill List\")$$$$messagecentrekey=\"TopSkill\"$$$$title=\"^7Skill\"$$$$sortkey=\"skill\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Score List\")$$$$messagecentrekey=\"TopScore\"$$$$title=\"^7Score\"$$$$sortkey=\"score\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Weighted Skill List\")$$$$messagecentrekey=\"TopWeightedSkill\"$$$$title=\"^7Weighted Skill\"$$$$sortkey=\"skillweighted\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Weighted Score List\")$$$$messagecentrekey=\"TopWeightedScore\"$$$$title=\"^7Weighted Score\"$$$$sortkey=\"scoreweighted\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Kill List\")$$$$messagecentrekey=\"TopKills\"$$$$title=\"^7Kills\"$$$$sortkey=\"kills\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Death List\")$$$$messagecentrekey=\"TopDeaths\"$$$$title=\"^7Deaths\"$$$$sortkey=\"deaths\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Kill List\")$$$$messagecentrekey=\"TopTeamKills\"$$$$title=\"^7Team Kills\"$$$$sortkey=\"teamkills\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Win List\")$$$$messagecentrekey=\"TopTeamWins\"$$$$title=\"^7Team Wins\"$$$$sortkey=\"teamwins\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Loss List\")$$$$messagecentrekey=\"TopTeamLosses\"$$$$title=\"^7Team Losses\"$$$$sortkey=\"teamlosses\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Kill Streak List\")$$$$messagecentrekey=\"TopKillStreak\"$$$$title=\"^7Longest Kill Streak\"$$$$sortkey=\"longestkillstreak\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Team Kill Streak List\")$$$$messagecentrekey=\"TopTeamKillStreak\"$$$$title=\"^7Longest Team Kill Streak\"$$$$sortkey=\"longestteamkillstreak\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Death Streak List\")$$$$messagecentrekey=\"TopDeathStreak\"$$$$title=\"^7Longest Death Streak\"$$$$sortkey=\"longestdeathstreak\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Suicide List\")$$$$messagecentrekey=\"TopSuicides\"$$$$title=\"^7Suicides\"$$$$sortkey=\"suicides\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Time Played List\")$$$$messagecentrekey=\"TopTimePlayed\"$$$$title=\"^7Time Played\"$$$$sortkey=\"duration\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"Rounds Played List\")$$$$messagecentrekey=\"TopRoundsPlayed\"$$$$title=\"^7Rounds Played\"$$$$sortkey=\"rounds\"$$$$include quickplayerlists.html$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"XP List\")$$$$include quickxplists.html$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quick.template"); + fileLines.Clear(); + fileLine="$$suffix=\"classes\"$$$$table=\"class\"$$$$title=\"Class\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + fileLine="$$suffix=\"gametypes\"$$$$table=\"gametype\"$$$$title=\"Game Type\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + fileLine="$$suffix=\"locations\"$$$$table=\"location\"$$$$title=\"Location\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + fileLine="$$suffix=\"maps\"$$$$table=\"map\"$$$$title=\"Map\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + fileLine="$$suffix=\"weapons\"$$$$table=\"weapon\"$$$$title=\"Weapon\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + fileLine="$$suffix=\"teams\"$$$$table=\"team\"$$$$title=\"Team\"$$$$include quicktotallist.html$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quickmainpage.html"); + fileLines.Clear(); + fileLine="$$loop row as totaltype index as totaltypeindex select * from %%table%%$$";fileLines.Add(fileLine); + fileLine="$$messagecentrekey=\"Top%%table%%%%totaltype.id%%\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as playertotal index as playertotalindex select * from view_killtotal%%suffix%% where itemindex='%%totaltype.idx%%' order by kills desc limit 1$$";fileLines.Add(fileLine); + fileLine="$$MessageCentre(messagecentrekey,playertotal.name,playertotal.kills)$$";fileLines.Add(fileLine); + fileLine="$$endloop playertotal$$";fileLines.Add(fileLine); + fileLine="$$endloop totaltype$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quicktotallist.html"); + fileLines.Clear(); + fileLine="$$loop row as awarddef index as awarddefindex select * from awarddefinition$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=\"0\"$$";fileLines.Add(fileLine); + fileLine=" $$loop row as awardpoints index as awardpointsindex select count(*) from view_awardpoints where awardindex='%%awarddef.awardindex%%'$$";fileLines.Add(fileLine); + fileLine=" $$pointsrecorded=awardpoints.0$$";fileLines.Add(fileLine); + fileLine=" $$endloop awardpoints$$";fileLines.Add(fileLine); + fileLine=" $$if (pointsrecorded !EQUALS \"0\")$$";fileLines.Add(fileLine); + fileLine=" $$if (awarddef.weighted EQUALS \"Y\")$$";fileLines.Add(fileLine); + fileLine=" $$loopcommand=\"loop row as awardpoints index as awardpointsindex select coalesce(cast(sum(score)as float)/cast(count(score)as float),'-9999999') as awardscore,playername from view_awardpoints where awardindex='%%awarddef.awardindex%%' group by playerindex order by awardscore desc limit 1\"$$";fileLines.Add(fileLine); + fileLine=" $$else$$";fileLines.Add(fileLine); + fileLine=" $$loopcommand=\"loop row as awardpoints index as awardpointsindex select sum(score) as awardscore,playername from view_awardpoints where awardindex='%%awarddef.awardindex%%' group by playerindex order by awardscore desc limit 1\"$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine=" $$%%loopcommand%%$$";fileLines.Add(fileLine); + fileLine=" $$MessageCentre(\"AWARD%%awarddef.id%%\",awardpoints.playername,awardpoints.awardscore)$$";fileLines.Add(fileLine); + fileLine=" $$endloop awardpoints$$";fileLines.Add(fileLine); + fileLine=" $$endif$$";fileLines.Add(fileLine); + fileLine="$$endloop awarddef$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quickawards.html"); + fileLines.Clear(); + fileLine="$$loop row as player index as playerindex select * from view_player order by %%sortkey%% desc limit 1$$";fileLines.Add(fileLine); + fileLine="$$MessageCentre(messagecentrekey,player.name,player.%%sortkey%%)$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quickplayerlists.html"); + fileLines.Clear(); + fileLine="$$loop row as xptype index as xptypeindex select * from xp$$";fileLines.Add(fileLine); + fileLine="$$updatestatus(\"xp %%xptype.id%%\")$$$$openfile xp_%%xptype.id%%.html$$";fileLines.Add(fileLine); + fileLine="$$messagecentrekey=\"TopXP%%xptype.id%%\"$$";fileLines.Add(fileLine); + fileLine="$$loop row as xptotal index as xptotalindex select * from view_xptotalpoints where pointsindex='%%xptype.idx%%' order by points desc limit 1$$";fileLines.Add(fileLine); + fileLine="$$MessageCentre(messagecentrekey,xptotal.playername,formatfloat(\"%.3f\",xptotal.points))$$";fileLines.Add(fileLine); + fileLine="$$endloop$$";fileLines.Add(fileLine); + fileLine="$$endloop xptype$$";fileLines.Add(fileLine); + ExportTemplateFile(directory,fileLines,"quickxplists.html"); +} diff --git a/DirectoryConfigItemGUI.cpp b/DirectoryConfigItemGUI.cpp new file mode 100644 index 0000000..90052aa --- /dev/null +++ b/DirectoryConfigItemGUI.cpp @@ -0,0 +1,206 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "DirectoryConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "Progress.h" + +BEGIN_EVENT_TABLE(DirectoryConfigItemGUI, wxPanel) + EVT_SIZE(DirectoryConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,DirectoryConfigItemGUI::OnTextChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,DirectoryConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +DirectoryConfigItemGUI::DirectoryConfigItemGUI() +{ + maxCharacters=-1; + configKey=""; +} + +void DirectoryConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +DirectoryConfigItemGUI::~DirectoryConfigItemGUI() +{ +} + +void DirectoryConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void DirectoryConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + int maxCharactersIn) +{ + wxSizeEvent event; + wxSize buttonSize(16,16); + + labelText=labelTextIn; + defaultValue=defaultValueIn; + maxCharacters=maxCharactersIn; + + //SetConfigKey(configKey); + + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + configKey=configKeyIn; + SetConfigKey(configKey); + button.Create(this, + WINDOW_ID_CONFIG_BUTTON, + wxArtProvider::GetIcon(wxART_FOLDER, + wxART_OTHER, + buttonSize)); + + OnResize(event); +} + +wxString DirectoryConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int DirectoryConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void DirectoryConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void DirectoryConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + int buttonWidth; + int buttonHeight; + int widthForTextEdit; + int fixedWidth; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=button.GetSize(); + buttonWidth=itemSize.GetWidth(); + buttonHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-buttonWidth; + fixedWidth=(maxCharacters * FONT_CHAR_WIDTH)+FONT_TEXT_CTRL_GAP; + if (maxCharacters>0) + { + // We have an overriding field width + if (fixedWidth0) + { + textEdit.SetValue(newDirectory); + } + +} + +void DirectoryConfigItemGUI::SetValue(wxString &value) +{ + textEdit.SetValue(value); +} + diff --git a/DirectoryConfigItemGUI.h b/DirectoryConfigItemGUI.h new file mode 100644 index 0000000..d1baa60 --- /dev/null +++ b/DirectoryConfigItemGUI.h @@ -0,0 +1,45 @@ +#ifndef __DIRECTORYCONFIGITEMGUI +#define __DIRECTORYCONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class DirectoryConfigItemGUI : public BaseConfigItemGUI +{ + public: + DirectoryConfigItemGUI(); + virtual ~DirectoryConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + int maxCharactersIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + void SetValue(wxString &value); + protected: + + private: + wxTextCtrl textEdit; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/DropList.cpp b/DropList.cpp new file mode 100644 index 0000000..ccf3090 --- /dev/null +++ b/DropList.cpp @@ -0,0 +1,314 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "DropList.h" +#include "DropListEntry.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" +#include "Progress.h" + +DropList::DropList() +{ +} + +DropList::~DropList() +{ +} + +int DropList::Compare(DropListEntry **entry1,DropListEntry **entry2) +{ + wxString name1; + wxString name2; + + name1=DecolouriseName((*entry1)->name); + name2=DecolouriseName((*entry2)->name); + + return (name1.Cmp(name2)); +} + +void DropList::Sort() +{ + allowList.Sort(DropList::Compare); + dropList.Sort(DropList::Compare); +} + +void DropList::Load() +{ + int dropCount; + int dropIndex; + wxTextFile fp; + wxString configKey="/General/DropList"; + wxString configValue; + bool retVal; + wxString status; + DropListEntry dropListEntry; + + status="Reading Drop List"; progress->SetStatus(status); + globalStatistics.configData.ReadTextValue(configKey,&configValue,"droplist.dat"); + if (wxFileExists(configValue)) + { + retVal=fp.Open(configValue); + dropList.Clear(); + allowList.Clear(); + if (retVal) + { + dropCount=fp.GetLineCount(); + progress->Initiate(dropCount, + "", + (long)1, + "", + 1); + for (dropIndex=0;dropIndexUpdate(dropIndex+1); + dropListEntry.ReadFromFile(&fp,dropIndex); + if (dropListEntry.DropType()) + { + dropList.Add(dropListEntry); + } + else + { + allowList.Add(dropListEntry); + } + } + } + } + + cheatListCache.Clear(); + dropListCache.Clear(); + notDroppedListCache.Clear(); + +} + +void DropList::Write() +{ + DropListEntry dropListEntry; + int dropCount; + int dropIndex; + FILE *fp; + wxString configKey="/General/DropList"; + wxString configValue; + + globalStatistics.configData.ReadTextValue(configKey,&configValue,"droplist.dat"); + fp=fopen(configValue.GetData(),"w"); + if (fp!=NULL) + { + dropCount=allowList.GetCount(); + for (dropIndex=0;dropIndex5)||(dropCount>5)) + { + useCache=true; + } + else + { + useCache=false; + } + if (InCache(name,&dropped,cheat)) + { + return (dropped); + } + + // If we have an allow list then we default to dropped + // If we do not have an allow list we default to not + // dropped + dropped=(allowCount>0); + + // See if it is in the allow list + for (dropIndex=0;dropIndexMatches(name,cheat)) + { + // This name matches this pattern so the + // name is allowed + dropped=false; + break; + } + } + + // we have scanned the allow list - even though we may have + // decided to drop this player we need to see if this player + // is a cheat or not + for (dropIndex=0;(dropIndexMatches(name,cheat)) + { + // This name matches this pattern so the + // name is dropped + dropped=true; + break; + } + } + + AddToCache(name,dropped,*cheat); + return (dropped); +} + diff --git a/DropList.h b/DropList.h new file mode 100644 index 0000000..d3fd5d3 --- /dev/null +++ b/DropList.h @@ -0,0 +1,41 @@ +#ifndef __DROPLIST +#define __DROPLIST + +// wxWindows includes +#include +#include + +// Statsgen Includes +#include "DropListEntry.h" + +class DropList +{ + public: + bool IsDropped(wxString &name,bool *cheat); + void Sort(); + void Load(); + void Write(); + DropList(); + virtual ~DropList(); + void AddCheat(wxString &name); + void AddEntry(DropListEntry &entry); + void RemoveEntry(DropListEntry &entry); + int DropIndex(wxString &name,ArrayOfDropListEntry &list); + void AddToCache(wxString &name,bool dropped,bool cheat); + bool InCache(wxString &name,bool *dropped,bool *cheat); + + static int Compare(DropListEntry **entry1,DropListEntry **entry2); + + ArrayOfDropListEntry allowList; + ArrayOfDropListEntry dropList; + + wxSortedArrayString cheatListCache; + wxSortedArrayString dropListCache; + wxSortedArrayString notDroppedListCache; + + bool useCache; + +}; + + +#endif diff --git a/DropListDialog.cpp b/DropListDialog.cpp new file mode 100644 index 0000000..78972fe --- /dev/null +++ b/DropListDialog.cpp @@ -0,0 +1,58 @@ +// Statsgen Includes +#include "DropListDialog.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +DropListDialog::DropListDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) : GenericOKCancelDialog + (parent, + id, + title, + pos, + size, + style, + name) +{ + panel=new DropListEditorPanel(); + panel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); +} + +bool DropListDialog::DisplayDialog() +{ + return (GenericOKCancelDialog::DisplayDialog((wxPanel *)panel)); +} + +DropListDialog::~DropListDialog() +{ +} + +void DropListDialog::OnSave(wxCommandEvent &event) +{ + wxString msg; + + // Write the DropList List to disk + globalStatistics.dropList.Write(); + globalStatistics.configData.CommitChanges(); + // Do any standard Save + GenericOKCancelDialog::OnSave(event); +} + +void DropListDialog::OnQuit(wxCommandEvent &event) +{ + wxString msg; + + // Re-read the DropList List to disk + globalStatistics.configData.RollbackChanges(); + globalStatistics.dropList.Load(); + // Do any standard Save + GenericOKCancelDialog::OnQuit(event); +} + diff --git a/DropListDialog.h b/DropListDialog.h new file mode 100644 index 0000000..31573fd --- /dev/null +++ b/DropListDialog.h @@ -0,0 +1,35 @@ +#ifndef __DROPLISTDIALOG +#define __DROPLISTDIALOG + +#include +#include + +// Statsgen Includes +#include "GenericOKCancelDialog.h" +#include "DropListEditorPanel.h" +#include "WindowIDs.h" + +class DropListDialog : public GenericOKCancelDialog +{ + public: + DropListDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + + virtual ~DropListDialog(); + + virtual void OnSave(wxCommandEvent& event); + virtual void OnQuit(wxCommandEvent& event); + virtual bool DisplayDialog(); + + protected: + + private: + DropListEditorPanel *panel; +}; + +#endif diff --git a/DropListEditorPanel.cpp b/DropListEditorPanel.cpp new file mode 100644 index 0000000..7cbf12a --- /dev/null +++ b/DropListEditorPanel.cpp @@ -0,0 +1,629 @@ +// wx includes +#include +#include +#include +#include + +// Statsgen Includes +#include "DropListEditorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(DropListEditorPanel, wxPanel) + EVT_SIZE(DropListEditorPanel::OnResize) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_DROPLIST, + DropListEditorPanel::OnDropListRightClick) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_PLAYERCACHE, + DropListEditorPanel::OnPlayerRightClick) + EVT_MENU(PLAYER_POPUP_ADD_DROP,DropListEditorPanel::OnPopupMenu) + EVT_MENU(PLAYER_POPUP_ADD_ALLOW,DropListEditorPanel::OnPopupMenu) + EVT_MENU(PLAYER_POPUP_ADD_CHEAT,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_DELETE,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_ALLOW,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_DROP,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_DONT_DROP,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_CHEAT,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_DONTUSECOLOURCODES,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_USECOLOURCODES,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_USEEXACTMATCH,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_USEPREFIXMATCH,DropListEditorPanel::OnPopupMenu) + EVT_MENU(DROPLIST_POPUP_USEREGEXPMATCH,DropListEditorPanel::OnPopupMenu) + EVT_LIST_END_LABEL_EDIT(WINDOW_ID_DROPLIST,DropListEditorPanel::OnLabelEdit) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,DropListEditorPanel::OnTextChange) +END_EVENT_TABLE() + +DropListEditorPanel::DropListEditorPanel() +{ + playerCache=NULL; + dropListList=NULL; + filterString=""; + + // Lets load up the current DropList List into + // the global statistics - we can transfer + // it across into the tree during creation + globalStatistics.dropList.Load(); +} + +bool DropListEditorPanel::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + wxString dummyConfigKey="/tmp/tmp"; + wxString labelText="Player Filter"; + wxString configKey; + + wxPanel::Create( parent, id, + pos, + size, + style, + name); + + playerCache=new PlayerCachePanel(dummyConfigKey,labelText); + playerCache->SetFilterType(PlayerCachePanel::FILTER_TYPE_NO_CASE); + playerCache->Create(this, + WINDOW_ID_PLAYERCACHE, + wxDefaultPosition, + wxDefaultSize); + dropListList=new wxListCtrl(this, + WINDOW_ID_DROPLIST, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT| + wxLC_EDIT_LABELS); + RefreshDropListTree(); + + configItems=new GroupedConfigItemsPanel("Minimum Players"); + configItems->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE,wxDefaultPosition,wxDefaultSize); + configKey="/General/MinPlayersInRound"; + configItems->Add("Minimum Players In Round For It To Count",configKey,"0",3); + configKey="/General/MinRoundsPerPlayer"; + configItems->Add("Minimum Rounds Per Player",configKey,"0",6); + configKey="/tmp/DropListPlayerFilter"; + configItems->Add("Drop List Player Filter",configKey,"",-1); + + wxSizeEvent dummyEvent; + OnResize(dummyEvent); + return (true); +} + +void DropListEditorPanel::OnTextChange(wxCommandEvent &event) +{ + wxString configKey; + wxString newFilterString; + configKey="/tmp/DropListPlayerFilter"; + globalStatistics.configData.ReadTextValue(configKey,&newFilterString); + if (newFilterString.Cmp(filterString)!=0) + { + // filter string has changed + RefreshDropListTree(); + } +} + +void DropListEditorPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int playerCacheWidth; + int playerCacheHeight; + int panelWidth; + int panelHeight; + int dropListWidth; + int dropListHeight; + int configWidth; + int configHeight; + wxString msg; + + + if (dropListList!=NULL) + { + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + configItems->SetSize(0,0,1,1); + itemSize=configItems->GetSize(); + configWidth=panelWidth; + configHeight=itemSize.GetHeight(); + configHeight=configItems->PreferredHeight(); + + panelHeight-=configHeight; + + playerCacheWidth=panelWidth; + playerCacheHeight=panelHeight/2; + dropListWidth=panelWidth; + dropListHeight=panelHeight/2; + + configItems->SetSize(0,0,configWidth,configHeight); + dropListList->SetSize(0,configHeight,dropListWidth,dropListHeight); + playerCache->SetSize(0,dropListHeight+configHeight,playerCacheWidth,playerCacheHeight); + } + +} + +void DropListEditorPanel::AddDropListEntry(int index, + DropListEntry &dropEntry) +{ + long itemIndex; + long listIndex; + long rowNumber; + int allowCount; + wxString allowDropText; + wxString whyDroppedText; + wxString matchTypeText; + wxString colourText; + wxString configKey; + bool addRow; + + configKey="/tmp/DropListPlayerFilter"; + globalStatistics.configData.ReadTextValue(configKey,&filterString); + allowCount=globalStatistics.dropList.allowList.GetCount(); + + rowNumber=index; + itemIndex=index; + itemIndex++; + allowDropText =DROPLISTPANEL_ALLOW; + whyDroppedText =""; + matchTypeText =DROPLISTPANEL_EXACT; + colourText =DROPLISTPANEL_NONCOLOURED; + + if (dropEntry.DropType()) + { + itemIndex*=-1; + rowNumber+=allowCount; + allowDropText=DROPLISTPANEL_DROP; + whyDroppedText=DROPLISTPANEL_PLAYERDROP; + if (dropEntry.cheat) + { + whyDroppedText=DROPLISTPANEL_PLAYERCHEAT; + } + } + if (dropEntry.dontDrop) + { + allowDropText=DROPLISTPANEL_DONT_DROP; + } + + if (dropEntry.prefix) + { + matchTypeText =DROPLISTPANEL_PREFIX; + } + if (dropEntry.regularExpression) + { + matchTypeText =DROPLISTPANEL_REGEXP; + } + if (dropEntry.coloured) + { + colourText =DROPLISTPANEL_COLOURED; + } + + addRow=true; + if ((!dropEntry.prefix)&& + (!dropEntry.regularExpression)&& + (dropEntry.DropType())&& + (filterString.Length()>0)) + { + wxString decolourisedName; + decolourisedName=DecolouriseName(dropEntry.name).MakeLower(); + filterString=filterString.MakeLower(); + if (decolourisedName.Contains(filterString)) + { + // filter enabled and name contains filter string + } + else + { + // filter string enabled and filter string not in + // name + addRow=false; + } + } + if (addRow) + { + rowNumber=dropListList->GetItemCount(); + listIndex=dropListList->InsertItem(rowNumber,dropEntry.name); + dropListList->SetItemData(listIndex,itemIndex); + dropListList->SetItem(rowNumber,1,DecolouriseName(dropEntry.name)); + dropListList->SetItem(rowNumber,2,allowDropText); + dropListList->SetItem(rowNumber,3,whyDroppedText); + dropListList->SetItem(rowNumber,4,colourText); + dropListList->SetItem(rowNumber,5,matchTypeText); + } +} + +void DropListEditorPanel::RefreshDropListTree() +{ + DropListEntry dropListEntry; + wxListItem listColumn; + int dropListCount; + int dropListIndex; + + globalStatistics.dropList.Sort(); + dropListList->Hide(); + + dropListList->DeleteAllColumns(); + dropListList->DeleteAllItems(); + listColumn.SetText("Name"); + dropListList->InsertColumn(0,listColumn); + listColumn.SetText(""); + dropListList->InsertColumn(1,listColumn); + listColumn.SetText("Allow/Drop"); + dropListList->InsertColumn(2,listColumn); + listColumn.SetText("Why Dropped"); + dropListList->InsertColumn(3,listColumn); + listColumn.SetText("Coloured Codes"); + dropListList->InsertColumn(4,listColumn); + listColumn.SetText("Match Type"); + dropListList->InsertColumn(5,listColumn); + + dropListCount=globalStatistics.dropList.allowList.GetCount(); + for (dropListIndex=0;dropListIndexSetColumnWidth(0,wxLIST_AUTOSIZE); + dropListList->SetColumnWidth(1,wxLIST_AUTOSIZE); + dropListList->SetColumnWidth(2,wxLIST_AUTOSIZE); + dropListList->SetColumnWidth(3,wxLIST_AUTOSIZE); + dropListList->SetColumnWidth(4,wxLIST_AUTOSIZE); + dropListList->SetColumnWidth(5,wxLIST_AUTOSIZE); + dropListList->Show(); +} + +void DropListEditorPanel::OnDropListRightClick(wxListEvent &event) +{ + wxString msg; + wxMenu popupMenu(_T("")); + wxString menuItem; + + // What have we right clicked on - parent or child? + menuItem="Delete"; popupMenu.Append(DROPLIST_POPUP_DELETE,menuItem); + popupMenu.AppendSeparator(); + + menuItem="Dont Use Colour Codes"; popupMenu.Append(DROPLIST_POPUP_DONTUSECOLOURCODES,menuItem); + menuItem="Use Colour Codes"; popupMenu.Append(DROPLIST_POPUP_USECOLOURCODES,menuItem); + popupMenu.AppendSeparator(); + + menuItem="Only Allow These Players"; popupMenu.Append(DROPLIST_POPUP_ALLOW,menuItem); + menuItem="These Players Are Cheats"; popupMenu.Append(DROPLIST_POPUP_CHEAT,menuItem); + menuItem="Drop These Players"; popupMenu.Append(DROPLIST_POPUP_DROP,menuItem); + menuItem="Don't Drop These Players"; popupMenu.Append(DROPLIST_POPUP_DONT_DROP,menuItem); + popupMenu.AppendSeparator(); + + menuItem="Use Exact Match"; popupMenu.Append(DROPLIST_POPUP_USEEXACTMATCH,menuItem); + menuItem="Use Prefix Match"; popupMenu.Append(DROPLIST_POPUP_USEPREFIXMATCH,menuItem); + menuItem="Use Regular Exp Match"; popupMenu.Append(DROPLIST_POPUP_USEREGEXPMATCH,menuItem); + popupMenu.AppendSeparator(); + popupMenu.Append(DROPLIST_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void DropListEditorPanel::OnPlayerRightClick(wxListEvent &event) +{ + wxString msg; + wxString menuItem; + wxMenu popupMenu(_T("")); + + // Right clicked on an item in the Player Cache + menuItem="Add To Players To Be Dropped"; + popupMenu.Append(PLAYER_POPUP_ADD_DROP,menuItem); + menuItem="Add To Players Who Are Cheats"; + popupMenu.Append(PLAYER_POPUP_ADD_CHEAT,menuItem); + menuItem="Add To Players To Allow"; + popupMenu.Append(PLAYER_POPUP_ADD_ALLOW,menuItem); + popupMenu.AppendSeparator(); + popupMenu.Append(DROPLIST_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void DropListEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + wxString msg; + int id; + bool removeColourCodes; + wxString howMatched; + wxArrayInt selectedPlayers; + int selectedCount; + int cacheIndex; + wxString decolouredName; + wxString longestMatch; + int length; + int charIndex; + PlayerCacheEntry cacheEntry; + int playerIndex; + int playerCount; + long selectedItem=-1; + int listIndex; + wxString nameToRemove; + + id=event.GetId(); + + switch (id) + { + case DROPLIST_POPUP_ALLOW: + case DROPLIST_POPUP_DONT_DROP: + case DROPLIST_POPUP_DROP: + case DROPLIST_POPUP_CHEAT: + case DROPLIST_POPUP_DONTUSECOLOURCODES: + case DROPLIST_POPUP_USECOLOURCODES: + case DROPLIST_POPUP_USEEXACTMATCH: + case DROPLIST_POPUP_USEPREFIXMATCH: + case DROPLIST_POPUP_USEREGEXPMATCH: + selectedPlayers.Clear(); + selectedItem=dropListList->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + while (selectedItem!=-1) + { + listIndex=(int)dropListList->GetItemData(selectedItem); + DropListEntry oldEntry; + DropListEntry newEntry; + if (listIndex<0) + { + listIndex=abs(listIndex); + listIndex--; + oldEntry=globalStatistics.dropList.dropList.Item(listIndex); + } + else + { + listIndex--; + oldEntry=globalStatistics.dropList.allowList.Item(listIndex); + } + newEntry=oldEntry; + switch (id) + { + case DROPLIST_POPUP_ALLOW: + newEntry.drop=false; + newEntry.cheat=false; + newEntry.dontDrop=false; + break; + case DROPLIST_POPUP_DONT_DROP: + newEntry.drop=false; + newEntry.cheat=false; + newEntry.dontDrop=true; + break; + case DROPLIST_POPUP_DROP: + newEntry.drop=true; + newEntry.cheat=false; + newEntry.dontDrop=false; + break; + case DROPLIST_POPUP_CHEAT: + newEntry.drop=true; + newEntry.cheat=true; + newEntry.dontDrop=false; + break; + case DROPLIST_POPUP_DONTUSECOLOURCODES: + newEntry.coloured=false; + break; + case DROPLIST_POPUP_USECOLOURCODES: + newEntry.coloured=true; + break; + case DROPLIST_POPUP_USEEXACTMATCH: + newEntry.prefix=false; + newEntry.regularExpression=false; + break; + case DROPLIST_POPUP_USEPREFIXMATCH: + newEntry.prefix=true; + newEntry.regularExpression=false; + break; + case DROPLIST_POPUP_USEREGEXPMATCH: + newEntry.prefix=true; + newEntry.regularExpression=true; + break; + } + + globalStatistics.dropList.RemoveEntry(oldEntry); + globalStatistics.dropList.AddEntry(newEntry); + selectedItem=dropListList->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + } + RefreshDropListTree(); + break; + case DROPLIST_POPUP_DELETE: + selectedPlayers.Clear(); + selectedItem=dropListList->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + while (selectedItem!=-1) + { + listIndex=(int)dropListList->GetItemData(selectedItem); + nameToRemove=dropListList->GetItemText(selectedItem); + DropListEntry dropListEntry; + dropListEntry.drop=(listIndex<0); // negative index for drop + dropListEntry.name=nameToRemove; + globalStatistics.dropList.RemoveEntry(dropListEntry); + selectedItem=dropListList->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + } + RefreshDropListTree(); + break; + case PLAYER_POPUP_ADD_ALLOW: + case PLAYER_POPUP_ADD_DROP: + case PLAYER_POPUP_ADD_CHEAT: + // Some sub category questions now + // some are dependent on the amount of + // players selected + removeColourCodes=(wxMessageBox("Remove Colour Codes?","Confirm",wxYES_NO)==wxYES); + playerCache->GetSelectedPlayers(selectedPlayers); + selectedCount=selectedPlayers.GetCount(); + if (selectedCount>1) + { + // we are possibly adding a prefix + wxArrayString choices; + wxString choice; + choice=DROPLISTPANEL_EXACT;choices.Add(choice); + choice=DROPLISTPANEL_PREFIX;choices.Add(choice); + choice=DROPLISTPANEL_REGEXP;choices.Add(choice); + + howMatched=wxGetSingleChoice("How Do You Want To Match The Names?","Choose",choices); + } + else + { + howMatched=DROPLISTPANEL_EXACT; + } + wxArrayString namesToAdd; + wxString nameToAdd; + if (howMatched.Cmp(DROPLISTPANEL_EXACT)!=0) + { + // we have asked for a prefix type match + playerIndex=selectedPlayers.Item(0); + cacheEntry=globalStatistics.playerCache.Item(playerIndex); + if (removeColourCodes) + { + longestMatch=DecolouriseName(cacheEntry.name); + } + else + { + longestMatch=cacheEntry.name; + } + for (cacheIndex=1;cacheIndexdecolouredName.Length()) + { + length=decolouredName.Length(); + } + + // now we need to scan each character + // in the longest match and the decoloured name + // and match when we reach a new character + for (charIndex=0;charIndex1) + { + // found a common piece of string at least 2 char long + // convert it to a regular expression if needed + wxString regularExpression="^"; + if (howMatched.Cmp(DROPLISTPANEL_REGEXP)==0) + { + length=longestMatch.Length(); + for (charIndex=0;charIndexGetItemData(index); + + if (dropListIndex<0) + { + // Drop List + dropListEntry=globalStatistics.dropList.dropList.Item(abs(dropListIndex)-1); + } + else + { + // Allow List + dropListEntry=globalStatistics.dropList.allowList.Item(abs(dropListIndex)-1); + } + +} + diff --git a/DropListEditorPanel.h b/DropListEditorPanel.h new file mode 100644 index 0000000..269d5a7 --- /dev/null +++ b/DropListEditorPanel.h @@ -0,0 +1,72 @@ +#ifndef __DROPLISTEDITORPANEL +#define __DROPLISTEDITORPANEL + +#include +#include + +// Statsgen Includes +#include "PlayerCachePanel.h" +#include "PlayerCacheEntry.h" +#include "DropListEntry.h" +#include "GroupedConfigItemsPanel.h" +#include "WindowIDs.h" + +#define DROPLISTPANEL_PLAYERCHEAT "Cheat" +#define DROPLISTPANEL_PLAYERDROP "Dropped" +#define DROPLISTPANEL_DROP "Drop This Player" +#define DROPLISTPANEL_DONT_DROP "Don't Drop This Player" +#define DROPLISTPANEL_ALLOW "Allow Only" +#define DROPLISTPANEL_EXACT "Exact Name" +#define DROPLISTPANEL_PREFIX "Name Prefix" +#define DROPLISTPANEL_REGEXP "Name Regular Expression" +#define DROPLISTPANEL_COLOURED "Colour Codes Present" +#define DROPLISTPANEL_NONCOLOURED "Colour Codes Removed" +class DropListEditorPanel : public wxPanel +{ + public: + DropListEditorPanel(); + virtual bool Create(wxWindow *parent, + wxWindowID id=-1, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + void OnResize(wxSizeEvent &event); + void OnDropListRightClick(wxListEvent &event); + void OnLabelEdit(wxListEvent &event); + void OnPlayerRightClick(wxListEvent &event); + void OnPopupMenu(wxCommandEvent &event); + void RefreshDropListTree(); + void OnTextChange(wxCommandEvent &event); + + protected: + + + private: + void AddDropListEntry(int index,DropListEntry &listEntry); + enum + { + DROPLIST_POPUP_CANCEL=1000, + DROPLIST_POPUP_DELETE, + DROPLIST_POPUP_ALLOW, + DROPLIST_POPUP_DROP, + DROPLIST_POPUP_DONT_DROP, + DROPLIST_POPUP_CHEAT, + DROPLIST_POPUP_DONTUSECOLOURCODES, + DROPLIST_POPUP_USECOLOURCODES, + DROPLIST_POPUP_USEEXACTMATCH, + DROPLIST_POPUP_USEPREFIXMATCH, + DROPLIST_POPUP_USEREGEXPMATCH, + PLAYER_POPUP_ADD_ALLOW, + PLAYER_POPUP_ADD_DROP, + PLAYER_POPUP_ADD_CHEAT + }; + + PlayerCachePanel *playerCache; + wxListCtrl *dropListList; + GroupedConfigItemsPanel *configItems; + wxString filterString; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/DropListEntry.cpp b/DropListEntry.cpp new file mode 100644 index 0000000..fbb940f --- /dev/null +++ b/DropListEntry.cpp @@ -0,0 +1,208 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "DropListEntry.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +DropListEntry::DropListEntry() +{ + lastCompiledName=""; + regExp=NULL; +} + +DropListEntry::~DropListEntry() +{ + if (regExp!=NULL) + { + delete (regExp); + } +} + +bool DropListEntry::Matches(wxString &nameIn,bool *cheatIn) +{ + bool matched=false; + wxString nameToCheck; + + if (coloured) + { + nameToCheck=nameIn; + } + else + { + nameToCheck=DecolouriseName(nameIn); + } + + if (!prefix) + { + // Regular Expression Match + if (nameToCheck.Cmp(name)==0) + { + *cheatIn=cheat; + matched=true; + } + } + else + { + // We are doing a prefix match of some kind + if (regularExpression) + { + if (regExp==NULL) + { + regExp=new wxRegEx(); + } + + if (name.Cmp(lastCompiledName)!=0) + { + // Need to compile the regular expression + // only do this once if possible + regExp->Compile(name); + lastCompiledName=name; + } + + if (regExp->Matches(nameToCheck)) + { + *cheatIn=cheat; + matched=true; + } + } + else + { + // Just a standard prefix string + if (nameToCheck.StartsWith(name)) + { + *cheatIn=cheat; + matched=true; + } + } + } + + if (matched && dontDrop) + { + // This has been set to Not Drop a matched name + *cheatIn=false; + matched=false; + } + return (matched); +} + +bool DropListEntry::DropType() +{ + return (dontDrop || drop); +} +void DropListEntry::ReadFromFile(wxTextFile *fp,int index) +{ + wxString lineRead; + wxString tempString; + wxString token; + + + lineRead=fp->GetLine(index); + + dontDrop=false; + drop=false; + coloured=false; + prefix=false; + cheat=false; + regularExpression=false; + name=""; + + tempString=lineRead; + token=tempString.BeforeFirst(','); + tempString=tempString.AfterFirst(','); + if (token.CmpNoCase("D")==0) + { + drop=true; + cheat=false; + dontDrop=false; + } + if (token.CmpNoCase("C")==0) + { + drop=true; + cheat=true; + dontDrop=false; + } + if (token.CmpNoCase("X")==0) + { + drop=false; + cheat=false; + dontDrop=true; + } + + token=tempString.BeforeFirst(','); + tempString=tempString.AfterFirst(','); + if (token.CmpNoCase("Y")==0) + { + coloured=true; + } + + token=tempString.BeforeFirst(','); + tempString=tempString.AfterFirst(','); + if (token.CmpNoCase("P")==0) + { + prefix=true; + regularExpression=false; + } + if (token.CmpNoCase("R")==0) + { + prefix=true; + regularExpression=true; + } + if (token.CmpNoCase("E")==0) + { + prefix=false; + regularExpression=false; + } + name=tempString; +} + +void DropListEntry::WriteToFile(FILE *fp) +{ + char dropChar; + char colouredChar; + char matchChar; + + dropChar='A'; + colouredChar='N'; + matchChar='E'; + if (drop) + { + if (cheat) + { + dropChar='C'; + } + else + { + dropChar='D'; + } + } + if (dontDrop) + { + dropChar='X'; + } + if (coloured) + { + colouredChar='Y'; + } + if (prefix) + { + matchChar='P'; + if (regularExpression) + { + matchChar='R'; + } + } + fprintf(fp,"%c,%c,%c,%s\n", + dropChar, + colouredChar, + matchChar, + name.GetData()); +} +int DropListEntry::Compare(DropListEntry *item1,DropListEntry *item2) +{ + return (item1->name.Cmp(item2->name)); +} + diff --git a/DropListEntry.h b/DropListEntry.h new file mode 100644 index 0000000..f25e544 --- /dev/null +++ b/DropListEntry.h @@ -0,0 +1,39 @@ +#ifndef __DROPLISTENTRY +#define __DROPLISTENTRY + +// wxWindows includes +#include +#include +#include +#include +#include + +// Statsgen Includes + +class DropListEntry; + +WX_DECLARE_OBJARRAY(DropListEntry,ArrayOfDropListEntry); +class DropListEntry +{ + public: + DropListEntry(); + ~DropListEntry(); + bool Matches(wxString &nameIn,bool *cheatIn); + void WriteToFile(FILE *fp); + void ReadFromFile(wxTextFile *fp,int index); + bool drop; + bool cheat; + bool coloured; + bool prefix; + bool regularExpression; + bool dontDrop; + wxString name; + wxString lastCompiledName; + wxRegEx *regExp; + static int Compare(DropListEntry *item1,DropListEntry *item2); + + bool DropType(); +}; + + +#endif diff --git a/DynamicArrays.cpp b/DynamicArrays.cpp new file mode 100644 index 0000000..7386bd8 --- /dev/null +++ b/DynamicArrays.cpp @@ -0,0 +1,66 @@ +// wxWindows includes +#include +#include + +// statsgen includes +#include "TemplateFile.h" +#include "GUITriggerItem.h" +#include "Player.h" +#include "KillData.h" +#include "AKAListEntry.h" +#include "ActionData.h" +#include "SpeechData.h" +#include "TeamWinData.h" +#include "TeamLossData.h" +#include "Round.h" +#include "ConfigItem.h" +#include "StreakData.h" +#include "GenericKey.h" +#include "TemplateOpenFile.h" +#include "TemplateVariableField.h" +#include "TemplateOpenQuery.h" +#include "Server.h" +#include "LogFile.h" +#include "PlayerCacheEntry.h" +#include "AliasListEntry.h" +#include "WeightListEntry.h" +#include "AwardDefinition.h" +#include "Clan.h" +#include "DropListEntry.h" +#include "KillTotal.h" +#include "PlayerDataEntry.h" +#include "KeyedIndex.h" +#include "XPPoints.h" + +WX_DEFINE_OBJARRAY(ArrayOfXPPoints); +WX_DEFINE_OBJARRAY(ArrayOfGUITriggerItem); +WX_DEFINE_OBJARRAY(ArrayOfWeightListEntry); +WX_DEFINE_OBJARRAY(ArrayOfPlayerDataEntry); +WX_DEFINE_OBJARRAY(ArrayOfPlayerCacheEntry); +WX_DEFINE_OBJARRAY(ArrayOfAliasListEntry); +WX_DEFINE_OBJARRAY(ArrayOfAKAListEntry); +WX_DEFINE_OBJARRAY(ArrayOfDropListEntry); +WX_DEFINE_OBJARRAY(ArrayOfPlayers); +WX_DEFINE_OBJARRAY(ArrayOfPlayersInRound); +WX_DEFINE_OBJARRAY(ArrayOfKillData); +WX_DEFINE_OBJARRAY(ArrayOfActionData); +WX_DEFINE_OBJARRAY(ArrayOfTeamWinData); +WX_DEFINE_OBJARRAY(ArrayOfTeamLossData); +WX_DEFINE_OBJARRAY(ArrayOfSpeechData); +WX_DEFINE_OBJARRAY(ArrayOfRoundLines); +WX_DEFINE_OBJARRAY(ArrayOfRounds); +WX_DEFINE_OBJARRAY(ArrayOfConfigItem); +WX_DEFINE_OBJARRAY(ArrayOfStreakData); +WX_DEFINE_OBJARRAY(ArrayOfGenericKey); +WX_DEFINE_OBJARRAY(ArrayOfTemplateOpenFile); +WX_DEFINE_OBJARRAY(ArrayOfTemplateVariableField); +WX_DEFINE_OBJARRAY(ArrayOfTemplateOpenQuery); +WX_DEFINE_OBJARRAY(ArrayOfServer); +WX_DEFINE_OBJARRAY(ArrayOfLogFile); +WX_DEFINE_OBJARRAY(ArrayOfAwardDefinition); +WX_DEFINE_OBJARRAY(ArrayOfClan); +WX_DEFINE_OBJARRAY(ArrayOfKillTotal); +WX_DEFINE_OBJARRAY(ArrayOfCompiledTemplateLine); +//WX_DEFINE_SORTED_ARRAY(KeyedIndex *,ArrayOfKeyedIndex); + +//WX_DEFINE_ARRAY(void *,ArrayOfPointers); diff --git a/DynamicArrays.h b/DynamicArrays.h new file mode 100644 index 0000000..cd67b33 --- /dev/null +++ b/DynamicArrays.h @@ -0,0 +1,8 @@ +#ifndef __DYNAMICARRAYS +#define __DYNAMICARRAYS + +#include + +WX_DEFINE_ARRAY(void *,ArrayOfPointers); + +#endif diff --git a/ETLogFileReader.cpp b/ETLogFileReader.cpp new file mode 100644 index 0000000..783ea53 --- /dev/null +++ b/ETLogFileReader.cpp @@ -0,0 +1,181 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "GlobalStatistics.h" +#include "ETLogFileReader.h" +#include "LogFileReader.h" +#include "ErrorData.h" +#include "Round.h" +#include "ConfigData.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "Server.h" +#include "Round.h" + + +ETLogFileReader::ETLogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn): MOHAALogFileReader(filenameIn,serverTypeIn) +{ + STATSGEN_DEBUG_FUNCTION_START("ETLogFileReader","Constructor"); + STATSGEN_DEBUG_FUNCTION_END +} + +bool ETLogFileReader::DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode) +{ + bool retVal=false; + + STATSGEN_DEBUG_FUNCTION_START("ETLogFileReader","DecodeTeamLoss"); + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool ETLogFileReader::DecodePlayerJoin(wxString &line,DecodedPlayerJoin &decode) +{ + bool retVal=false; + wxString playerInRoundID; + + STATSGEN_DEBUG_FUNCTION_START("ETLogFileReader","DecodePlayerJoin"); + retVal=DecodeClientUserinfoChanged(line, + playerInRoundID, + decode.playerName, + decode.playerTeam, + decode.playerClass); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,decode.playerName); + STATSGEN_DEBUG(DEBUG_RARELY,decode.playerTeam); + STATSGEN_DEBUG(DEBUG_RARELY,decode.playerClass); + UpdatePlayerRoundInfo(playerInRoundID, + playerIDListNames, + playerIDList, + decode.playerName); + UpdatePlayerRoundInfo(decode.playerName, + playerTeamListNames, + playerTeamList, + decode.playerTeam); + UpdatePlayerRoundInfo(decode.playerName, + playerClassListNames, + playerClassList, + decode.playerClass); + } + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool ETLogFileReader::DecodeTeamWin(wxString &line,DecodedTeamWin &decode) +{ + bool retVal=false; + + STATSGEN_DEBUG_FUNCTION_START("ETLogFileReader","DecodeTeamWin"); + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool ETLogFileReader::IsWorldPlayer(wxString &id,wxString &team,wxString &name) +{ + bool retVal=false; + + if ((name.Length()==0) || + (name.Cmp("")==0)) + { + retVal=true; + } + + return (retVal); +} + +bool ETLogFileReader::DecodeRoundStart(wxString &line, + DecodedRoundStart &decode, + Round *round) +{ + return (DecodeInitGame(line,decode,round)); +} + +bool ETLogFileReader::IsRoundStart(wxString &line) +{ + bool retVal; + + retVal=(line.StartsWith("InitGame:")); + + return (retVal); +} + +bool ETLogFileReader::IsRoundEnd(wxString &line) +{ + bool retVal=false; + + retVal=false; + if ((line.StartsWith("ShutdownGame:"))) + { + retVal=true; + } + return (retVal); +} + +bool ETLogFileReader::StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime) +{ + bool retVal=false; + wxString timeString; + wxString remainder; + wxString minuteString; + wxString secondString; + wxString hourString; + int hours=0; + int minutes=0; + int seconds=0; + time_t since1970; + + + timeString=lineRead.BeforeFirst(' '); + remainder=lineRead.AfterFirst(' '); + lineRead=remainder; + + timeString.Trim(true); + timeString.Trim(false); + + timeString.Replace(".",":"); + + + hourString=timeString.BeforeFirst(':'); + minuteString=timeString.AfterFirst(':'); + secondString=minuteString.AfterFirst(':'); + minuteString=minuteString.BeforeFirst(':'); + if (secondString.Length()>0) + { + // we are in format HH:MM:SS + } + else + { + // we are in format MM:SS + secondString=minuteString; + minuteString=hourString; + hourString="0"; + } + if (minuteString.IsNumber() && + secondString.IsNumber() && + hourString.IsNumber()) + { + retVal=true; + hours=atoi(hourString.GetData()); + minutes=atoi(minuteString.GetData()); + seconds=atoi(secondString.GetData()); + since1970=(3600*hours)+(60*minutes)+seconds; + lineTime.Set(since1970); + } + else + { + retVal=false; + } + return(retVal); + +} + +ETLogFileReader::~ETLogFileReader() +{ +} + diff --git a/ETLogFileReader.h b/ETLogFileReader.h new file mode 100644 index 0000000..7ccd7e5 --- /dev/null +++ b/ETLogFileReader.h @@ -0,0 +1,40 @@ +#ifndef __ETLOGFILEREADER +#define __ETLOGFILEREADER + +// wxWindows includes +#include +#include +#include +#include +#include + +// statsgen includes +#include "ErrorData.h" +#include "Round.h" +#include "MOHAALogFileReader.h" +#include "DynamicArrays.h" +#include "Round.h" + +class ETLogFileReader:public MOHAALogFileReader +{ + public: + virtual bool IsWorldPlayer(wxString &id,wxString &team,wxString &name); + ETLogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn); + virtual ~ETLogFileReader(); + virtual bool DecodeTeamLoss(wxString &line,DecodedTeamLoss &teamLoss); + virtual bool DecodeTeamWin(wxString &line,DecodedTeamWin &teamWin); + virtual bool DecodePlayerJoin(wxString &line,DecodedPlayerJoin &decode); + virtual bool DecodeRoundStart(wxString &line, + DecodedRoundStart &decode, + Round *round); + + protected: + + virtual bool StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime); + virtual bool IsRoundStart(wxString &line); + virtual bool IsRoundEnd(wxString &line); + + private: +}; + +#endif diff --git a/ErrorData.cpp b/ErrorData.cpp new file mode 100644 index 0000000..260de7a --- /dev/null +++ b/ErrorData.cpp @@ -0,0 +1,138 @@ +// wxWindows includes +#include +#include + +// statsgen includes +#include "ErrorData.h" +#include "GlobalStatistics.h" + +StatsgenDebugObject statsgenDebug; + +StatsgenDebugObject::StatsgenDebugObject() +{ + initiateDebugFile=true; + currentDebugLevel=0; + +} + +void StatsgenDebugObject::UpdateDebugConfig() +{ + wxString configKey; + int debugIndex; + wxString configValue; + + configKey="/Debug/DebugFile"; + globalStatistics.configData.ReadTextValue(configKey,&debugFilename,""); + + debugMaxLevel.Clear(); + for (debugIndex=WINDOW_ID_PROGRESS_PANEL_GENERAL; + debugIndex=debugLevel) + { + FILE *fp; + if (initiateDebugFile) + { + fp=fopen(debugFilename.GetData(),"w"); + initiateDebugFile=false; + } + else + { + fp=fopen(debugFilename.GetData(),"a"); + } + if (fp!=NULL) + { + fprintf(fp,"%s::%s():%s\n", + classname,functionname,message); + fclose(fp); + } + } + } +} + +void StatsgenDebugObject::Debug(const char *classname,const char *functionname, + int debugLevel,wxString &message) +{ + Debug(classname,functionname,debugLevel,message.GetData()); +} + +void StatsgenDebugObject::Entering(const char *classname,const char *functionname) +{ + Debug(classname,functionname,DEBUG_SOMETIMES,"Entering"); +} + +void StatsgenDebugObject::Leaving(const char *classname,const char *functionname) +{ + Debug(classname,functionname,DEBUG_SOMETIMES,"Leaving"); +} + +void StatsgenDebugObject::UpdateCurrentDebugLevel(int progressPanelID) +{ + if (progressPanelID=WINDOW_ID_PROGRESS_PANEL_MAX) + { + progressPanelID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + } + + currentDebugLevel=debugMaxLevel.Item(progressPanelID-WINDOW_ID_PROGRESS_PANEL_GENERAL); +} + +ErrorData::ErrorData() +{ + ClearError(); +} + +void ErrorData::ClearError() +{ + errorCode=ERROR_CODE_OK; +} + +ErrorCodes ErrorData::CurrentError() +{ + return (errorCode); +} + +bool ErrorData::IsOK() +{ + return (errorCode==ERROR_CODE_OK); +} + +void ErrorData::SetError(ErrorCodes error,char *description) +{ + errorCode=error; + errorDescription=description; +} + +void ErrorData::SetError(ErrorCodes error,wxString &description) +{ + errorCode=error; + errorDescription=description; +} + + diff --git a/ErrorData.h b/ErrorData.h new file mode 100644 index 0000000..e4b8998 --- /dev/null +++ b/ErrorData.h @@ -0,0 +1,97 @@ +#ifndef __ERRORDATA +#define __ERRORDATA + +// wxWindows includes +#include +#include + +// statsgen includes +#include "WindowIDs.h" +//#define DEBUG 1 +#ifdef DEBUG +#define STATSGEN_DEBUG_FUNCTION_START(CLASSNAME,FUNCTIONNAME) \ +char *StatsgenDebugClassName=CLASSNAME; \ +char *StatsgenDebugFunctionName=FUNCTIONNAME; \ +statsgenDebug.Entering(StatsgenDebugClassName,StatsgenDebugFunctionName); + +#define STATSGEN_DEBUG_FUNCTION_END \ +statsgenDebug.Leaving(StatsgenDebugClassName,StatsgenDebugFunctionName); + +#define STATSGEN_DEBUG(LEVEL,MESSAGE) \ +statsgenDebug.Debug(StatsgenDebugClassName,StatsgenDebugFunctionName,LEVEL,MESSAGE); + +#define STATSGEN_DEBUG_INITIATE \ +statsgenDebug.UpdateDebugConfig(); + +#define STATSGEN_DEBUG_UPDATE_DEBUG_LEVEL(PROGRESS_PANEL) \ +statsgenDebug.UpdateCurrentDebugLevel(PROGRESS_PANEL); + +#define STATSGEN_DEBUG_CODE(CODE) \ +if (statsgenDebug.DebugOn()) \ +{ \ + CODE \ +} +#else +#define STATSGEN_DEBUG_FUNCTION_START(CLASSNAME,FUNCTIONNAME) +#define STATSGEN_DEBUG_FUNCTION_END +#define STATSGEN_DEBUG(LEVEL,MESSAGE) +#define STATSGEN_DEBUG_INITIATE +#define STATSGEN_DEBUG_UPDATE_DEBUG_LEVEL(PROGRESS_PANEL) +#define STATSGEN_DEBUG_CODE(CODE) +#endif +#define DEBUG_OFF 0 +#define DEBUG_ALWAYS 1 +#define DEBUG_SOMETIMES 2 +#define DEBUG_RARELY 3 + +class StatsgenDebugObject +{ + public: + wxString debugFilename; + wxArrayInt debugMaxLevel; + + StatsgenDebugObject(); + void UpdateDebugConfig(); + void Debug(const char *classname, + const char *functionname, + int DebugLevel, + wxString &message); + void Debug(const char *classname, + const char *functionname, + int DebugLevel, + const char *message); + void Entering(const char *classname, + const char *functionname); + void Leaving(const char *classname, + const char *functionname); + void UpdateCurrentDebugLevel(int progressPanelID); + bool DebugOn(); + bool initiateDebugFile; + int currentDebugLevel; +}; + +extern StatsgenDebugObject statsgenDebug; + +enum ErrorCodes +{ + ERROR_CODE_OK=0, + ERROR_CODE_FILE_OPEN +}; + +class ErrorData +{ + public: + ErrorData(); + void ClearError(); + ErrorCodes CurrentError(); + bool IsOK(); + void SetError(ErrorCodes error,char *description); + void SetError(ErrorCodes error,wxString &description); + + + private: + ErrorCodes errorCode; + wxString errorDescription; +}; + +#endif diff --git a/ErrorPanel.cpp b/ErrorPanel.cpp new file mode 100644 index 0000000..7c84bbc --- /dev/null +++ b/ErrorPanel.cpp @@ -0,0 +1,117 @@ +// wx includes +#include +#include +#include + +// Statsgen Includes +#include "ErrorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" +#include "ProgressPanel.h" + +BEGIN_EVENT_TABLE(ErrorPanel, wxPanel) + EVT_SIZE(ErrorPanel::OnResize) +END_EVENT_TABLE() + +ErrorPanel::ErrorPanel(wxArrayString &errorsIn,wxArrayInt &severitiesIn) +{ + errorDisplay=NULL; + errors=errorsIn; + severities=severitiesIn; +} + +void ErrorPanel::Update() +{ + wxListItem listColumn; + int errorIndex; + int errorCount; + int listIndex; + wxString error; + int severity; + wxBitmap bitmap; + + imageList.Create(16,16); + for (severity=SeverityNotRun;severitySetImageList(&imageList,wxIMAGE_LIST_NORMAL); + errorDisplay->SetImageList(&imageList,wxIMAGE_LIST_SMALL); + + errorDisplay->Hide(); + errorDisplay->DeleteAllColumns(); + errorDisplay->DeleteAllItems(); + listColumn.SetText("Severity"); + errorDisplay->InsertColumn(0,listColumn); + listColumn.SetText("Text"); + errorDisplay->InsertColumn(2,listColumn); + errorCount=errors.GetCount(); + for (errorIndex=0;errorIndexInsertItem(errorIndex,severityString); + errorDisplay->SetItemData(listIndex,errorIndex); + errorDisplay->SetItem(errorIndex,1,error); + errorDisplay->SetItem(errorIndex,0,severityString,severity); + } + errorDisplay->SetColumnWidth(0,wxLIST_AUTOSIZE); + errorDisplay->SetColumnWidth(1,wxLIST_AUTOSIZE); + + errorDisplay->Show(); +} + +void ErrorPanel::CreateScreen() +{ + wxString defaultValue=""; + wxSizeEvent event; + + if (errorDisplay==NULL) + { + globalStatistics.ReadPlayerCache(); + errorDisplay=new wxListCtrl(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT); + Update(); + + } + else + { + // Screen is already created + } +} + +void ErrorPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int panelWidth; + int panelHeight; + int listHeight; + int listWidth; + wxString msg; + + // Make sure the screen has been created + CreateScreen(); + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + listWidth=panelWidth-10; + listHeight=panelHeight; + if (listHeight<0) + { + listHeight=0; + } + + errorDisplay->SetSize(0,0,listWidth,listHeight); + +} + diff --git a/ErrorPanel.h b/ErrorPanel.h new file mode 100644 index 0000000..110c7f4 --- /dev/null +++ b/ErrorPanel.h @@ -0,0 +1,30 @@ +#ifndef __ERRORPANEL +#define __ERRORPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" + +class ErrorPanel : public wxPanel +{ + public: + ErrorPanel(wxArrayString &errorsIn, + wxArrayInt &severitiesIn); + void CreateScreen(); + void OnResize(wxSizeEvent &event); + + protected: + wxListCtrl *errorDisplay; + + private: + void Update(); + wxArrayString errors; + wxArrayInt severities; + wxImageList imageList; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ExternalDatabase.cpp b/ExternalDatabase.cpp new file mode 100644 index 0000000..12a5b95 --- /dev/null +++ b/ExternalDatabase.cpp @@ -0,0 +1,509 @@ +#include +#include +#include +#include +#include + +#include "ExternalDatabase.h" +#include "GlobalStatistics.h" +#include "TemplateOpenQuery.h" +#include "Progress.h" + +ExternalDatabase::ExternalDatabase() +{ + mySQLHandle=NULL; +} + +ExternalDatabase::~ExternalDatabase() +{ + if (mySQLHandle!=NULL) + { + mysql_close(mySQLHandle); + mySQLHandle=NULL; + } +} + +void ExternalDatabase::UpdateFromConfig() +{ + wxString configKey; + wxString configValue; + + configKey="/ExternalDatabase/Enabled"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"N"); + enabled=(configValue.CmpNoCase("Y")==0); + + configKey="/ExternalDatabase/CreateIndexes"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"N"); + createIndexes=(configValue.CmpNoCase("Y")==0); + + configKey="/ExternalDatabase/Hostname"; + globalStatistics.configData.ReadTextValue(configKey,&hostname,""); + + configKey="/ExternalDatabase/Username"; + globalStatistics.configData.ReadTextValue(configKey,&username,""); + + configKey="/ExternalDatabase/Password"; + globalStatistics.configData.ReadTextValue(configKey,&password,""); + + configKey="/ExternalDatabase/DatabaseName"; + globalStatistics.configData.ReadTextValue(configKey,&databasename,"statsgen"); + + configKey="/ExternalDatabase/Port"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"3306"); + port=atoi(configValue.GetData()); +} + +void ExternalDatabase::SplitFieldNames(wxString &createSQL,wxArrayString &fieldNames) +{ + wxString basicFieldList; + int fieldCount; + int fieldIndex; + wxString field; + + fieldNames.Clear(); + basicFieldList=createSQL.AfterFirst('('); + basicFieldList=basicFieldList.BeforeLast(')'); + field=GetLineToken(basicFieldList,",",1,&fieldCount); + for (fieldIndex=1;fieldIndex<=fieldCount;fieldIndex++) + { + field=GetLineToken(basicFieldList,",",fieldIndex,&fieldCount); + field=field.BeforeFirst(' '); + fieldNames.Add(field); + } +} + +long ExternalDatabase::RowCount(wxString &tableName) +{ + wxString SQL; + TemplateOpenQuery query; + long rowCount=0; + wxString fieldName="rowcount"; + wxString fieldValue; + + SQL.Printf("select count(*) as rowcount from %s",tableName.GetData()); + query.Initiate(SQL,globalStatistics.statsgenDatabase.DBHandle()); + if (query.NextRow()) + { + fieldValue=query.RetrieveProperty(fieldName); + rowCount=atoi(fieldValue.GetData()); + } + + return (rowCount); +} + +void ExternalDatabase::TransferFromInternal() +{ + wxArrayString tableNames; + wxArrayString tableSQL; + wxString tableName; + wxString indexName; + wxString viewName; + wxArrayString indexNames; + wxArrayString indexSQL; + wxArrayString viewNames; + wxArrayString viewSQL; + wxString createSQL; + wxArrayString fieldNames; + int tableCount; + int tableIndex; + int indexCount; + int indexIndex; + int viewCount; + int viewIndex; + wxString msg; + wxString SQL; + long rowCount; + long currentRowCount; + wxString beginSQL="begin"; + wxString commitSQL="commit"; + bool connectOK; + STATSGEN_DEBUG_FUNCTION_START("ExternalDatabase","TransferFromInternal") + + UpdateFromConfig(); + if (enabled) + { + connectOK=Connect(); + if (connectOK) + { + globalStatistics.statsgenDatabase.GetDatabaseComponent("table",tableNames,tableSQL); + globalStatistics.statsgenDatabase.GetDatabaseComponent("index",indexNames,indexSQL); + globalStatistics.statsgenDatabase.GetDatabaseComponent("view",viewNames,viewSQL); + + tableCount=tableNames.GetCount(); + indexCount=indexNames.GetCount(); + viewCount=viewNames.GetCount(); + currentRowCount=0; + rowCount=0; + for (tableIndex=0;tableIndexInitiate(rowCount," rows",1," rows",1); + progress->Update(currentRowCount); + ExecuteSQL(beginSQL); + for (tableIndex=0;tableIndexUpdate(currentRowCount); + tableName=tableNames.Item(tableIndex); + msg.Printf("Create Table:%s",tableName.GetData()); + progress->SetStatus(msg); + createSQL=tableSQL.Item(tableIndex); + createSQL.Replace(" string"," varchar(255)",true); + createSQL.Replace("(255)(","(",true); + createSQL.Replace("(255) ("," (",true); + createSQL.Replace("key "," ky ",true); + STATSGEN_DEBUG(DEBUG_ALWAYS,createSQL); + ExecuteSQL(createSQL); + } + ExecuteSQL(commitSQL); + + /* + if (createIndexes) + { + ExecuteSQL(beginSQL); + for (indexIndex=0;indexIndexSetStatus(msg); + createSQL.Printf("drop index %s on %s", + indexName.GetData(), + tableName.GetData()); + ExecuteSQL(createSQL); + } + ExecuteSQL(commitSQL); + } + */ + for (tableIndex=0;tableIndexUpdate(currentRowCount); + tableName=tableNames.Item(tableIndex); + msg.Printf("Empty Table:%s",tableName.GetData()); + progress->SetStatus(msg); + SQL.Printf("delete from %s",tableName.GetData()); + ExecuteSQL(SQL); + ExecuteSQL(commitSQL); + } + for (tableIndex=0;tableIndexSetStatus(msg); + SplitFieldNames(createSQL,fieldNames); + TransferTableData(tableName,fieldNames,¤tRowCount); + } + if (createIndexes) + { + for (indexIndex=0;indexIndexUpdate(currentRowCount); + indexName=indexNames.Item(indexIndex); + msg.Printf("Create index:%s",indexName.GetData()); + progress->SetStatus(msg); + createSQL=indexSQL.Item(indexIndex); + ExecuteSQL(createSQL); + ExecuteSQL(commitSQL); + } + } + ExecuteSQL(beginSQL); + for (viewIndex=0;viewIndexUpdate(currentRowCount); + viewName=viewNames.Item(viewIndex); + msg.Printf("Create view:%s",viewName.GetData()); + progress->SetStatus(msg); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + createSQL=viewSQL.Item(viewIndex); + char *buffer; + unsigned long length; + wxString escapedSQL; + //insertSQL+="'"; + length=(createSQL.Length()*2)+1; + buffer=(char *)malloc(length); + if (buffer!=NULL) + { + mysql_real_escape_string(mySQLHandle, + buffer, + createSQL.GetData(), + createSQL.Length()); + escapedSQL=buffer; + free(buffer); + } + STATSGEN_DEBUG(DEBUG_ALWAYS,createSQL) + //ExecuteSQL(escapedSQL); + ExecuteSQL(createSQL); + } + ExecuteSQL(commitSQL); + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void ExternalDatabase::TransferTableData(wxString &tableName, + wxArrayString &fieldNames, + long *currentRowCount) +{ + wxString retrieveSQL; + wxString insertSQLPrefix; + wxString insertSQL; + int fieldCount; + int fieldIndex; + wxString fieldName; + wxString fieldValue; + TemplateOpenQuery query; + wxString msg; + wxString beginSQL="begin"; + wxString commitSQL="commit"; + wxString filename="mysql.upload"; + FILE *fp; + int rowCount; + wxString lineTerminator; + + lineTerminator="\r\n"; + + STATSGEN_DEBUG_FUNCTION_START("ExternalDatabase","TransferTableData") + + progress->SetStatus(tableName); + filename.Printf("mysqlupload.%s",tableName.GetData()); + fieldCount=fieldNames.GetCount(); + retrieveSQL.Printf("select * from %s",tableName.GetData()); + insertSQLPrefix.Printf("insert into %s (",tableName.GetData()); + + for (fieldIndex=0;fieldIndexUpdate(*currentRowCount); + */ + //STATSGEN_DEBUG(DEBUG_RARELY,insertSQL) + } + if (fp!=NULL) + { + fclose(fp); + } +/* + insertSQL.Printf( + "LOAD DATA LOCAL INFILE '%s' " + "INTO TABLE %s " + "FIELDS " + "TERMINATED BY '\\%c' " + "ENCLOSED BY '\\%c' " + "ESCAPED BY '\\%c'", + filename.GetData(), + tableName.GetData(), + ',', // Fields terminated by + '\'', // Enclosed by + '\\'); // Escaped by +*/ + insertSQL.Printf( + "LOAD DATA LOCAL INFILE '%s' " + "INTO TABLE %s " + "FIELDS " + "TERMINATED BY '\\%c' " + "ESCAPED BY '\\%c'" + "LINES " + "TERMINATED BY '\\%s' " + , + filename.GetData(), + tableName.GetData(), + '\t', // Fields terminated by + '\\', // Fields escaped by + lineTerminator.GetData() // Line terminated by + ); // Escaped by + ExecuteSQL(insertSQL); + (*currentRowCount)+=(rowCount); + progress->Update(*currentRowCount); + ExecuteSQL(commitSQL); + STATSGEN_DEBUG_FUNCTION_END +} + +wxString ExternalDatabase::EscapedString(wxString &escaped) +{ + wxString retVal; + int length; + char *buffer; + + STATSGEN_DEBUG_FUNCTION_START("ExternalDatabase","EscapedString") + STATSGEN_DEBUG(DEBUG_RARELY,escaped) + retVal=escaped; + length=(escaped.Length()*2)+1; + buffer=(char *)malloc(length); + if (buffer!=NULL) + { + mysql_real_escape_string(mySQLHandle, + buffer, + retVal.GetData(), + retVal.Length()); + retVal=buffer; + free(buffer); + } +// STATSGEN_DEBUG(DEBUG_RARELY,retVal) +// retVal.Replace("-","\\-"); + + STATSGEN_DEBUG(DEBUG_RARELY,retVal) + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool ExternalDatabase::CreateDatabaseInstance() +{ + bool retVal=true; + wxString SQL; + SQL.Printf("create database %s",databasename.GetData()); + retVal=ExecuteSQL(SQL); + return (retVal); +} + +bool ExternalDatabase::Connect() +{ + bool retVal=true; + wxString msg; + + if (mySQLHandle==NULL) + { + mySQLHandle=mysql_init(NULL); + } + if (mySQLHandle!=NULL) + { + + if (mysql_real_connect(mySQLHandle, + hostname.GetData(), + username.GetData(), + password.GetData(), + //databasename.GetData(), + NULL, + port, + NULL, + CLIENT_COMPRESS)==NULL) + { + // Failed to connect + retVal=false; + msg.Printf("Connect Error: %s",mysql_error(mySQLHandle)); + progress->LogError(msg,SeverityError); + } + else + { + retVal=CreateDatabaseInstance(); + + if (mysql_real_connect(mySQLHandle, + hostname.GetData(), + username.GetData(), + password.GetData(), + databasename.GetData(), + port, + NULL, + CLIENT_COMPRESS)==NULL) + { + // Failed to connect + retVal=false; + msg.Printf("Connect Error: %s",mysql_error(mySQLHandle)); + progress->LogError(msg,SeverityError); + } + } + } + else + { + msg.Printf("Error: %s",mysql_error(mySQLHandle)); + progress->LogError(msg,SeverityError); + } + + return (retVal); +} + +bool ExternalDatabase::ExecuteSQL(wxString &SQL) +{ + bool retVal=true; + int status; + wxString msg; + + if (mySQLHandle!=NULL) + { + status=mysql_real_query(mySQLHandle, + SQL.GetData(), + SQL.Length()); + status=mysql_errno(mySQLHandle); + switch (status) + { + case 0: + case ER_TABLE_EXISTS_ERROR: + case ER_DUP_KEYNAME: + case ER_DB_CREATE_EXISTS: + break; + default: + msg.Printf("SQL Error: %d %s",status,mysql_error(mySQLHandle)); + progress->LogError(msg,SeverityError); + msg.Printf("SQL Attempted: %s",SQL.GetData()); + progress->LogError(msg,SeverityError); + retVal=false; + break; + } + } + + return (retVal); +} + diff --git a/ExternalDatabase.h b/ExternalDatabase.h new file mode 100644 index 0000000..691a834 --- /dev/null +++ b/ExternalDatabase.h @@ -0,0 +1,37 @@ +#ifndef __EXTERNALDATABASE +#define __EXTERNALDATABASE + +// wxWindows includes +#include +#include + +#include + +class ExternalDatabase +{ + public: + ExternalDatabase(); + virtual ~ExternalDatabase(); + void UpdateFromConfig(); + void TransferFromInternal(); + wxString EscapedString(wxString &escaped); + void SplitFieldNames(wxString &createSQL,wxArrayString &fieldNames); + void TransferTableData(wxString &tableName, + wxArrayString &fieldNames, + long *currentRowCount); + wxString hostname; + int port; + wxString username; + wxString password; + wxString databasename; + bool enabled; + bool createIndexes; + private: + bool Connect(); + bool CreateDatabaseInstance(); + bool ExecuteSQL(wxString &SQL); + long RowCount(wxString &tableName); + MYSQL *mySQLHandle; +}; + +#endif diff --git a/FTPBrowserPanel.cpp b/FTPBrowserPanel.cpp new file mode 100644 index 0000000..ac85bd5 --- /dev/null +++ b/FTPBrowserPanel.cpp @@ -0,0 +1,454 @@ +// wx includes +#include + +// Statsgen Includes +#include "FTPBrowserPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "ProgressPanel.h" +#include "RemoteMachine.h" + +BEGIN_EVENT_TABLE(FTPBrowserPanel, wxPanel) + EVT_SIZE(FTPBrowserPanel::OnResize) + EVT_MENU(WORKER_EVENT,FTPBrowserPanel::OnRemoteRequest) + EVT_LIST_ITEM_SELECTED(WINDOW_ID_LISTBOX_CONFIGITEMS,FTPBrowserPanel::OnListSingleClick) + EVT_LIST_ITEM_ACTIVATED(WINDOW_ID_LISTBOX_CONFIGITEMS,FTPBrowserPanel::OnListDoubleClick) +END_EVENT_TABLE() + +FTPBrowserPanel::~FTPBrowserPanel() +{ + if (remoteMachine!=NULL) + { + delete (remoteMachine); + } + progress->SetDynamicPanel(NULL); + /* + if (thread!=NULL) + { + thread->Delete(); + delete (thread); + } + */ +} + +FTPBrowserPanel::FTPBrowserPanel( + wxString &configGroupIn, + wxString &defaultPathIn, + bool browsingForFile) +{ + workingForThread=false; + directoryListing=NULL; + configGroup=configGroupIn; + currentPath=defaultPathIn; + remoteMachine=new RemoteMachine(configGroup); + thread=NULL; +} + +void FTPBrowserPanel::OnListDoubleClick(wxListEvent &event) +{ + wxString msg; + wxString fileName; + long fileSize; + int listIndex; + + STATSGEN_DEBUG_FUNCTION_START("FTPBrowserPanel","OnListDoubleClick") + listIndex=event.GetIndex(); + STATSGEN_DEBUG_CODE(msg.Printf("item double clicked %ld",event.GetIndex());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (listIndexGetRemoteDirectoryListing(currentPath, + wildcard, + fileNames); + filename=".."; + fileNames.Insert(filename,0); + + StopThreadWork(); + } + else + { + // been asked to get the file size of this index item + Update(fileIndex); + StopThreadWork(); + } +} + +void FTPBrowserPanel::Update(int directoryIndex) +{ + int listIndex; + int directoryCount; + long fileSize; + wxString fileName; + wxString status; + + + STATSGEN_DEBUG_FUNCTION_START("FTPBrowserPanel","Update") + directoryCount=fileNames.GetCount(); + if (directoryIndexSetStatus(status); + fileSize=remoteMachine->GetRemoteFileSize(currentPath,fileName); + status="Done";progress->SetStatus(status); + fileSizes.RemoveAt(directoryIndex); + fileSizes.Insert(fileSize,directoryIndex); + if (fileSize<0) + { + fileSizeString=""; + imageIndex=0; + } + else + { + fileSizeString.Printf("%ld bytes",fileSize); + if (fileSize> (2 * 1024)) + { + fileSizeString.Printf("%.1f kb",((float)fileSize/1024.0)); + } + if (fileSize> (2 * 1024 * 1024)) + { + fileSizeString.Printf("%.1f mb",((float)fileSize/(1024.0 * 1024.0))); + } + imageIndex=2; + } + directoryListing->SetItem(directoryIndex,0,fileName,imageIndex); + directoryListing->SetItem(directoryIndex,1,fileSizeString); + + directoryListing->SetColumnWidth(0,wxLIST_AUTOSIZE); + directoryListing->SetColumnWidth(1,wxLIST_AUTOSIZE); + } + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void FTPBrowserPanel::GetDirectoryListing() +{ + int directoryCount; + int directoryIndex; + long fileSize; + wxString fileName; + wxString wildCard; + int imageIndex; + int listIndex; + wxString status; + + STATSGEN_DEBUG_FUNCTION_START("FTPBrowserPanel","GetDirectoryListing") + status="Getting Directory Listing"; progress->SetStatus(status); + CreateList(); + + fileNames.Clear(); + fileSizes.Clear(); + + wxString wildcard=""; + + remoteMachine->GetRemoteDirectoryListing(currentPath, + wildcard, + fileNames); + status="Done"; progress->SetStatus(status); + fileName=".."; + fileNames.Insert(fileName,0); + + directoryCount=fileNames.GetCount(); + for (directoryIndex=0;directoryIndex0) + { + fileSize=-2; + imageIndex=3; + } + else + { + fileSize=-1; + imageIndex=1; + } + fileSizes.Add(fileSize); + fileName=fileNames.Item(directoryIndex); + + listIndex=directoryListing->InsertItem(directoryIndex,_T("")); + directoryListing->SetItemData(listIndex,directoryIndex); + directoryListing->SetItem(directoryIndex,0,fileName,imageIndex); + directoryListing->SetItem(directoryIndex,1,_T("")); + } + + directoryListing->SetColumnWidth(0,wxLIST_AUTOSIZE); + directoryListing->SetColumnWidth(1,wxLIST_AUTOSIZE); + /* + if (thread!=NULL) + { + thread->Delete(); + } + else + { + thread=new RemoteFTPBrowserThread(this); + } + + thread->Create(); + thread->Run(); + */ + STATSGEN_DEBUG_FUNCTION_END +} + +void FTPBrowserPanel::CreateScreen() +{ + wxString defaultValue=""; + wxSizeEvent event; + + if (directoryListing==NULL) + { + globalStatistics.ReadPlayerCache(); + directoryListing=new wxListCtrl(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT); + currentSelection=new wxTextCtrl(this, + -1, + currentPath, + wxDefaultPosition, + wxDefaultSize, + wxTE_READONLY); + + progressPanel=new ProgressPanel(); + progressPanel->DynamicSizing(); + progressPanel->DisableTimeToGo(); + progressPanel->DisableCounter(); + + progressPanel->Create(this, + WINDOW_ID_PROGRESS_PANEL_DYNAMIC, + wxDefaultPosition, + wxDefaultSize, + wxRAISED_BORDER); + progress->SetDynamicPanel(progressPanel); + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DYNAMIC); + progress->UpdateLabel(""); + + GetDirectoryListing(); + + } + else + { + // Screen is already created + } +} + +void FTPBrowserPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int panelWidth; + int panelHeight; + int selectionWidth; + int selectionHeight; + int progressWidth; + int progressHeight; + int listHeight; + int listWidth; + wxString msg; + + // Make sure the screen has been created + CreateScreen(); + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + itemSize=currentSelection->GetSize(); + selectionWidth=itemSize.GetWidth(); + selectionHeight=itemSize.GetHeight(); + itemSize=progressPanel->GetSize(); + progressWidth=itemSize.GetWidth(); + progressHeight=itemSize.GetHeight(); + + progressWidth=panelWidth-10; + + listWidth=panelWidth-10; + listHeight=panelHeight; + listHeight-=selectionHeight; + listHeight-=progressHeight; + if (listHeight<0) + { + listHeight=0; + } + + selectionWidth=panelWidth; + + directoryListing->SetSize(0,0,listWidth,listHeight); + currentSelection->SetSize(0,listHeight,selectionWidth,selectionHeight); + progressPanel->SetSize(0,listHeight+selectionHeight, + progressWidth,progressHeight); + +} + +void FTPBrowserPanel::CreateList() +{ + wxListItem listColumn; + wxBitmap bitmap; + wxSize buttonSize(16,16); + + imageList.Create(16,16); + bitmap=wxArtProvider::GetIcon(wxART_FOLDER,wxART_OTHER,buttonSize); + imageList.Add(bitmap); + bitmap=wxArtProvider::GetIcon(wxART_GO_DIR_UP,wxART_OTHER,buttonSize); + imageList.Add(bitmap); + bitmap=wxArtProvider::GetIcon(wxART_NORMAL_FILE,wxART_OTHER,buttonSize); + imageList.Add(bitmap); + bitmap=wxArtProvider::GetIcon(wxART_QUESTION,wxART_OTHER,buttonSize); + imageList.Add(bitmap); + + directoryListing->SetImageList(&imageList,wxIMAGE_LIST_NORMAL); + directoryListing->SetImageList(&imageList,wxIMAGE_LIST_SMALL); + + directoryListing->DeleteAllColumns(); + directoryListing->DeleteAllItems(); + listColumn.SetText("Filename"); + directoryListing->InsertColumn(0,listColumn); + listColumn.SetText("Size"); + directoryListing->InsertColumn(1,listColumn); + +} + +RemoteFTPBrowserThread::RemoteFTPBrowserThread( + FTPBrowserPanel *panelIn) : wxThread(wxTHREAD_JOINABLE) +{ + browserPanel=panelIn; +} + +void RemoteFTPBrowserThread::OnExit() +{ + // Called when the thread has exited +} + +void *RemoteFTPBrowserThread::Entry() +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT); + + // This is the main entry point of the directory getter thread + browserPanel->StartThreadWork(); + event.SetInt(-1); + wxPostEvent(browserPanel,event); + while (browserPanel->DoingThreadWork()) + { + wxYield(); + } + if (TestDestroy()) + { + return (NULL); + } + // Right - should have got the directory listing + int directoryCount; + int directoryIndex; + + directoryCount=browserPanel->fileNames.GetCount(); + for (directoryIndex=0;directoryIndexStartThreadWork(); + event.SetInt(directoryIndex); + wxPostEvent(browserPanel,event); + while (browserPanel->DoingThreadWork()) + { + wxYield(); + } + if (TestDestroy()) + { + return (NULL); + } + } + return (NULL); +} + +void FTPBrowserPanel::OnListSingleClick(wxListEvent &event) +{ + wxString msg; + wxString fileName; + long fileSize; + int listIndex; + wxString selection; + + STATSGEN_DEBUG_FUNCTION_START("FTPBrowserPanel","OnListSingleClick") + listIndex=event.GetIndex(); + STATSGEN_DEBUG_CODE(msg.Printf("item selected %ld",event.GetIndex());) + if (listIndexSetValue(selection); + Update(listIndex); + fileSize=fileSizes.Item(listIndex); + selectedSize=fileSize; + } + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + STATSGEN_DEBUG_FUNCTION_END +} + +wxString FTPBrowserPanel::GetCurrentSelection() +{ + return (currentSelection->GetValue()); +} + +void FTPBrowserPanel::ChangeDirectory(wxString &filename) +{ + wxString newDirectory=currentPath+"/"+filename; + + if (remoteMachine->ChangeDirectory(newDirectory)) + { + currentPath=newDirectory; + currentSelection->SetValue(currentPath); + selectedSize=-1; + GetDirectoryListing(); + } +} + +wxString FTPBrowserPanel::CurrentPath() +{ + return (currentPath); +} diff --git a/FTPBrowserPanel.h b/FTPBrowserPanel.h new file mode 100644 index 0000000..7fd408e --- /dev/null +++ b/FTPBrowserPanel.h @@ -0,0 +1,76 @@ +#ifndef __FTPBROWSERPANEL +#define __FTPBROWSERPANEL + +#include +#include +#include +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "RemoteMachine.h" +#include "ProgressPanel.h" + +#define WORKER_EVENT 1000 + +#define REMOTE_REQUEST_DIR_LIST + +class RemoteFTPBrowserThread; +class FTPBrowserPanel : public wxPanel +{ + public: + virtual ~FTPBrowserPanel(); + FTPBrowserPanel( + wxString &configGroupIn, + wxString &defaultPath, + bool browsingForFile); + void CreateScreen(); + void Update(int fileIndex); + void CreateList(); + void OnResize(wxSizeEvent &event); + void OnRemoteRequest(wxCommandEvent &event); + + RemoteMachine *remoteMachine; + wxArrayString fileNames; + void StartThreadWork(); + void StopThreadWork(); + bool DoingThreadWork(); + void GetDirectoryListing(); + void ChangeDirectory(wxString &filename); + void OnListDoubleClick(wxListEvent &event); + void OnListSingleClick(wxListEvent &event); + wxString GetCurrentSelection(); + long selectedSize; + wxString CurrentPath(); + + protected: + wxListCtrl *directoryListing; + + + private: + wxImageList imageList; + wxString configGroup; + wxArrayLong fileSizes; + wxString currentPath; + bool workingForThread; + RemoteFTPBrowserThread *thread; + wxTextCtrl *currentSelection; + ProgressPanel *progressPanel; + + DECLARE_EVENT_TABLE() +}; + +class RemoteFTPBrowserThread : public wxThread +{ + public: + RemoteFTPBrowserThread(FTPBrowserPanel *browserPanelIn); + virtual void *Entry(); + virtual void OnExit(); + + FTPBrowserPanel *browserPanel; + +}; + +#endif diff --git a/FTPConnectionPanel.cpp b/FTPConnectionPanel.cpp new file mode 100644 index 0000000..334a361 --- /dev/null +++ b/FTPConnectionPanel.cpp @@ -0,0 +1,47 @@ +// Statsgen Includes +#include "FTPConnectionPanel.h" +#include "GlobalStatistics.h" +#include "GUITriggerList.h" + +FTPConnectionPanel::FTPConnectionPanel() : GroupedConfigItemsPanel("FTP Connection Settings") +{ +} + +void FTPConnectionPanel::CreateConfigs(char *group) +{ + wxString configKey; + wxString triggerKey; + + GUITriggerList triggerList; + GUITriggerItem triggerItem; + + triggerKey.Printf("/%s/FTPEnabled",group); + + triggerItem.SetPositiveDisableTrigger(triggerKey,"N"); + triggerList.Add(triggerItem); + + AddBoolean("Enabled",triggerKey,false); + + configKey.Printf("/%s/IPAddress",group); + Add("Hostname",configKey,"",-1); + + configKey.Printf("/%s/FTPUsername",group); + Add("Username",configKey,"",-1,&triggerList); + + configKey.Printf("/%s/FTPPassword",group); + Add("Password",configKey,"",-1,&triggerList); + + configKey.Printf("/%s/FTPPort",group); + Add("Port",configKey,"21",5,&triggerList); + + configKey.Printf("/%s/FTPPassive",group); + AddBoolean("Passive",configKey,true,&triggerList); + + configKey.Printf("/%s/FTPRestartDownload",group); + AddBoolean("Restart Downloads",configKey,true,&triggerList); +} + +FTPConnectionPanel::~FTPConnectionPanel() +{ +} + diff --git a/FTPConnectionPanel.h b/FTPConnectionPanel.h new file mode 100644 index 0000000..953fc3f --- /dev/null +++ b/FTPConnectionPanel.h @@ -0,0 +1,22 @@ +#ifndef __FTPCONNECTIONPANEL +#define __FTPCONNECTIONPANEL + +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" + +class FTPConnectionPanel : public GroupedConfigItemsPanel +{ + public: + FTPConnectionPanel(); + ~FTPConnectionPanel(); + void CreateConfigs(char *group); + protected: + + private: +}; + +#endif diff --git a/FileConfigItemGUI.cpp b/FileConfigItemGUI.cpp new file mode 100644 index 0000000..4b38c3a --- /dev/null +++ b/FileConfigItemGUI.cpp @@ -0,0 +1,222 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "FileConfigItemGUI.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(FileConfigItemGUI, wxPanel) + EVT_SIZE(FileConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,FileConfigItemGUI::OnTextChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,FileConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +FileConfigItemGUI::FileConfigItemGUI() +{ + configKey=""; + maxCharacters=-1; + directoryConfig=NULL; +} + +void FileConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +FileConfigItemGUI::~FileConfigItemGUI() +{ +} + +void FileConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void FileConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + int maxCharactersIn, + DirectoryConfigItemGUI *directoryConfigIn) +{ + wxSizeEvent event; + wxSize buttonSize(16,16); + + labelText=labelTextIn; + defaultValue=defaultValueIn; + maxCharacters=maxCharactersIn; + directoryConfig=directoryConfigIn; + + //SetConfigKey(configKey); + + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + configKey=configKeyIn; + + button.Create(this, + WINDOW_ID_CONFIG_BUTTON, + wxArtProvider::GetIcon(wxART_FILE_OPEN, + wxART_OTHER, + buttonSize)); + SetConfigKey(configKey); + + OnResize(event); +} + +wxString FileConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int FileConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void FileConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void FileConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + int buttonWidth; + int buttonHeight; + int widthForTextEdit; + int fixedWidth; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=button.GetSize(); + buttonWidth=itemSize.GetWidth(); + buttonHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-buttonWidth; + fixedWidth=(maxCharacters * FONT_CHAR_WIDTH)+FONT_TEXT_CTRL_GAP; + if (maxCharacters>0) + { + // We have an overriding field width + if (fixedWidthGetValue(); + } + else + { + path=""; + } + message="Select File"; + newFilename=wxFileSelector(message,path); + if (newFilename.Length()>0) + { + wxFileName filename(newFilename); + if (directoryConfig!=NULL) + { + textEdit.SetValue(filename.GetFullName()); + path=filename.GetPath(); + directoryConfig->SetValue(path); + } + else + { + textEdit.SetValue(filename.GetFullPath()); + } + } + +} diff --git a/FileConfigItemGUI.h b/FileConfigItemGUI.h new file mode 100644 index 0000000..9625b08 --- /dev/null +++ b/FileConfigItemGUI.h @@ -0,0 +1,47 @@ +#ifndef __FILECONFIGITEMGUI +#define __FILECONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" +#include "DirectoryConfigItemGUI.h" + +class FileConfigItemGUI : public BaseConfigItemGUI +{ + public: + FileConfigItemGUI(); + virtual ~FileConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + int maxCharactersIn, + DirectoryConfigItemGUI *directoryGUIIn=NULL); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxTextCtrl textEdit; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + DirectoryConfigItemGUI *directoryConfig; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GUITriggerItem.cpp b/GUITriggerItem.cpp new file mode 100644 index 0000000..c595b32 --- /dev/null +++ b/GUITriggerItem.cpp @@ -0,0 +1,127 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "GUITriggerItem.h" +#include "GlobalStatistics.h" + +GUITriggerItem::GUITriggerItem() +{ + configKey=""; + matchValue=""; + matchSwitchesOff=true; + triggerHides=false; +} + +GUITriggerItem::~GUITriggerItem() +{ +} + +void GUITriggerItem::SetPositiveHideTrigger(wxString &key,wxString &value) +{ + triggerHides =true; + configKey =key; + matchValue =value; + matchSwitchesOff=true; +} +void GUITriggerItem::SetNegativeHideTrigger(wxString &key,wxString &value) +{ + triggerHides =true; + configKey =key; + matchValue =value; + matchSwitchesOff=false; +} +void GUITriggerItem::SetPositiveDisableTrigger(wxString &key,wxString &value) +{ + triggerHides =false; + configKey =key; + matchValue =value; + matchSwitchesOff=true; +} +void GUITriggerItem::SetNegativeDisableTrigger(wxString &key,wxString &value) +{ + triggerHides =false; + configKey =key; + matchValue =value; + matchSwitchesOff=false; +} +void GUITriggerItem::SetPositiveHideTrigger(wxString &key,const char *value) +{ + triggerHides =true; + configKey =key; + matchValue =value; + matchSwitchesOff=true; +} +void GUITriggerItem::SetNegativeHideTrigger(wxString &key,const char *value) +{ + triggerHides =true; + configKey =key; + matchValue =value; + matchSwitchesOff=false; +} +void GUITriggerItem::SetPositiveDisableTrigger(wxString &key,const char *value) +{ + triggerHides =false; + configKey =key; + matchValue =value; + matchSwitchesOff=true; +} +void GUITriggerItem::SetNegativeDisableTrigger(wxString &key,const char *value) +{ + triggerHides =false; + configKey =key; + matchValue =value; + matchSwitchesOff=false; +} + +bool GUITriggerItem::PerformTrigger(wxWindow *window, + bool *currentlyShown, + bool *currentlyEnabled) +{ + bool triggered=false; + wxString configValue; + + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey,&configValue); + if (configValue.CmpNoCase(matchValue)==0) + { + if (triggerHides) + { + if (matchSwitchesOff) + { + *currentlyShown=false; + } + } + else + { + if (matchSwitchesOff) + { + *currentlyEnabled=false; + } + } + } + else + { + if (triggerHides) + { + if (!matchSwitchesOff) + { + *currentlyShown=false; + } + } + else + { + if (!matchSwitchesOff) + { + *currentlyEnabled=false; + } + } + } + } + + return (triggered); +} + diff --git a/GUITriggerItem.h b/GUITriggerItem.h new file mode 100644 index 0000000..a6be8c9 --- /dev/null +++ b/GUITriggerItem.h @@ -0,0 +1,40 @@ +#ifndef __GUITRIGGERITEM +#define __GUITRIGGERITEM + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen Includes + +class GUITriggerItem; + +WX_DECLARE_OBJARRAY(GUITriggerItem,ArrayOfGUITriggerItem); +class GUITriggerItem +{ + public: + wxString configKey; + wxString matchValue; + bool matchSwitchesOff; + bool triggerHides; + public: + GUITriggerItem(); + ~GUITriggerItem(); + bool PerformTrigger(wxWindow *panel, + bool *currentlyShown, + bool *currentlyEnabled); + void SetPositiveDisableTrigger(wxString &key,const char *value); + void SetPositiveDisableTrigger(wxString &key,wxString &value); + void SetNegativeDisableTrigger(wxString &key,const char *value); + void SetNegativeDisableTrigger(wxString &key,wxString &value); + void SetPositiveHideTrigger(wxString &key,const char *value); + void SetPositiveHideTrigger(wxString &key,wxString &value); + void SetNegativeHideTrigger(wxString &key,const char *value); + void SetNegativeHideTrigger(wxString &key,wxString &value); + +}; + + +#endif diff --git a/GUITriggerList.cpp b/GUITriggerList.cpp new file mode 100644 index 0000000..7dcbd9c --- /dev/null +++ b/GUITriggerList.cpp @@ -0,0 +1,57 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "GUITriggerList.h" +#include "GUITriggerItem.h" + +void GUITriggerList::Add(GUITriggerItem &triggerItem) +{ + triggerList.Add(triggerItem); +} + +bool GUITriggerList::PerformTrigger(wxWindow *window) +{ + int itemCount; + int itemIndex; + GUITriggerItem triggerItem; + bool triggered; + bool currentlyShown; + bool currentlyEnabled; + + currentlyShown=true; + currentlyEnabled=true; + + triggered=false; + itemCount=triggerList.GetCount(); + for (itemIndex=0;itemIndexEnable(); + } + else + { + window->Disable(); + } + + if (currentlyShown) + { + window->Show(); + } + else + { + window->Hide(); + } + + return (triggered); +} + diff --git a/GUITriggerList.h b/GUITriggerList.h new file mode 100644 index 0000000..2a1bc0f --- /dev/null +++ b/GUITriggerList.h @@ -0,0 +1,23 @@ +#ifndef __GUITRIGGERLIST +#define __GUITRIGGERLIST + +// wxWindows includes +#include +#include + + +// Statsgen Includes +#include "GUITriggerItem.h" + +class GUITriggerList +{ + public: + void Add(GUITriggerItem &triggerItem); + bool PerformTrigger(wxWindow *window); + public: + ArrayOfGUITriggerItem triggerList; + +}; + + +#endif diff --git a/GUIWizards.cpp b/GUIWizards.cpp new file mode 100644 index 0000000..b28e9ad --- /dev/null +++ b/GUIWizards.cpp @@ -0,0 +1,5161 @@ +#include "StaticFunctions.h" +#include "GUIWizards.h" +#include "GlobalStatistics.h" +#include "RemoteMachine.h" +#include "GenericOKCancelDialog.h" +#include "FTPBrowserPanel.h" +#include "Progress.h" +#include "StatsgenWeb.h" +#include "RestartingFTP.h" + +BEGIN_EVENT_TABLE(GUIWizardPageConfigText,GUIWizardPageConfig) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfig::OnValueChanged) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageConfigChoice,GUIWizardPageConfig) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfig::OnValueChanged) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageConfigChoice::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageConfigFile,GUIWizardPageConfig) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfigFile::OnValueChanged) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageConfigFile::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageConfigWildcard,GUIWizardPageConfig) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfigWildcard::OnValueChanged) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageConfigWildcard::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageConfigRemoteDirectory,GUIWizardPageConfig) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfigRemoteDirectory::OnValueChanged) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageConfigRemoteDirectory::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageConfigBoolean,GUIWizardPageConfig) + EVT_CHECKBOX(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GUIWizardPageConfig::OnValueChanged) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageRemoteTest,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageRemoteTest::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageRun,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageRun::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageImagePacks,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageImagePacks::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageTemplatePacks,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageTemplatePacks::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageRemoteFileTest,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageRemoteFileTest::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageRemoteDirectoryTest,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageRemoteDirectoryTest::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(GUIWizardPageChoice,GUIWizardPageStatsgen) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GUIWizardPageChoice::OnButtonPressed) +END_EVENT_TABLE() + +BEGIN_EVENT_TABLE(StatsgenWizard,wxWizard) + EVT_WIZARD_PAGE_CHANGED(WINDOW_ID_WIZARD,StatsgenWizard::OnWizardPageChanged) + EVT_WIZARD_FINISHED(WINDOW_ID_WIZARD,StatsgenWizard::OnWizardFinish) + EVT_WIZARD_FINISHED(WINDOW_ID_WIZARD,StatsgenWizard::OnWizardCancel) +END_EVENT_TABLE() + +GUIWizardPageStatsgen::GUIWizardPageStatsgen(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : wxWizardPage(wizardIn) +{ + wxFont font; + previousPage = NULL; + nextPage = NULL; + helpTextCtrl = NULL; + sectionTitle = NULL; + installProgress = NULL; + helpText = ""; + callBack = NULL; + callBackObject = NULL; + + wizard=wizardIn; + + helpTextCtrl = new wxRichTextCtrl(this); + sectionTitle = new wxStaticText(this,-1,""); + font = sectionTitle->GetFont(); + font.SetPointSize(3 * font.GetPointSize()); + font.SetWeight(wxFONTWEIGHT_BOLD); + + sectionTitle->SetFont(font); + + installProgress = new wxGauge(this,-1,30); + helpTextCtrl->SetEditable(false); + pageID=parentPageID; + pageID+=thisPageID; +} + + +GUIWizardPageStatsgen::~GUIWizardPageStatsgen() +{ +} + +wxString GUIWizardPageStatsgen::GetPageID() +{ + return (pageID); +} + +void GUIWizardPageStatsgen::SetSectionTitle(const char *titleChars) +{ + sectionTitle->SetLabel(titleChars); +} + +void GUIWizardPageStatsgen::SetCallBack(void(* callBackIn)(void *object),void *callBackObjectIn) +{ + callBack = callBackIn; + callBackObject = callBackObjectIn; +} + +wxWizardPage *GUIWizardPageStatsgen::GetPrev() const +{ + return (previousPage); +} + +wxWizardPage *GUIWizardPageStatsgen::GetNext() const +{ + return (nextPage); +} + +void GUIWizardPageStatsgen::SetNextPage(wxWizardPage *page) +{ + nextPage = page; +} + +void GUIWizardPageStatsgen::SetPreviousPage(wxWizardPage *page) +{ + previousPage = page; +} + +void GUIWizardPageStatsgen::SetHelp(const char *helpTextIn) +{ + helpText = helpTextIn; + UpdateScreen(); +} + +void GUIWizardPageStatsgen::UpdateScreen() +{ + if (helpTextCtrl!=NULL) + { + wxString workingString; + wxString textSection; + wxString codeSection; + bool startSection; + char code; + + workingString =helpText; + helpTextCtrl->Clear(); + helpTextCtrl->BeginFontSize(15); + + while (workingString.Length()>0) + { + textSection=workingString.BeforeFirst('['); + helpTextCtrl->AppendText(textSection); + + codeSection=workingString.AfterFirst('['); + if (codeSection.StartsWith("/")) + { + startSection=false; + codeSection=codeSection.AfterFirst('/'); + } + else + { + startSection=true; + } + code='\0'; + if (codeSection.Length()>0) + { + code=codeSection[0]; + } + switch (code) + { + case 'b': + case 'B': + if (startSection) + { + helpTextCtrl->BeginBold(); + } + else + { + helpTextCtrl->EndBold(); + } + break; + case 'i': + case 'I': + if (startSection) + { + helpTextCtrl->BeginItalic(); + } + else + { + helpTextCtrl->EndItalic(); + } + break; + } + workingString=codeSection.AfterFirst(']'); + } + //helpTextCtrl->SetValue(helpText); + } +} + +wxSize GUIWizardPageStatsgen::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize controlSize; + + controlSize.SetWidth(width); + controlSize.SetHeight(0); + + return (controlSize); +} + +void GUIWizardPageStatsgen::Resize(int maxHeight) +{ + int sectionTitleX; + int sectionTitleY; + int sectionTitleWidth; + int sectionTitleHeight; + + int progressX; + int progressY; + int progressWidth; + int progressHeight; + int helpX; + int helpY; + int helpWidth; + int helpHeight; + int controlX; + int controlY; + int controlHeight; + wxSize controlSize; + wxSize pageSize; + + int width=700; + int height; + wxString msg; + + if (helpTextCtrl!=NULL) + { + controlSize = ResizeControl(0,0,width,false); + controlHeight = controlSize.GetHeight(); + if (controlSize.GetWidth()>width) + { + width=controlSize.GetWidth(); + } + sectionTitleX = 0; + sectionTitleY = 0; + sectionTitleWidth = width; + sectionTitleHeight = 60; + progressX = 0; + progressY = sectionTitleY + sectionTitleHeight; + progressHeight = 20; + progressWidth = width; + + controlX = 0; + controlY = progressY+progressHeight+5; + + helpX = 0; + helpY = controlY + controlHeight; + helpWidth = width; + helpHeight = 100; + + sectionTitle->SetSize(sectionTitleX,sectionTitleY,sectionTitleWidth,sectionTitleHeight); + installProgress->SetSize(progressX,progressY,progressWidth,progressHeight); + if (maxHeight>=0) + { + helpHeight = maxHeight - helpY; + } + helpTextCtrl->SetSize(helpX,helpY,helpWidth,helpHeight); + + ResizeControl(controlX,controlY,width,true); + + height = helpY + helpHeight; + + SetSize(wxSize(width,height)); + } +} + +void GUIWizardPageStatsgen::SetPageCounter(int pageIndexIn,int pageCountIn) +{ + pageIndex = pageIndexIn; + wizardPageCount = pageCountIn; + + installProgress->SetRange(wizardPageCount); +} + +void GUIWizardPageStatsgen::UpdateProgress() +{ + installProgress->SetValue(pageIndex+1); +} + +bool GUIWizardPageStatsgen::AutoAdvance() +{ + return false; +} + +void GUIWizardPageStatsgen::PageContentsChanged() +{ + if (wizard!=NULL) + { + wizard->PageContentsChanged(); + } +} + +GUIWizardPageNull::GUIWizardPageNull(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ +} + +GUIWizardPageNull::~GUIWizardPageNull() +{ +} + +bool GUIWizardPageNull::AutoAdvance() +{ + return true; +} + +wxString GUIWizardPageNull::GetValue() +{ + wxString value=""; + return (value); +} + +GUIWizardPageConfig::GUIWizardPageConfig(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + titleCtrl = NULL; + configKey = ""; + defaultValue = ""; + title = ""; + AllowCtrlUpdates(); + + titleCtrl = new wxStaticText(this,-1,title); +} + +GUIWizardPageConfig::~GUIWizardPageConfig() +{ +} + +bool GUIWizardPageConfig::ConfigReady() +{ + if (configKey.Length()>0) + { + return (true); + } + else + { + return (false); + } +} + +void GUIWizardPageConfig::SetDefault(const char *defaultValueIn) +{ + if (defaultValueIn==NULL) + { + defaultValue = ""; + } + else + { + defaultValue = defaultValueIn; + } +} + +void GUIWizardPageConfig::SetConfigKey(wxString &configKeyIn,const char *defaultValueIn) +{ + configKey = configKeyIn; + SetDefault(defaultValueIn); + UpdateScreen(); +} + +void GUIWizardPageConfig::SetConfigTitle(const char *titleIn) +{ + title=titleIn; + UpdateScreen(); +} + +void GUIWizardPageConfig::VetoCtrlUpdates() +{ + vetoUpdates =true; +} + +void GUIWizardPageConfig::AllowCtrlUpdates() +{ + vetoUpdates =false; +} + +bool GUIWizardPageConfig::CtrlUpdatesAllowed() +{ + return (vetoUpdates); +} + +void GUIWizardPageConfig::OnValueChanged(wxCommandEvent &event) +{ + if (ScreenReady() && ConfigReady() && !CtrlUpdatesAllowed()) + { + SetValueFromCtrl(); + UpdateConfigFromValue(); + PageContentsChanged(); + } +} + +void GUIWizardPageConfig::UpdateConfigFromValue() +{ + if (ConfigReady()) + { + globalStatistics.configData.WriteTextValue(configKey,value); + if (callBack!=NULL) + { + callBack(callBackObject); + } + } +} + +void GUIWizardPageConfig::UpdateValueFromConfig() +{ + if (ConfigReady()) + { + globalStatistics.configData.ReadTextValue(configKey,&value,(char *)defaultValue.GetData()); + } +} + +void GUIWizardPageConfig::UpdateCtrlFromValue() +{ + if (ScreenReady() && ConfigReady()) + { + UpdateValueFromConfig(); + VetoCtrlUpdates(); + SetCtrlFromValue(); + AllowCtrlUpdates(); + } +} + +void GUIWizardPageConfig::UpdateScreen() +{ + if (titleCtrl!=NULL) + { + titleCtrl->SetLabel(title); + } + UpdateCtrlFromValue(); + GUIWizardPageStatsgen::UpdateScreen(); +} + +wxSize GUIWizardPageConfig::ResizeControl(int x,int y,int width,bool resize) +{ + int titleX; + int titleY; + int titleWidth; + int titleHeight; + wxSize controlSize; + + if (titleCtrl!=NULL) + { + titleX =x; + titleY =y; + titleWidth =width; + titleHeight =30; + + controlSize.SetWidth(titleWidth); + controlSize.SetHeight(titleHeight); + if (resize) + { + titleCtrl->SetSize(titleX,titleY,titleWidth,titleHeight); + } + } + + return (controlSize); +} + +wxString GUIWizardPageConfig::GetValue() +{ + //UpdateValueFromConfig(); + return (value); +} + +GUIWizardPageConfigText::GUIWizardPageConfigText(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfig(wizardIn,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + CreateControl(); +} + +GUIWizardPageConfigText::~GUIWizardPageConfigText() +{ + valueCtrl = FALSE; +} +void GUIWizardPageConfigText::CreateControl() +{ + valueCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); +} + +wxSize GUIWizardPageConfigText::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize baseControlSize; + wxSize controlSize; + int baseX; + int baseY; + int baseWidth; + int baseHeight; + int valueX; + int valueY; + int valueWidth; + int valueHeight; + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + valueX = x; + valueY = baseY + baseHeight; + valueWidth = width; + valueHeight = 30; + + controlSize.SetWidth(width); + controlSize.SetHeight(baseHeight + valueHeight); + + if (resize) + { + valueCtrl->SetSize(valueX,valueY,valueWidth,valueHeight); + } + + return (controlSize); +} + +void GUIWizardPageConfigText::SetCtrlFromValue() +{ + valueCtrl->SetValue(value); +} + +bool GUIWizardPageConfigText::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigText::SetValueFromCtrl() +{ + value=valueCtrl->GetValue(); +} + +GUIWizardPageRemoteTest::GUIWizardPageRemoteTest(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + statusCtrl = new wxStaticText(this,-1,"Test Not Run"); + errorCtrl = new wxRichTextCtrl(this,-1,""); + errorCtrl->SetEditable(false); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Test Connection"); + lastConnectionResult = false; + SetHelp("[b]Press the button[/b] to confirm FTP Access Details are correct"); +} + +GUIWizardPageRemoteTest::~GUIWizardPageRemoteTest() +{ + lastConnectionResult = false; +} + +void GUIWizardPageRemoteTest::SetGroupPrefix(wxString &groupPrefixIn) +{ + groupPrefix = groupPrefixIn; +} + +bool GUIWizardPageRemoteTest::TestResult() +{ + return (lastConnectionResult); +} + +wxString GUIWizardPageRemoteTest::GetValue() +{ + wxString retVal; + + if (TestResult()) + { + retVal="TRUE"; + } + else + { + retVal="FALSE"; + } + + return (retVal); +} + +bool GUIWizardPageRemoteTest::PerformTest() +{ + RemoteMachine remoteMachine(groupPrefix); + RestartingFTP ftpConnection; + + lastConnectionResult =remoteMachine.Connect(ftpConnection); + + if (lastConnectionResult) + { + statusCtrl->SetLabel("Connection Successful"); + errorCtrl->SetValue(""); + } + else + { + errorCtrl->SetValue(remoteMachine.GetLastErrorMessage()); + statusCtrl->SetLabel("Failed to connect"); + } + + return (lastConnectionResult); +} + +void GUIWizardPageRemoteTest::OnButtonPressed(wxCommandEvent &event) +{ + PerformTest(); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +wxSize GUIWizardPageRemoteTest::ResizeControl(int x,int y,int width,bool resize) +{ + int statusX; + int statusY; + int statusWidth; + int statusHeight; + + int errorX; + int errorY; + int errorWidth; + int errorHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + + wxSize controlSize; + + if (statusCtrl!=NULL) + { + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =y; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + statusX =x; + statusY =buttonY + buttonHeight; + statusWidth =width; + statusHeight =30; + + errorX =x; + errorY =statusY + statusHeight; + errorWidth =width; + errorHeight =90; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + statusCtrl->SetSize(statusX,statusY,statusWidth,statusHeight); + errorCtrl->SetSize(errorX,errorY,errorWidth,errorHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + statusHeight + errorHeight); + } + + return (controlSize); +} + +void GUIWizardPageRemoteTest::ResetTestResult() +{ + statusCtrl->SetLabel("Test Not Run"); + errorCtrl->SetValue(""); + lastConnectionResult = false; +} + + +GUIWizardPagesRemoteMachine::GUIWizardPagesRemoteMachine() +{ + pageHostname = NULL; + pageEnabled = NULL; + pageUsername = NULL; + pagePassword = NULL; + pageFTPPort = NULL; + pagePassive = NULL; + pageTest = NULL; + groupPrefix = ""; + + callBack = NULL; + callBackObject = NULL; +} + +GUIWizardPagesRemoteMachine::~GUIWizardPagesRemoteMachine() +{ +} + +void GUIWizardPagesRemoteMachine::SetCallBack(void(* callBackIn)(void *object),void *callBackObjectIn) +{ + callBack = callBackIn; + callBackObject = callBackObjectIn; +} + +void GUIWizardPagesRemoteMachine::SetSectionTitle(const char *titleChars) +{ + pageHostname->SetSectionTitle(titleChars); + pageEnabled->SetSectionTitle(titleChars); + pageUsername->SetSectionTitle(titleChars); + pagePassword->SetSectionTitle(titleChars); + pageFTPPort->SetSectionTitle(titleChars); + pagePassive->SetSectionTitle(titleChars); + pageTest->SetSectionTitle(titleChars); +} + +bool GUIWizardPagesRemoteMachine::IsFTPEnabled() +{ + return (pageEnabled->GetValue().CmpNoCase("y")==0); +} + +void GUIWizardPagesRemoteMachine::UpdateConfigKeys() +{ + wxString configKey; + + if ((pageHostname != NULL) && (groupPrefix.length()>0)) + { + configKey.Printf("/%s/IPAddress",groupPrefix.GetData()); + pageHostname->SetConfigKey(configKey); + + configKey.Printf("/%s/FTPUsername",groupPrefix.GetData()); + pageUsername->SetConfigKey(configKey); + + configKey.Printf("/%s/FTPPassword",groupPrefix.GetData()); + pagePassword->SetConfigKey(configKey); + + configKey.Printf("/%s/FTPPort",groupPrefix.GetData()); + pageFTPPort->SetConfigKey(configKey,"21"); + + configKey.Printf("/%s/FTPPassive",groupPrefix.GetData()); + pagePassive->SetConfigKey(configKey,"y"); + + configKey.Printf("/%s/FTPEnabled",groupPrefix.GetData()); + pageEnabled->SetConfigKey(configKey,"y"); + + pageTest->SetGroupPrefix(groupPrefix); + } +} + +void GUIWizardPagesRemoteMachine::SetGroupPrefix(wxString &groupPrefixIn) +{ + groupPrefix = groupPrefixIn; + + UpdateConfigKeys(); +} + +wxString GUIWizardPagesRemoteMachine::GetEnabledPageID() +{ + return (pageEnabled->GetPageID()); +} + +void GUIWizardPagesRemoteMachine::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wxString ruleEnabled; + wxString ruleTestPassed; + + wizard=wizardIn; + pageHostname = new GUIWizardPageConfigText(wizard,pageID,_T("HOSTNAME")); + pageEnabled = new GUIWizardPageConfigBoolean(wizard,pageID,_T("FTPENABLED")); + pageUsername = new GUIWizardPageConfigText(wizard,pageID,_T("FTPUSERNAME")); + pagePassword = new GUIWizardPageConfigText(wizard,pageID,_T("FTPPASSWORD")); + pageFTPPort = new GUIWizardPageConfigText(wizard,pageID,_T("FTPPORT")); + pagePassive = new GUIWizardPageConfigBoolean(wizard,pageID,_T("FTPPASSIVE")); + pageTest = new GUIWizardPageRemoteTest(wizard,pageID,_T("TEST")); + + pageHostname->SetConfigTitle("Hostname"); + pageHostname->SetHelp( + "The [b]FTP Access hostname[/b], either in named form or in IP address form.\n" + "Do not prefix the address with [i]http://[/i] or [i]ftp://[/i]\n" + "Do not put the port number after the address.\n" + "\n" + "[b]Good examples.[/b]\n" + "[i]ftp.myserver.com[/i]\n" + "[i]192.168.0.1[/i]\n" + "\n" + "[b]Bad examples.[/b]\n" + "[i]ftp://ftp.myserver.com[/i]\n" + "[i]http://ftp.myserver.com[/i]\n" + "[i]192.168.0.1:28960[/i]\n" + ); + + pageEnabled->SetConfigTitle("Transfer Enabled?"); + pageEnabled->SetHelp("Enable / Disable FTP Transfer to this remote machine"); + pageEnabled->SetTrueFalseLabels("Yes", "No"); + + pageUsername->SetConfigTitle("FTP Username"); + pageUsername->SetHelp("Enter the [b]FTP username[/b] used to access the hostname"); + + pagePassword->SetConfigTitle("FTP Password"); + pagePassword->SetHelp("Enter the [b]FTP password[/b] used to access the hostname"); + + pageFTPPort->SetConfigTitle("FTP Port"); + pageFTPPort->SetHelp( + "Enter the [b]FTP port[/b] used to access the hostname\n" + "This is typically 21" + ); + + pagePassive->SetConfigTitle("FTP Passive Mode?"); + pagePassive->SetHelp( + "Enter whether in passive mode.\n" + "This is typically On" + ); + pagePassive->SetTrueFalseLabels("On", "Off"); + + + pageHostname->SetCallBack(ConfigChangedCallBack,this); + pageEnabled->SetCallBack(ConfigChangedCallBack,this); + pageUsername->SetCallBack(ConfigChangedCallBack,this); + pagePassword->SetCallBack(ConfigChangedCallBack,this); + pageFTPPort->SetCallBack(ConfigChangedCallBack,this); + pagePassive->SetCallBack(ConfigChangedCallBack,this); + pageTest->SetCallBack(ConnectionTestCallBack,this); + + ruleEnabled.Printf("%s=\"Y\"",pageEnabled->GetPageID().GetData()); + ruleTestPassed.Printf("%s=\"TRUE\"",pageTest->GetPageID().GetData()); + + wizard->AddPageLink(pageHostname, "", ""); + wizard->AddPageLink(pageEnabled, "", ""); + wizard->AddPageLink(pageUsername, ruleEnabled, ""); + wizard->AddPageLink(pagePassword, ruleEnabled, ""); + wizard->AddPageLink(pageFTPPort, ruleEnabled, ""); + wizard->AddPageLink(pagePassive, ruleEnabled, ""); + wizard->AddPageLink(pageTest, ruleEnabled, ruleTestPassed); + ResizePages(); +} + +void GUIWizardPagesRemoteMachine::ResizePages() +{ + pageHostname->Resize(); + pageEnabled->Resize(); + pageUsername->Resize(); + pagePassword->Resize(); + pageFTPPort->Resize(); + pagePassive->Resize(); + pageTest->Resize(); +} + +void GUIWizardPagesRemoteMachine::ConnectionTest() +{ + //PageContentsChanged(); +} + +void GUIWizardPagesRemoteMachine::ConnectionTestCallBack(void *object) +{ + GUIWizardPagesRemoteMachine *callingObject; + + callingObject = (GUIWizardPagesRemoteMachine *)object; + + callingObject->ConnectionTest(); +} +void GUIWizardPagesRemoteMachine::PopCallBack() +{ + if (callBack!=NULL) + { + callBack(callBackObject); + } +} + +void GUIWizardPagesRemoteMachine::ConfigChangedCallBack(void *object) +{ + GUIWizardPagesRemoteMachine *callingObject; + + callingObject = (GUIWizardPagesRemoteMachine *)object; + + callingObject->PopCallBack(); +} + +GUIWizardPageConfigBoolean::GUIWizardPageConfigBoolean(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfig(wizardIn,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + trueLabel = "Yes"; + falseLabel = "No"; + CreateControl(); +} + +GUIWizardPageConfigBoolean::~GUIWizardPageConfigBoolean() +{ + valueCtrl = FALSE; +} + + +void GUIWizardPageConfigBoolean::SetTrueFalseLabels(const char *trueLabelIn, const char *falseLabelIn) +{ + trueLabel = trueLabelIn; + falseLabel = falseLabelIn; +} + +void GUIWizardPageConfigBoolean::CreateControl() +{ + valueCtrl = new wxCheckBox(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE,title); +} + +wxSize GUIWizardPageConfigBoolean::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize baseControlSize; + wxSize controlSize; + int baseX; + int baseY; + int baseWidth; + int baseHeight; + int valueX; + int valueY; + int valueWidth; + int valueHeight; + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + valueX = x; + valueY = baseY + baseHeight; + valueWidth = width; + valueHeight = 30; + + controlSize.SetWidth(width); + controlSize.SetHeight(baseHeight + valueHeight); + + if (resize) + { + valueCtrl->SetSize(valueX,valueY,valueWidth,valueHeight); + } + + return (controlSize); +} + +void GUIWizardPageConfigBoolean::UpdateLabel() +{ + bool valueBool; + wxString titleStr; + + valueBool = (value.CmpNoCase("y")==0); + titleStr=title; + titleStr+=" "; + if (valueBool) + { + titleStr+=trueLabel; + } + else + { + titleStr+=falseLabel; + } + valueCtrl->SetLabel(titleStr); +} + +void GUIWizardPageConfigBoolean::SetCtrlFromValue() +{ + bool valueBool; + + valueBool = (value.CmpNoCase("y")==0); + valueCtrl->SetValue(valueBool); + UpdateLabel(); +} + +bool GUIWizardPageConfigBoolean::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigBoolean::SetValueFromCtrl() +{ + if (valueCtrl->GetValue()) + { + value="y"; + } + else + { + value="n"; + } + UpdateLabel(); +} + +GUIWizardPagesServer::GUIWizardPagesServer() +{ + pageServerType = NULL; + pageLocalOrRemote = NULL; + pageRCONPassword = NULL; + pageRCONPort = NULL; + pageMessagingEnabled = NULL; + pageRemoteLatestFilename = NULL; + pageRemoteLatestFilenameTest = NULL; + pageRemoteLatestSecondaryFilename = NULL; + pageRemoteLatestSecondaryFilenameTest = NULL; + pageRemoteArchiveFilename = NULL; + pageRemoteArchiveFilenameTest = NULL; + pageLocalLatestFilename = NULL; + pageLocalArchiveFilename = NULL; + pageLocalLatestSecondaryFilename = NULL; + groupPrefix = ""; + + logfileLimit =0; + +} + +GUIWizardPagesServer::~GUIWizardPagesServer() +{ +} + +void GUIWizardPagesServer::UpdateConfigKeys() +{ + wxString configKey; + + if ((pageServerType != NULL) && (groupPrefix.length()>0)) + { + configKey.Printf("/%s/serverType",groupPrefix.GetData()); + pageServerType->SetConfigKey(configKey,SERVER_TYPE_COD4); + + configKey.Printf("/%s/localorremote",groupPrefix.GetData()); + pageLocalOrRemote->SetConfigKey(configKey,WIZARD_CHOICE_HOMEPC); + + configKey.Printf("/%s/RCONPassword",groupPrefix.GetData()); + pageRCONPassword->SetConfigKey(configKey); + + configKey.Printf("/%s/gamePort",groupPrefix.GetData()); + pageRCONPort->SetConfigKey(configKey); + + configKey.Printf("/%s/MessagingEnabled",groupPrefix.GetData()); + pageMessagingEnabled->SetConfigKey(configKey,"n"); + + configKey.Printf("/%s/FTPLatest",groupPrefix.GetData()); + pageRemoteLatestFilename->SetConfigKey(configKey); + pageRemoteLatestFilenameTest->SetGroupPrefix(groupPrefix); + + configKey.Printf("/%s/FTPSecondaryLatest",groupPrefix.GetData()); + pageRemoteLatestSecondaryFilename->SetConfigKey(configKey); + pageRemoteLatestSecondaryFilenameTest->SetGroupPrefix(groupPrefix); + + configKey.Printf("/%s/FTPArchive",groupPrefix.GetData()); + pageRemoteArchiveFilename->SetConfigKey(configKey); + pageRemoteArchiveFilenameTest->SetGroupPrefix(groupPrefix); + + configKey.Printf("/%s/latest",groupPrefix.GetData()); + pageLocalLatestFilename->SetConfigKey(configKey); + + configKey.Printf("/%s/archive",groupPrefix.GetData()); + pageLocalArchiveFilename->SetConfigKey(configKey); + + configKey.Printf("/%s/secondarylatest",groupPrefix.GetData()); + pageLocalLatestSecondaryFilename->SetConfigKey(configKey); + + configKey.Printf("/%s/BanFile1Type",groupPrefix.GetData()); + globalStatistics.configData.WriteTextValue(configKey,"COD"); + + configKey.Printf("/%s/BanFile2Type",groupPrefix.GetData()); + globalStatistics.configData.WriteTextValue(configKey,"PUNKBUSTER"); + + configKey.Printf("/%s/FTPBanFile2Directory",groupPrefix.GetData()); + pagePBRemoteDirectory->SetConfigKey(configKey); + + SetTestParameters(); + SetLogfileLimit(); + } +} + +void GUIWizardPagesServer::SetTestParameters() +{ + wxString file; + wxString directory; + wxString configKey; + + if (groupPrefix.Length()>0) + { + pageRemoteLatestFilename->SplitValue(directory,file); + pageRemoteLatestFilenameTest->SetFile(directory,file); + + pageRemoteLatestSecondaryFilename->SplitValue(directory,file); + pageRemoteLatestSecondaryFilenameTest->SetFile(directory,file); + + directory=pageRemoteArchiveFilename->GetValue(); + file=pageRemoteArchiveFilename->GetWildcard(); + pageRemoteArchiveFilenameTest->SetFile(directory,file); + + pagePBRemoteDirectoryTest->SetGroupPrefix(groupPrefix); + + configKey.Printf("/%s/RCONUsePunkBuster",groupPrefix.GetData()); + if (pageLocalOrRemote->GetValue().Cmp(WIZARD_CHOICE_HOMEPC)==0) + { + globalStatistics.configData.WriteTextValue(configKey,"Y"); + } + else + { + globalStatistics.configData.WriteTextValue(configKey,"N"); + } + } +} + +void GUIWizardPagesServer::SetLogfileLimit(int limit) +{ + logfileLimit=limit; + SetLogfileLimit(); +} + +void GUIWizardPagesServer::SetLogfileLimit() +{ + wxString configKey; + wxString configValue; + + if (groupPrefix.Length()>0) + { + configKey.Printf("/%s/MaxLogfileSize",groupPrefix.GetData()); + configValue.Printf("%d",logfileLimit); + globalStatistics.configData.WriteTextValue(configKey,configValue); + } +} + +void GUIWizardPagesServer::SetGroupPrefix(wxString &groupPrefixIn) +{ + groupPrefix = groupPrefixIn; + + remoteMachine.SetGroupPrefix(groupPrefix); + UpdateConfigKeys(); +} + +void GUIWizardPagesServer::CreateWizardPages(StatsgenWizard *wizardIn) +{ + const char *sectionTitle="Configure Server"; + wxString ruleServerTypeContinue; + wxString ruleLocalOrRemoteContinue; + wxString ruleLocalOrRemoteHomePC; + wxString ruleLocalOrRemoteGameServer; + wxString ruleRemoteLatestFilenameTestPassed; + wxString ruleRemoteArchiveFilenameTestPassed; + wxString ruleQuakewars; + wxString ruleQuakewarsHomePC; + wxString ruleQuakewarsGameServer; + wxString ruleMOHAA; + wxString ruleMOHAAHomePC; + wxString ruleMOHAAGameServer; + wxString ruleMessagingServers; + wxString ruleMessagingEnabled; + wxString ruleMessaging; + wxString rulePunkbuster; + wxString rulePunkbusterTestPassed; + wxString ruleHomePCNotMOHAA; + wxString ruleGameServerNotMOHAA; + + wizard=wizardIn; + + wxArrayString localOrRemoteAnswers; + wxArrayString localOrRemoteButtonTexts; + wxArrayString localOrRemoteButtonDescriptions; + + wxArrayString serverTypeAnswers; + wxArrayString serverTypeButtonTexts; + wxArrayString serverTypeButtonDescriptions; + wxString archiveHelp; + + archiveHelp= + "If you have more than one logfile, typical for MOHAA servers, you can set up " + "a wildcard to download multiple logs.\n" + "\n" + "[b]examples of wildcard are[/b]\n" + "[i]*.log[/i]\n" + "[i]gameserver*.log[/i]\n" + "\n" + "It is important that logfiles are selected in the correct order, otherwise " + "stats will produce odd results, sometimes alphabetical order, the default, " + "is sufficient to achieve this, but at other times there may be components of " + "a date / time in the filename which means alphabetical ordering is not correct " + "to get around this problem you can specify special codes to indicate to " + "statsgen which parts of the filename represent dates.\n" + "\n" + "e.g.\n" + "If you are using Tatakai Server Scan to archive your logfiles they are named in the following way:-\n" + "[i]8_12_2007_gameserver.log[/i]\n" + "[i]9_12_2007_gameserver.log[/i]\n" + "[i]10_12_2007_gameserver.log[/i]\n" + "[i]11_12_2007_gameserver.log[/i]\n" + "etc.\n" + "\n" + "if you just put \n" + "[b]*gameserver.log[/b]\n" + "as the wildcard statsgen would assume these files should be picked up, sorted alphabetically as follows\n" + "[i]10_12_2007_gameserver.log[/i]\n" + "[i]11_12_2007_gameserver.log[/i]\n" + "[i]8_12_2007_gameserver.log[/i]\n" + "[i]9_12_2007_gameserver.log[/i]\n" + "This is obviously the wrong order as the 8th December file should be first.\n" + "This is where the embedded codes can be used to specify date components of the filename. The codes are CAPITAL letters and surrounded by $$ symbols.\n" + "[b]$$DAY$$[/b] The day of the month, 1 - 31\n" + "[b]$$0DAY$$[/b] The day of the month, 01 - 31\n" + "[b]$$MONTH$$[/b] The month of the year, 1 - 12\n" + "[b]$$0MONTH$$[/b] The month of the year, 01 - 12\n" + "[b]$$YEAR$$[/b] The year, e.g. 2007\n" + "[b]$$HOUR$$[/b] The hour of the day, 00 - 23\n" + "[b]$$MINUTE$$[/b] The minute of the hour, 00 - 59\n" + "[b]$$SECOND$$[/b] The second of the minute, 00 - 59\n" + "\n" + "so ... in order to sort the order properly we need to set the wildcard as follows\n" + "[b]$$DAY$$_$$MONTH$$_$$YEAR$$_gameserver.log[/b]\n"; + + localOrRemoteAnswers.Add(WIZARD_CHOICE_HOMEPC); + localOrRemoteAnswers.Add(WIZARD_CHOICE_GAMESERVER); + localOrRemoteButtonTexts.Add("Home PC"); + localOrRemoteButtonTexts.Add("Game Server"); + localOrRemoteButtonDescriptions.Add("Statsgen is running on your home PC"); + localOrRemoteButtonDescriptions.Add("Statsgen is running on the game server"); + + serverTypeAnswers.Add(SERVER_TYPE_COD1); + serverTypeAnswers.Add(SERVER_TYPE_COD2); + serverTypeAnswers.Add(SERVER_TYPE_COD4); + serverTypeAnswers.Add(SERVER_TYPE_COD5); + serverTypeAnswers.Add(SERVER_TYPE_MOHAA); + serverTypeAnswers.Add(SERVER_TYPE_QUAKEWARS); + serverTypeAnswers.Add(SERVER_TYPE_WOLFENSTEIN); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_COD1); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_COD2); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_COD4); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_COD5); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_MOHAA); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_QUAKEWARS); + serverTypeButtonTexts.Add(SERVER_TYPE_NAME_WOLFENSTEIN); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_COD1); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_COD2); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_COD4); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_COD5); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_MOHAA); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_QUAKEWARS); + serverTypeButtonDescriptions.Add(SERVER_TYPE_NAME_WOLFENSTEIN); + pageServerType = new GUIWizardPageConfigChoice(wizard, + pageID,_T("SERVERTYPE"), + serverTypeAnswers, + serverTypeButtonTexts, + serverTypeButtonDescriptions); + pageLocalOrRemote = new GUIWizardPageConfigChoice(wizard, + pageID,_T("LOCALORREMOTE"), + localOrRemoteAnswers, + localOrRemoteButtonTexts, + localOrRemoteButtonDescriptions); + pageRCONPassword = new GUIWizardPageConfigText(wizard,pageID,_T("RCONPASSWORD")); + pageRCONPort = new GUIWizardPageConfigText(wizard,pageID,_T("RCONPORT")); + pagePBRemoteDirectory = new GUIWizardPageConfigRemoteDirectory(wizard,pageID,_T("PBREMOTEDIRECTORY")); + pagePBRemoteDirectoryTest = new GUIWizardPageRemoteDirectoryTest(wizard,pageID,_T("PBREMOTEDIRECTORYTEST")); + pageMessagingEnabled = new GUIWizardPageConfigBoolean(wizard,pageID,_T("MESSAGINGENABLED")); + pageMessagingEnabled = new GUIWizardPageConfigBoolean(wizard,pageID,_T("MESSAGINGENABLED")); + pageRemoteLatestFilename = new GUIWizardPageConfigRemoteFile(wizard,pageID,_T("REMOTELATESTFILENAME")); + pageRemoteLatestFilenameTest = new GUIWizardPageRemoteFileTest(wizard,pageID,_T("REMOTELATESTFILENAMETEST")); + pageRemoteLatestSecondaryFilename = new GUIWizardPageConfigRemoteFile(wizard,pageID,_T("REMOTELATESTSECONDARYFILENAME")); + pageRemoteLatestSecondaryFilenameTest = new GUIWizardPageRemoteFileTest(wizard,pageID,_T("REMOTELATESTSECONDARYFILENAMETEST")); + pageRemoteArchiveFilename = new GUIWizardPageConfigRemoteWildcard(wizard,pageID,_T("REMOTEARCHIVEFILENAME")); + pageRemoteArchiveFilenameTest = new GUIWizardPageRemoteFileTest(wizard,pageID,_T("REMOTEARCHIVEFILENAMETEST")); + pageLocalLatestFilename = new GUIWizardPageConfigLocalFile(wizard,pageID,_T("LOCALLATESTFILENAME")); + pageLocalArchiveFilename = new GUIWizardPageConfigLocalWildcard(wizard,pageID,_T("LOCALARCHIVEFILENAME")); + pageLocalLatestFilename = new GUIWizardPageConfigLocalFile(wizard,pageID,_T("LOCALLATESTFILENAME")); + pageLocalArchiveFilename = new GUIWizardPageConfigLocalWildcard(wizard,pageID,_T("LOCALARCHIVEFILENAME")); + pageLocalLatestSecondaryFilename= new GUIWizardPageConfigLocalFile(wizard,pageID,_T("LOCALLATESTSECONDARYFILENAME")); + + pageLocalOrRemote->SetHelp( + "Depending on where you are running statsgen dictates various" + " configurations.\nYou can run statsgen on the [b]game server[/b]" + " itself, or if that is not available you can run statsgen" + " from your [b]home pc[/b]." + ); + pageLocalOrRemote->SetConfigTitle("Statsgen Location"); + + pageServerType->SetConfigTitle("Game Server Type"); + pageServerType->SetHelp( + "What sort of Server is this\n" + ); + + pageRCONPassword->SetConfigTitle("Game Server RCON Password?"); + pageRCONPassword->SetHelp("Enter the servers [b]RCON Password[/b].\n" + "This is used to send messages to the game server."); + + pagePBRemoteDirectory->SetConfigTitle("Punkbuster Remote Directory"); + pagePBRemoteDirectory->SetHelp("Enter the location on your game server of the [b]Punkbuster Directory[/b]"); + + pagePBRemoteDirectoryTest->SetHelp("[b]Press the button[/b] to test the Punkbuster Directory"); + + pageRCONPort->SetConfigTitle("Game Server Port?"); + pageRCONPort->SetHelp("Enter the Game Servers Port Number.\n" + "e.g.\n28960"); + + pageMessagingEnabled->SetConfigTitle("Game Server Messaging Enabled?"); + pageMessagingEnabled->SetHelp("Do you want to send stats messages to this paticular game server?"); + pageMessagingEnabled->SetTrueFalseLabels("Yes", "No"); + + pageRemoteLatestFilename->SetConfigTitle("Kills Logfile"); + pageRemoteLatestFilename->SetHelp( + "The logfile on the game server where the [b]kills[/b] are stored, typically on COD" + " games this is called [b]games_mp.log[/b]." + ); + pageRemoteLatestFilenameTest->SetHelp( + "[b]Push the button[/b] to ensure Kills logfile can be accessed." + ); + + pageRemoteLatestSecondaryFilename->SetConfigTitle("QuakeWars Objective Logfile"); + pageRemoteLatestSecondaryFilename->SetHelp( + "The logfile on the game server where the [b]objectives[/b] are stored" + ); + pageRemoteLatestSecondaryFilenameTest->SetHelp( + "[b]Push the button[/b] to ensure objective logfile can be accessed."); + + pageLocalLatestFilename->SetConfigTitle("Local Logfile Name"); + pageLocalLatestFilename->SetHelp( + "The logfile on the game server where the [b]kills[/b] are stored, typically on COD" + " games this is called [b]games_mp.log[/b]." + ); + + pageLocalLatestSecondaryFilename->SetConfigTitle("Quakewars Objective Logfile Name"); + pageLocalLatestSecondaryFilename->SetHelp( + "The logfile on the game server where the [b]objectives[/b] are stored" + ); + pageLocalArchiveFilename->SetConfigTitle("Multiple Kill File Wildcard"); + pageLocalArchiveFilename->SetHelp(archiveHelp); + pageRemoteArchiveFilename->SetConfigTitle("Multiple Kill File Wildcard"); + pageRemoteArchiveFilename->SetHelp(archiveHelp); + pageRemoteArchiveFilenameTest->SetHelp("[b]Push the button[/b] to check that the logfiles are accessible"); + + pageServerType->SetCallBack(ConfigChangedCallBack,this); + pageLocalOrRemote->SetCallBack(ConfigChangedCallBack,this); + pageRCONPassword->SetCallBack(ConfigChangedCallBack,this); + pagePBRemoteDirectory->SetCallBack(ConfigChangedCallBack,this); + pagePBRemoteDirectoryTest->SetCallBack(ConfigChangedCallBack,this); + pageRCONPort->SetCallBack(ConfigChangedCallBack,this); + pageMessagingEnabled->SetCallBack(ConfigChangedCallBack,this); + pageRemoteLatestFilename->SetCallBack(ConfigChangedCallBack,this); + pageRemoteLatestFilenameTest->SetCallBack(ConfigChangedCallBack,this); + pageRemoteLatestSecondaryFilename->SetCallBack(ConfigChangedCallBack,this); + pageRemoteLatestSecondaryFilenameTest->SetCallBack(ConfigChangedCallBack,this); + pageRemoteArchiveFilename->SetCallBack(ConfigChangedCallBack,this); + pageRemoteArchiveFilenameTest->SetCallBack(ConfigChangedCallBack,this); + pageLocalLatestFilename->SetCallBack(ConfigChangedCallBack,this); + pageLocalArchiveFilename->SetCallBack(ConfigChangedCallBack,this); + pageLocalLatestSecondaryFilename->SetCallBack(ConfigChangedCallBack,this); + + + + ruleServerTypeContinue.Printf("%s!\"\"",pageServerType->GetPageID().GetData()); + ruleLocalOrRemoteContinue.Printf("%s!\"\"",pageLocalOrRemote->GetPageID().GetData()); + ruleLocalOrRemoteHomePC.Printf("%s=\"%s\"",pageLocalOrRemote->GetPageID().GetData(),WIZARD_CHOICE_HOMEPC); + ruleLocalOrRemoteGameServer.Printf("%s=\"%s\"",pageLocalOrRemote->GetPageID().GetData(),WIZARD_CHOICE_GAMESERVER); + + ruleRemoteLatestFilenameTestPassed.Printf("%s=\"TRUE\"",pageRemoteLatestFilenameTest->GetPageID().GetData()); + ruleRemoteArchiveFilenameTestPassed.Printf("%s=\"TRUE\"",pageRemoteArchiveFilenameTest->GetPageID().GetData()); + rulePunkbusterTestPassed.Printf("%s=\"TRUE\"",pagePBRemoteDirectoryTest->GetPageID().GetData()); + + ruleQuakewars.Printf("%s=\"%s\"",pageServerType->GetPageID().GetData(),SERVER_TYPE_QUAKEWARS); + ruleQuakewarsHomePC.Printf("(%s)&(%s)",ruleLocalOrRemoteHomePC.GetData(),ruleQuakewars.GetData()); + ruleQuakewarsGameServer.Printf("(%s)&(%s)",ruleLocalOrRemoteGameServer.GetData(),ruleQuakewars.GetData()); + ruleMOHAA.Printf("%s=\"%s\"",pageServerType->GetPageID().GetData(),SERVER_TYPE_MOHAA); + ruleMOHAAHomePC.Printf("(%s)&(%s)",ruleLocalOrRemoteHomePC.GetData(),ruleMOHAA.GetData()); + ruleMOHAAGameServer.Printf("(%s)&(%s)",ruleLocalOrRemoteGameServer.GetData(),ruleMOHAA.GetData()); + ruleMessagingServers.Printf("((%s=\"%s\")|(%s=\"%s\")|(%s=\"%s\")|(%s=\"%s\")|(%s=\"%s\"))", + pageServerType->GetPageID().GetData(),SERVER_TYPE_COD1, + pageServerType->GetPageID().GetData(),SERVER_TYPE_COD2, + pageServerType->GetPageID().GetData(),SERVER_TYPE_COD4, + pageServerType->GetPageID().GetData(),SERVER_TYPE_COD5, + pageServerType->GetPageID().GetData(),SERVER_TYPE_QUAKEWARS); + ruleMessagingEnabled.Printf("(%s=\"%s\")", pageMessagingEnabled->GetPageID().GetData(),"Y"); + ruleMessaging.Printf("%s&%s",ruleMessagingServers.GetData(),ruleMessagingEnabled.GetData()); + rulePunkbuster.Printf("(%s)&(%s)",ruleMessaging.GetData(),ruleLocalOrRemoteHomePC.GetData()); + ruleHomePCNotMOHAA.Printf("(%s)&(%s!\"%s\")", + ruleLocalOrRemoteHomePC.GetData(), + pageServerType->GetPageID().GetData(), + SERVER_TYPE_MOHAA); + ruleGameServerNotMOHAA.Printf("(%s)&(%s!\"%s\")", + ruleLocalOrRemoteGameServer.GetData(), + pageServerType->GetPageID().GetData(), + SERVER_TYPE_MOHAA); + + wizard->AddPageLink(pageServerType, "" ,ruleServerTypeContinue); + wizard->AddPageLink(pageLocalOrRemote, "" ,ruleLocalOrRemoteContinue); + remoteMachine.SetPageID(pageID,"REMOTEMACHINE"); + remoteMachine.CreateWizardPages(wizard); + wizard->AddPageLink(pageRCONPort, "" ,""); + wizard->AddPageLink(pageMessagingEnabled, ruleMessagingServers ,""); + wizard->AddPageLink(pageRCONPassword, ruleMessaging ,""); + wizard->AddPageLink(pagePBRemoteDirectory, rulePunkbuster ,""); + wizard->AddPageLink(pagePBRemoteDirectoryTest, rulePunkbuster ,rulePunkbusterTestPassed); + wizard->AddPageLink(pageRemoteLatestFilename, ruleHomePCNotMOHAA ,""); + wizard->AddPageLink(pageRemoteLatestFilenameTest, ruleHomePCNotMOHAA ,ruleRemoteLatestFilenameTestPassed); + wizard->AddPageLink(pageRemoteLatestSecondaryFilename, ruleQuakewarsHomePC ,""); + wizard->AddPageLink(pageRemoteLatestSecondaryFilenameTest, ruleQuakewarsHomePC ,ruleRemoteLatestFilenameTestPassed); + wizard->AddPageLink(pageRemoteArchiveFilename, ruleMOHAAHomePC ,""); + wizard->AddPageLink(pageRemoteArchiveFilenameTest, ruleMOHAAHomePC ,ruleRemoteArchiveFilenameTestPassed); + wizard->AddPageLink(pageLocalLatestFilename, ruleGameServerNotMOHAA ,""); + wizard->AddPageLink(pageLocalArchiveFilename, ruleMOHAAGameServer ,""); + wizard->AddPageLink(pageLocalLatestSecondaryFilename, ruleQuakewarsGameServer ,""); + + /* + wizard->AddPageLink(pageHostname,"",""); + wizard->AddPageLink(pageEnabled,"",""); + wizard->AddPageLink(pageUsername,"FTPENABLED=\"TRUE\"",""); + wizard->AddPageLink(pagePassword,"FTPENABLED=\"TRUE\"",""); + wizard->AddPageLink(pageFTPPort,"FTPENABLED=\"TRUE\"",""); + wizard->AddPageLink(pagePassive,"FTPENABLED=\"TRUE\"",""); + wizard->AddPageLink(pageTest,"FTPENABLED=\"TRUE\"","TRUE"); + wizard->AddPageLink(pageFinished,"",""); + */ + SetSectionTitle(sectionTitle); + + ResizePages(); +} + +void GUIWizardPagesServer::SetSectionTitle(const char *sectionTitle) +{ + pageServerType->SetSectionTitle(sectionTitle); + pageLocalOrRemote->SetSectionTitle(sectionTitle); + pageRCONPassword->SetSectionTitle(sectionTitle); + pageRCONPort->SetSectionTitle(sectionTitle); + pagePBRemoteDirectory->SetSectionTitle(sectionTitle); + pagePBRemoteDirectoryTest->SetSectionTitle(sectionTitle); + pageMessagingEnabled->SetSectionTitle(sectionTitle); + pageRemoteLatestFilename->SetSectionTitle(sectionTitle); + pageRemoteLatestFilenameTest->SetSectionTitle(sectionTitle); + pageRemoteLatestSecondaryFilename->SetSectionTitle(sectionTitle); + pageRemoteLatestSecondaryFilenameTest->SetSectionTitle(sectionTitle); + pageLocalLatestFilename->SetSectionTitle(sectionTitle); + pageLocalLatestSecondaryFilename->SetSectionTitle(sectionTitle); + pageRemoteArchiveFilename->SetSectionTitle(sectionTitle); + pageRemoteArchiveFilenameTest->SetSectionTitle(sectionTitle); + pageLocalArchiveFilename->SetSectionTitle(sectionTitle); + remoteMachine.SetSectionTitle(sectionTitle); +} + +void GUIWizardPagesServer::ResizePages() +{ + pageServerType->Resize(); + pageLocalOrRemote->Resize(); + pageRCONPassword->Resize(); + pageRCONPort->Resize(); + pagePBRemoteDirectory->Resize(); + pagePBRemoteDirectoryTest->Resize(); + pageMessagingEnabled->Resize(); + pageRemoteLatestFilename->Resize(); + pageRemoteLatestFilenameTest->Resize(); + pageRemoteLatestSecondaryFilename->Resize(); + pageRemoteLatestSecondaryFilenameTest->Resize(); + pageLocalLatestFilename->Resize(); + pageLocalLatestSecondaryFilename->Resize(); + pageRemoteArchiveFilename->Resize(); + pageRemoteArchiveFilenameTest->Resize(); + pageLocalArchiveFilename->Resize(); +} + +void GUIWizardPagesServer::PrepareServerConfig() +{ + wxFileName baseDirectory(wxGetApp().argv[0]); + wxFileName logDirectory; + wxFileName archiveDirectory; + wxFileName banDirectory; + wxString logDirectoryName; + wxString archiveDirectoryName; + wxString banDirectoryName; + wxString baseDirectoryName; + + baseDirectory.AppendDir(groupPrefix); + baseDirectory.MakeAbsolute(); + logDirectory=baseDirectory; + archiveDirectory=baseDirectory; + banDirectory=baseDirectory; + archiveDirectory.AppendDir("archivelogs"); + banDirectory.AppendDir("ban"); + logDirectory.AppendDir("logs"); + + logDirectoryName=logDirectory.GetPath(); + banDirectoryName=banDirectory.GetPath(); + archiveDirectoryName=archiveDirectory.GetPath(); + baseDirectoryName=baseDirectory.GetPath(); + + #ifdef _LINUX + mkdir(baseDirectoryName,0777); + mkdir(banDirectoryName,0777); + mkdir(logDirectoryName,0777); + mkdir(archiveDirectoryName,0777); + #else + wxMkDir(baseDirectoryName); + wxMkDir(banDirectoryName); + wxMkDir(logDirectoryName); + wxMkDir(archiveDirectoryName); + #endif + + logDirectoryName+=logDirectory.GetPathSeparator(); + banDirectoryName+=banDirectory.GetPathSeparator(); + archiveDirectoryName+=archiveDirectory.GetPathSeparator(); + + pageLocalLatestFilename->SetDefault(logDirectoryName); + pageLocalLatestFilename->UpdateValueFromConfig(); + pageLocalLatestSecondaryFilename->SetDefault(logDirectoryName); + pageLocalLatestSecondaryFilename->UpdateValueFromConfig(); + pageLocalArchiveFilename->SetDefault(archiveDirectoryName); + pageLocalArchiveFilename->UpdateValueFromConfig(); + + +} + +void GUIWizardPagesServer::ConfigChangedCallBack(void *object) +{ + GUIWizardPagesServer *serverWizard; + serverWizard = (GUIWizardPagesServer *)object; + serverWizard->SetTestParameters(); +} + +GUIWizardPageChoice::GUIWizardPageChoice(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID, + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + selectionLabel = NULL; + selectedChoice = NULL; + choice = ""; + + UpdateChoices(answerCodesIn,buttonTextsIn,buttonDescriptionsIn); +} + +GUIWizardPageChoice::~GUIWizardPageChoice() +{ +} + +void GUIWizardPageChoice::UpdateChoices( + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn) +{ + int buttonCount; + int buttonIndex; + wxButton *button; + wxStaticText *description; + int answerCount; + int answerIndex; + wxString answerCode; + wxString buttonText; + wxString buttonDescription; + + // Remove existing stuff + buttonCount=buttons.GetCount(); + for (buttonIndex=0;buttonIndexDestroy(); + description->Destroy(); + } + buttons.Clear(); + labels.Clear(); + + // Create new buttons and labels + answerCodes = answerCodesIn; + buttonTexts = buttonTextsIn; + buttonDescriptions = buttonDescriptionsIn; + + answerCount = answerCodes.GetCount(); + for (answerIndex = 0; answerIndex < answerCount; answerIndex++) + { + answerCode = answerCodes.Item(answerIndex); + buttonText = buttonTexts.Item(answerIndex); + buttonDescription = buttonDescriptions.Item(answerIndex); + button = new wxButton(this, + WINDOW_ID_BUTTON_NEW, + buttonText); + description = new wxStaticText(this, -1, buttonDescription); + buttons.Add(button); + labels.Add(description); + } + if (selectedChoice == NULL) + { + selectedChoice = new wxStaticText(this, -1, ""); + selectionLabel = new wxStaticText(this,-1,"Current Selection: "); + } + SetSelection("Nothing"); + if (answerCodes.GetCount()==1) + { + choice = buttonTexts.Item(0); + SetSelection(choice); + choice = answerCodes.Item(0); + } + Resize(); + +} + +void GUIWizardPageChoice::SetSelection(const char *selection) +{ + wxString selectionStr; + + selectionStr=selection; + SetSelection(selectionStr); +} + +void GUIWizardPageChoice::SetSelection(wxString &selection) +{ + selectedChoice->SetLabel(selection); +} + +void GUIWizardPageChoice::OnButtonPressed(wxCommandEvent &event) +{ + int answerCount; + int answerIndex; + wxButton *button=NULL; + wxString selection; + + + answerCount = buttons.GetCount(); + + choice = ""; + for (answerIndex = 0; answerIndex < answerCount; answerIndex++) + { + button=(wxButton *)buttons.Item(answerIndex); + if (button == event.GetEventObject()) + { + choice = answerCodes.Item(answerIndex); + selection = buttonTexts.Item(answerIndex); + SetSelection(selection); + break; + } + } + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); + +} + +wxString GUIWizardPageChoice::GetChoice() +{ + return (choice); +} + +wxString GUIWizardPageChoice::GetValue() +{ + return (GetChoice()); +} + +void GUIWizardPageChoice::SelectChoice(wxString &choiceIn) +{ + int answerCount; + int answerIndex; + wxButton *button=NULL; + wxString selection; + + for (answerIndex = 0; answerIndex < answerCount; answerIndex++) + { + button=(wxButton *)buttons.Item(answerIndex); + choice = answerCodes.Item(answerIndex); + if (choice.CmpNoCase(choiceIn)==0) + { + selection = buttonTexts.Item(answerIndex); + SetSelection(selection); + break; + } + choice = ""; + } + if (callBack!=NULL) + { + callBack(callBackObject); + } +} + +wxSize GUIWizardPageChoice::ResizeControl(int x,int y,int width,bool resize) +{ + + int selectionX; + int selectionY; + int selectionWidth; + int selectionHeight; + + int labelX; + int labelY; + int labelWidth; + int labelHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + int answerCount; + int answerIndex; + wxButton *button; + wxStaticText *label; + int maxButtonWidth; + int currentY; + int lineHeight; + int selectionLabelX; + int selectionLabelY; + int selectionLabelWidth; + int selectionLabelHeight; + + wxSize controlSize; + + if (selectedChoice!=NULL) + { + answerCount = buttons.GetCount(); + + maxButtonWidth = 0; + + for (answerIndex = 0; answerIndexGetSize(); + buttonWidth = objectSize.GetWidth(); + buttonHeight = objectSize.GetHeight(); + if (buttonWidth > maxButtonWidth) + { + maxButtonWidth = buttonWidth; + } + } + if (maxButtonWidth > width) + { + width = maxButtonWidth; + } + // Make the width at least 100 more than the button sizes + if ((width - maxButtonWidth) <= 100) + { + width = width + 100; + } + + currentY = y; + for (answerIndex = 0; answerIndexGetSize(); + buttonX = x; + buttonY = currentY; + buttonWidth = maxButtonWidth; + buttonHeight = objectSize.GetHeight(); + + label = (wxStaticText *)labels.Item(answerIndex); + labelX = maxButtonWidth + 10; + labelY = currentY; + labelWidth = width - (maxButtonWidth + 10); + labelHeight = 30; + + if (labelHeight > buttonHeight) + { + lineHeight = labelHeight; + } + else + { + lineHeight = buttonHeight; + } + + if (resize) + { + button->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + label->SetSize(labelX,labelY,labelWidth,labelHeight); + } + currentY+=lineHeight; + currentY+=10; + } + + selectionLabelX =x; + selectionLabelY =currentY; + selectionLabelWidth =100; + selectionLabelHeight =30; + + selectionX =selectionLabelX + selectionLabelWidth; + selectionY =currentY; + selectionHeight =30; + selectionWidth =width; + + if (resize) + { + selectionLabel->SetSize(selectionLabelX,selectionLabelY, + selectionLabelWidth,selectionLabelHeight); + selectedChoice->SetSize(selectionX,selectionY, + selectionWidth,selectionHeight); + + } + + currentY+=selectionHeight; + + controlSize.SetWidth(width); + controlSize.SetHeight(currentY - y); + } + + return (controlSize); +} + +GUIWizardPageConfigFile::GUIWizardPageConfigFile(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfig(wizardIn,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + browseButton = FALSE; + CreateControl(); +} + +GUIWizardPageConfigFile::~GUIWizardPageConfigFile() +{ + valueCtrl = FALSE; + browseButton = FALSE; +} + +void GUIWizardPageConfigFile::CreateControl() +{ + valueCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + browseButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Browse For File"); +} + +wxSize GUIWizardPageConfigFile::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize baseControlSize; + wxSize controlSize; + int baseX; + int baseY; + int baseWidth; + int baseHeight; + int valueX; + int valueY; + int valueWidth; + int valueHeight; + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + + objectSize = browseButton->GetSize(); + buttonWidth = objectSize.GetWidth(); + buttonHeight = objectSize.GetHeight(); + + if (width < buttonWidth) + { + width = buttonWidth; + } + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + valueX = x; + valueY = baseY + baseHeight; + valueWidth = width; + valueHeight = 30; + + buttonX = x; + buttonY = valueY + valueHeight; + + controlSize.SetWidth(width); + controlSize.SetHeight(baseHeight + valueHeight + buttonHeight); + + if (resize) + { + valueCtrl->SetSize(valueX,valueY,valueWidth,valueHeight); + browseButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + } + + return (controlSize); +} + +void GUIWizardPageConfigFile::SetCtrlFromValue() +{ + valueCtrl->SetValue(value); +} + +bool GUIWizardPageConfigFile::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigFile::SetValueFromCtrl() +{ + value = valueCtrl->GetValue(); +} + +void GUIWizardPageConfigFile::GetConfigKeys(wxString &configKeyDirectory, + wxString &configKeyFilename) +{ + configKeyDirectory = configKey + "Directory"; + configKeyFilename = configKey + "Filename"; +} + +void GUIWizardPageConfigFile::SplitValue(wxString &valueDirectory, + wxString &valueFilename) +{ + wxFileName filename(value,wxPATH_UNIX); + + valueFilename = filename.GetFullName(); + valueDirectory = filename.GetPath(); + valueDirectory.Replace("\\","/"); +} + +void GUIWizardPageConfigFile::OnButtonPressed(wxCommandEvent &event) +{ + wxString userFilename; + + userFilename=RequestFileFromUser(); + if (userFilename.Length()>0) + { + value=userFilename; + SetCtrlFromValue(); + } + PageContentsChanged(); +} + +void GUIWizardPageConfigFile::UpdateConfigFromValue() +{ + wxString configKeyDirectory; + wxString configKeyFilename; + + if (ConfigReady()) + { + GetConfigKeys(configKeyDirectory,configKeyFilename); + SplitValue(directory,filename); + globalStatistics.configData.WriteTextValue(configKeyDirectory,directory); + globalStatistics.configData.WriteTextValue(configKeyFilename,filename); + if (callBack!=NULL) + { + callBack(callBackObject); + } + } +} + +void GUIWizardPageConfigFile::UpdateValueFromConfig() +{ + wxString configKeyDirectory; + wxString configKeyFilename; + + if (ConfigReady()) + { + GetConfigKeys(configKeyDirectory,configKeyFilename); + globalStatistics.configData.ReadTextValue(configKeyDirectory,&directory); + globalStatistics.configData.ReadTextValue(configKeyFilename,&filename); + if ((directory.Length()==0)&&(filename.Length()==0)&&(defaultValue.Length()>0)) + { + wxFileName defaultFilename(defaultValue); + directory=defaultFilename.GetPath(); + filename=defaultFilename.GetFullName(); + globalStatistics.configData.WriteTextValue(configKeyDirectory,directory); + globalStatistics.configData.WriteTextValue(configKeyFilename,filename); + } + + CombineValue(); + } +} + +void GUIWizardPageConfigFile::CombineValue() +{ +} + +GUIWizardPageConfigRemoteFile::GUIWizardPageConfigRemoteFile(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfigFile(wizardIn,parentPageID,thisPageID) +{ +} + +GUIWizardPageConfigRemoteFile::~GUIWizardPageConfigRemoteFile() +{ +} + +wxString GUIWizardPageConfigRemoteFile::RequestFileFromUser() +{ + wxString message; + bool result; + wxString groupPrefix; + wxString userFilename; + + message="Select File"; + + groupPrefix = configKey.AfterFirst('/'); + groupPrefix = groupPrefix.BeforeFirst('/'); + + GenericOKCancelDialog dialog(this,-1, + message, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + FTPBrowserPanel *browserPanel=new FTPBrowserPanel( + groupPrefix, + directory, + true); + browserPanel->Create(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + browserPanel->CreateScreen(); + + dialog.SetPanel(browserPanel); + dialog.CreateDialog(); + result=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + if (result) + { + userFilename=browserPanel->GetCurrentSelection(); + } + else + { + userFilename=""; + } + return (userFilename); +} + +void GUIWizardPageConfigRemoteFile::CombineValue() +{ + value= directory; + value+="/"; + value+=filename; +} + +void GUIWizardPageConfigRemoteFile::SplitValue(wxString &valueDirectory, + wxString &valueFilename) +{ + wxFileName filename(value,wxPATH_UNIX); + + valueFilename = filename.GetFullName(); + valueDirectory = filename.GetPath(); + valueDirectory.Replace("\\","/"); +} + +GUIWizardPageConfigLocalFile::GUIWizardPageConfigLocalFile(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfigFile(wizardIn,parentPageID,thisPageID) +{ +} + +void GUIWizardPageConfigLocalFile::SplitValue(wxString &valueDirectory, + wxString &valueFilename) +{ + wxFileName filenameStr(value); + + valueFilename = filenameStr.GetFullName(); + valueDirectory = filenameStr.GetPath(); +} + +void GUIWizardPageConfigLocalFile::CombineValue() +{ + wxFileName filenameStr; + + filenameStr.SetFullName(filename); + filenameStr.SetPath(directory); + + value = filenameStr.GetFullPath(); +} + +wxString GUIWizardPageConfigLocalFile::RequestFileFromUser() +{ + wxString message; + wxString result; + wxString userFile; + + message="Select File"; + + result=wxFileSelector(message,directory); + if (result.Length()>0) + { + userFile=result; + } + + return (userFile); +} + +GUIWizardPageRemoteFileTest::GUIWizardPageRemoteFileTest(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + statusCtrl = new wxStaticText(this,-1,"Test Not Run"); + errorCtrl = new wxRichTextCtrl(this,-1,""); + errorCtrl->SetEditable(false); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Test Remote File"); + fileDirectory = ""; + lastResult = false; +} + +GUIWizardPageRemoteFileTest::~GUIWizardPageRemoteFileTest() +{ + lastResult = false; +} + +void GUIWizardPageRemoteFileTest::SetGroupPrefix(wxString &groupPrefixIn) +{ + groupPrefix = groupPrefixIn; +} + +bool GUIWizardPageRemoteFileTest::TestResult() +{ + return (lastResult); +} + +wxString GUIWizardPageRemoteFileTest::GetValue() +{ + wxString retVal; + + if (TestResult()) + { + retVal="TRUE"; + } + else + { + retVal="FALSE"; + } + + return (retVal); +} + +bool GUIWizardPageRemoteFileTest::PerformTest() +{ + RemoteMachine remoteMachine(groupPrefix); + RestartingFTP ftpConnection; + wxString msg; + int fileCount; + wxString filename; + + statusCtrl->SetLabel("Connecting To Remote Host"); + errorCtrl->SetValue(""); + lastResult =remoteMachine.Connect(ftpConnection); + + if (lastResult) + { + statusCtrl->SetLabel("Retrieving Directory Listing"); + lastResult = remoteMachine.GetRemoteDirectoryListing(fileDirectory,fileName,filenameList); + + if (lastResult) + { + fileCount = filenameList.GetCount(); + if (fileCount == 0) + { + statusCtrl->SetLabel("Retrieving Directory Listing: Failed"); + errorCtrl->SetLabel("Directory listing received, but no files present"); + lastResult = false; + } + else + { + msg.Printf("Retrieving Directory Listing: OK - %d files located",fileCount); + statusCtrl->SetLabel(msg); + } + } + else + { + statusCtrl->SetLabel("Retrieving Directory Listing: Failed"); + errorCtrl->SetValue(remoteMachine.GetLastErrorMessage()); + } + } + else + { + statusCtrl->SetLabel("Connecting To Remote Host: Failed"); + errorCtrl->SetValue(remoteMachine.GetLastErrorMessage()); + } + + return (lastResult); +} + +void GUIWizardPageRemoteFileTest::OnButtonPressed(wxCommandEvent &event) +{ + PerformTest(); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +wxSize GUIWizardPageRemoteFileTest::ResizeControl(int x,int y,int width,bool resize) +{ + int statusX; + int statusY; + int statusWidth; + int statusHeight; + + int errorX; + int errorY; + int errorWidth; + int errorHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + + wxSize controlSize; + + if (statusCtrl!=NULL) + { + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =y; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + statusX =x; + statusY =buttonY + buttonHeight; + statusWidth =width; + statusHeight =30; + + errorX =x; + errorY =statusY + statusHeight; + errorWidth =width; + errorHeight =90; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + statusCtrl->SetSize(statusX,statusY,statusWidth,statusHeight); + errorCtrl->SetSize(errorX,errorY,errorWidth,errorHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + statusHeight + errorHeight); + } + + return (controlSize); +} + +void GUIWizardPageRemoteFileTest::ResetTestResult() +{ + statusCtrl->SetLabel("Test Not Run"); + errorCtrl->SetValue(""); + lastResult = false; + filenameList.Clear(); + filesizeList.Clear(); +} + +void GUIWizardPageRemoteFileTest::SetFile(wxString &fileDirectoryIn, wxString &fileNameIn) +{ + fileDirectory = fileDirectoryIn; + fileName = fileNameIn; +} + +GUIWizardPageConfigChoice::GUIWizardPageConfigChoice(StatsgenWizard *wizardIn, + wxString parentPageID, + wxString thisPageID, + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn) : GUIWizardPageConfig(wizardIn,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + answerCodes = answerCodesIn; + buttonTexts = buttonTextsIn; + buttonDescriptions = buttonDescriptionsIn; + + choice = ""; + CreateControl(); +} + +GUIWizardPageConfigChoice::~GUIWizardPageConfigChoice() +{ + valueCtrl = FALSE; +} +void GUIWizardPageConfigChoice::CreateControl() +{ + int answerCount; + int answerIndex; + wxButton *button; + wxStaticText *description; + wxString answerCode; + wxString buttonText; + wxString buttonDescription; + + + answerCount = answerCodes.GetCount(); + for (answerIndex = 0; answerIndex < answerCount; answerIndex++) + { + answerCode = answerCodes.Item(answerIndex); + buttonText = buttonTexts.Item(answerIndex); + buttonDescription = buttonDescriptions.Item(answerIndex); + button = new wxButton(this, + WINDOW_ID_BUTTON_NEW, + buttonText); + description = new wxStaticText(this, -1, buttonDescription); + buttons.Add(button); + labels.Add(description); + } + valueCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + selectionLabel = new wxStaticText(this,-1,"Current Selection: "); + SetSelection("Nothing"); + if (answerCodes.GetCount()==1) + { + choice = buttonTexts.Item(0); + SetSelection(choice); + choice = answerCodes.Item(0); + } +} + +void GUIWizardPageConfigChoice::SetCtrlFromValue() +{ + valueCtrl->SetValue(value); +} + +bool GUIWizardPageConfigChoice::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigChoice::SetValueFromCtrl() +{ + value=valueCtrl->GetValue(); +} + +void GUIWizardPageConfigChoice::SetSelection(const char *selection) +{ + wxString selectionStr; + + selectionStr=selection; +} + +void GUIWizardPageConfigChoice::SetSelection(wxString &selection) +{ + valueCtrl->SetValue(selection); +} + +void GUIWizardPageConfigChoice::OnButtonPressed(wxCommandEvent &event) +{ + int answerCount; + int answerIndex; + wxButton *button=NULL; + wxString selection; + + + answerCount = buttons.GetCount(); + + choice = ""; + for (answerIndex = 0; answerIndex < answerCount; answerIndex++) + { + button=(wxButton *)buttons.Item(answerIndex); + if (button == event.GetEventObject()) + { + choice = answerCodes.Item(answerIndex); + selection = buttonTexts.Item(answerIndex); + SetSelection(choice); + break; + } + } + if (callBack!=NULL) + { + callBack(callBackObject); + } + + PageContentsChanged(); +} + +wxString GUIWizardPageConfigChoice::GetChoice() +{ + return (choice); +} + +wxSize GUIWizardPageConfigChoice::ResizeControl(int x,int y,int width,bool resize) +{ + + int selectionX; + int selectionY; + int selectionWidth; + int selectionHeight; + + int labelX; + int labelY; + int labelWidth; + int labelHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + int answerCount; + int answerIndex; + wxButton *button; + wxStaticText *label; + int maxButtonWidth; + int currentY; + int lineHeight; + int baseX; + int baseY; + int baseHeight; + int baseWidth; + wxSize baseSize; + int selectionLabelX; + int selectionLabelY; + int selectionLabelWidth; + int selectionLabelHeight; + + wxSize controlSize; + wxSize baseControlSize; + + if (valueCtrl!=NULL) + { + answerCount = buttons.GetCount(); + + maxButtonWidth = 0; + + for (answerIndex = 0; answerIndexGetSize(); + buttonWidth = objectSize.GetWidth(); + buttonHeight = objectSize.GetHeight(); + if (buttonWidth > maxButtonWidth) + { + maxButtonWidth = buttonWidth; + } + } + if (maxButtonWidth > width) + { + width = maxButtonWidth; + } + // Make the width at least 100 more than the button sizes + if ((width - maxButtonWidth) <= 100) + { + width = width + 100; + } + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + currentY = baseY + baseHeight; + + for (answerIndex = 0; answerIndexGetSize(); + buttonX = x; + buttonY = currentY; + buttonWidth = maxButtonWidth; + buttonHeight = objectSize.GetHeight(); + + label = (wxStaticText *)labels.Item(answerIndex); + labelX = maxButtonWidth + 10; + labelY = currentY; + labelWidth = width - (maxButtonWidth + 10); + labelHeight = 30; + + if (labelHeight > buttonHeight) + { + lineHeight = labelHeight; + } + else + { + lineHeight = buttonHeight; + } + + if (resize) + { + button->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + label->SetSize(labelX,labelY,labelWidth,labelHeight); + } + currentY+=lineHeight; + currentY+=10; + } + + selectionLabelX =x; + selectionLabelY =currentY; + selectionLabelWidth =100; + selectionLabelHeight =30; + + selectionX =selectionLabelX + selectionLabelWidth; + selectionY =currentY; + selectionHeight =30; + selectionWidth =width; + + if (resize) + { + selectionLabel->SetSize(selectionLabelX,selectionLabelY, + selectionLabelWidth,selectionLabelHeight); + valueCtrl->SetSize(selectionX,selectionY, + selectionWidth,selectionHeight); + + } + + currentY+=selectionHeight; + + controlSize.SetWidth(width); + controlSize.SetHeight(currentY - y); + } + + return (controlSize); +} + +GUIWizardPagesServers::GUIWizardPagesServers() +{ + pageDeleteEditNew = NULL; + +} + +GUIWizardPagesServers::~GUIWizardPagesServers() +{ +} + +void GUIWizardPagesServers::SetLogfileLimit(int limit) +{ + pageServer.SetLogfileLimit(limit); +} + +void GUIWizardPagesServers::SetLogfileLimit() +{ + pageServer.SetLogfileLimit(); +} + +void GUIWizardPagesServers::SetDeleteEditNewChoices() +{ + wxArrayString deleteEditNewAnswers; + wxArrayString deleteEditNewButtonTexts; + wxArrayString deleteEditNewButtonDescriptions; + wxString listGroup ="SERVERS"; + wxArrayString serverIDs; + int serverCount; + + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverCount=serverIDs.GetCount(); + + deleteEditNewAnswers.Add(WIZARD_CHOICE_NEW); + deleteEditNewButtonTexts.Add("New"); + deleteEditNewButtonDescriptions.Add("Create New Server"); + if (serverCount > 0) + { + deleteEditNewAnswers.Add(WIZARD_CHOICE_EDIT); + deleteEditNewButtonTexts.Add("Edit"); + deleteEditNewButtonDescriptions.Add("Edit Existing Server"); + deleteEditNewAnswers.Add(WIZARD_CHOICE_DELETE); + deleteEditNewButtonTexts.Add("Delete"); + deleteEditNewButtonDescriptions.Add("Delete Existing Server"); + } + + pageDeleteEditNew->UpdateChoices( + deleteEditNewAnswers, + deleteEditNewButtonTexts, + deleteEditNewButtonDescriptions); + /* + if (serverCount>0) + { + pageDeleteEditNew->SetSelection(WIZARD_CHOICE_EDIT); + } + */ + + pageDeleteEditNew->Resize(); +} + +void GUIWizardPagesServers::CreateWizardPages(StatsgenWizard *wizardIn) +{ + const char *sectionTitle = "Configure Servers"; + wxString id; + wxString ruleDeleteEditNewContinue; + wxString ruleServerSelection; + wxString ruleServerSelectionContinue; + + wxArrayString deleteEditNewAnswers; + wxArrayString deleteEditNewButtonTexts; + wxArrayString deleteEditNewButtonDescriptions; + wxArrayString serverAnswers; + wxArrayString serverButtonTexts; + wxArrayString serverButtonDescriptions; + + wizard = wizardIn; + + id="FINISHED"; + + pageDeleteEditNew = new GUIWizardPageChoice(wizard, + pageID,_T("DELETEEDITNEW"), + deleteEditNewAnswers, + deleteEditNewButtonTexts, + deleteEditNewButtonDescriptions); + pageServerSelection = new GUIWizardPageChoice(wizard, + pageID,_T("SERVERSELECTION"), + serverAnswers, + serverButtonTexts, + serverButtonDescriptions); + SetDeleteEditNewChoices(); + SetServerChoices(); + pageServerSelection->SetHelp("select a server to modify"); + pageServerSelection->SetCallBack(ServerSelectedCallBack,this); + + + pageDeleteEditNew->SetHelp( + "Do you want to create a [b]new[/b] server configuration, " + "[b]edit[/b] an existing one, or [b]delete[/b] an existing one.\n" + "\n" + "[b]Press the appropriate button[/b]." + ); + + pageDeleteEditNew->SetCallBack(DeleteEditNewCallBack,this); + + + pageServer.SetPageID(pageID,"SERVER"); + ruleDeleteEditNewContinue.Printf("(%s=\"%s\")|(%s=\"%s\")", + pageDeleteEditNew->GetPageID().GetData(), + WIZARD_CHOICE_EDIT, + pageDeleteEditNew->GetPageID().GetData(), + WIZARD_CHOICE_NEW); + ruleServerSelection.Printf("%s=\"%s\"",pageDeleteEditNew->GetPageID().GetData(),WIZARD_CHOICE_EDIT); + ruleServerSelectionContinue.Printf("%s!\"\"",pageServerSelection->GetPageID().GetData()); + + wizard->AddPageLink(pageDeleteEditNew, "", ruleDeleteEditNewContinue); + wizard->AddPageLink(pageServerSelection,ruleServerSelection,ruleServerSelectionContinue); + pageServer.CreateWizardPages(wizard); + + pageDeleteEditNew->SetSectionTitle(sectionTitle); + pageServerSelection->SetSectionTitle(sectionTitle); + pageServer.SetSectionTitle(sectionTitle); + ResizePages(); +} + +void GUIWizardPagesServers::ResizePages() +{ + pageDeleteEditNew->Resize(); + pageServerSelection->Resize(); +} + +void GUIWizardPagesServers::SetServerChoices() +{ + wxArrayString serverIDs; + wxString listGroup ="SERVERS"; + wxString listPrefix ="Server"; + wxString serverID; + wxString serverConfigPrefix; + int serverCount; + int serverIndex; + wxArrayString serverAnswers; + wxArrayString serverButtonTexts; + wxArrayString serverButtonDescriptions; + + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverCount=serverIDs.GetCount(); + for (serverIndex=0;serverIndexUpdateChoices(serverAnswers, + serverButtonTexts, + serverButtonDescriptions); +} + +wxString GUIWizardPagesServers::GetDeleteEditNewChoice() +{ + return (pageDeleteEditNew->GetChoice()); +} + +void GUIWizardPagesServers::PrepareServerConfig() +{ + pageServer.PrepareServerConfig(); +} + +void GUIWizardPagesServers::DeleteEditNewCallBack(void *object) +{ + wxString captionNew="Enter new ID for Server"; + wxString messageNew="New ID"; + wxString captionDelete="Select ID To Remove"; + wxString messageDelete="Removal ID"; + wxString chosen; + wxString listGroup ="SERVERS"; + wxString listPrefix ="Server"; + wxString groupPrefix; + wxArrayString serverIDs; + wxString serverID; + wxString deleteEditNewChoice; + + GUIWizardPagesServers *serversWizard; + serversWizard = (GUIWizardPagesServers *)object; + + deleteEditNewChoice=serversWizard->GetDeleteEditNewChoice(); + + if (deleteEditNewChoice.CmpNoCase(WIZARD_CHOICE_NEW)==0) + { + chosen=wxGetTextFromUser(messageNew,captionNew); + SafeString(chosen); + if (chosen.Length()>0) + { + globalStatistics.ClearServers(); + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverIDs.Add(chosen); + globalStatistics.configData.WriteList(listGroup,serverIDs); + //globalStatistics.ReadServersFromConfig(); + groupPrefix=listPrefix+chosen; + // Need to create the directories and default configurations + // etc here + serversWizard->SetDeleteEditNewChoices(); + serversWizard->SetServerChoices(); + serversWizard->SelectServer(groupPrefix); + serversWizard->PrepareServerConfig(); + } + } + else + if (deleteEditNewChoice.CmpNoCase(WIZARD_CHOICE_EDIT)==0) + { + serversWizard->SelectServer(); + } + else + if (deleteEditNewChoice.CmpNoCase(WIZARD_CHOICE_DELETE)==0) + { + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverID=wxGetSingleChoice(messageDelete,captionDelete,serverIDs); + if (serverID.Length()>0) + { + serverIDs.Remove(serverID); + globalStatistics.configData.WriteList(listGroup,serverIDs); + groupPrefix=listPrefix+serverID; + globalStatistics.configData.DeleteGroup(groupPrefix); + serversWizard->SetDeleteEditNewChoices(); + serversWizard->SetServerChoices(); + } + } +} + +void GUIWizardPagesServers::ServerSelectedCallBack(void *object) +{ + GUIWizardPagesServers *serversWizard; + serversWizard = (GUIWizardPagesServers *)object; + + serversWizard->SelectServer(); +} + +void GUIWizardPagesServers::SelectServer() +{ + wxString serverConfigPrefix; + + serverConfigPrefix=pageServerSelection->GetChoice(); + pageServer.SetGroupPrefix(serverConfigPrefix); + pageServer.SetLogfileLimit(); +} + +void GUIWizardPagesServers::SelectServer(wxString &choice) +{ + wxString deleteEditNewChoice; + pageServerSelection->SelectChoice(choice); + deleteEditNewChoice=WIZARD_CHOICE_EDIT; + pageDeleteEditNew->SelectChoice(deleteEditNewChoice); +} + +GUIWizardPageConfigRemoteDirectory::GUIWizardPageConfigRemoteDirectory(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfig(wizardIn,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + browseButton = FALSE; + CreateControl(); +} + +GUIWizardPageConfigRemoteDirectory::~GUIWizardPageConfigRemoteDirectory() +{ + valueCtrl = FALSE; + browseButton = FALSE; +} + +void GUIWizardPageConfigRemoteDirectory::CreateControl() +{ + valueCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + browseButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Browse For Directory"); +} + +wxSize GUIWizardPageConfigRemoteDirectory::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize baseControlSize; + wxSize controlSize; + int baseX; + int baseY; + int baseWidth; + int baseHeight; + int valueX; + int valueY; + int valueWidth; + int valueHeight; + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + + objectSize = browseButton->GetSize(); + buttonWidth = objectSize.GetWidth(); + buttonHeight = objectSize.GetHeight(); + + if (width < buttonWidth) + { + width = buttonWidth; + } + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + valueX = x; + valueY = baseY + baseHeight; + valueWidth = width; + valueHeight = 30; + + buttonX = x; + buttonY = valueY + valueHeight; + + controlSize.SetWidth(width); + controlSize.SetHeight(baseHeight + valueHeight + buttonHeight); + + if (resize) + { + valueCtrl->SetSize(valueX,valueY,valueWidth,valueHeight); + browseButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + } + + return (controlSize); +} + +void GUIWizardPageConfigRemoteDirectory::SetCtrlFromValue() +{ + valueCtrl->SetValue(value); +} + +bool GUIWizardPageConfigRemoteDirectory::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigRemoteDirectory::SetValueFromCtrl() +{ + value = valueCtrl->GetValue(); +} + +void GUIWizardPageConfigRemoteDirectory::OnButtonPressed(wxCommandEvent &event) +{ + wxString message; + bool result; + wxString groupPrefix; + + message="Select Directory"; + + groupPrefix = "WEBSITE"; + + GenericOKCancelDialog dialog(this,-1, + message, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + FTPBrowserPanel *browserPanel=new FTPBrowserPanel( + groupPrefix, + value, + false); + browserPanel->Create(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + browserPanel->CreateScreen(); + + dialog.SetPanel(browserPanel); + dialog.CreateDialog(); + result=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + if (result) + { + value=browserPanel->GetCurrentSelection(); + SetCtrlFromValue(); + } + PageContentsChanged(); +} + +void GUIWizardPageConfigRemoteDirectory::UpdateConfigFromValue() +{ + if (ConfigReady()) + { + globalStatistics.configData.WriteTextValue(configKey,value); + if (callBack!=NULL) + { + callBack(callBackObject); + } + } +} + +void GUIWizardPageConfigRemoteDirectory::UpdateValueFromConfig() +{ + if (ConfigReady()) + { + globalStatistics.configData.ReadTextValue(configKey,&value); + } +} + +GUIWizardPagesWebsite::GUIWizardPagesWebsite() +{ + pageRemoteDirectory = NULL; + pageRemoteDirectoryTest = NULL; + groupPrefix = "WEBSITE"; + +} + +GUIWizardPagesWebsite::~GUIWizardPagesWebsite() +{ +} + +void GUIWizardPagesWebsite::UpdateConfigKeys() +{ + wxString configKey; + + if ((pageRemoteDirectory != NULL) && (groupPrefix.length()>0)) + { + configKey.Printf("/%s/FTPRemoteDirectory",groupPrefix.GetData()); + pageRemoteDirectory->SetConfigKey(configKey); + } +} + +void GUIWizardPagesWebsite::SetGroupPrefix() +{ + remoteMachine.SetGroupPrefix(groupPrefix); + pageRemoteDirectoryTest->SetGroupPrefix(groupPrefix); + UpdateConfigKeys(); +} + +void GUIWizardPagesWebsite::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wizard = wizardIn; + wxString ruleTestPassed; + wxString ruleWebsiteEnabled; + + const char *sectionTitle="Configure Website"; + pageRemoteDirectory = new GUIWizardPageConfigRemoteDirectory(wizard,pageID,_T("REMOTEDIRECTORY")); + pageRemoteDirectoryTest = new GUIWizardPageRemoteDirectoryTest(wizard,pageID,_T("REMOTEDIRECTORYTEST")); + + pageRemoteDirectory->SetConfigTitle("Website Directory"); + pageRemoteDirectory->SetHelp( + "The location on your web server where you want stats pages to be " + "uploaded too." + ); + + pageRemoteDirectoryTest->SetHelp( + "[b]Press the button[/b] to check the website directory is configured correctly." + ); + + + pageRemoteDirectory->SetCallBack(ConfigChangedCallBack,this); + pageRemoteDirectoryTest->SetCallBack(ConfigChangedCallBack,this); + + + remoteMachine.SetPageID(pageID,"WEBSITE"); + remoteMachine.CreateWizardPages(wizard); + + ruleTestPassed.Printf("%s=\"TRUE\"",pageRemoteDirectoryTest->GetPageID().GetData()); + ruleWebsiteEnabled.Printf("%s=\"Y\"",remoteMachine.GetEnabledPageID().GetData()); + //wxMessageBox(ruleWebsiteEnabled); + wizard->AddPageLink(pageRemoteDirectory, ruleWebsiteEnabled,""); + wizard->AddPageLink(pageRemoteDirectoryTest, ruleWebsiteEnabled,ruleTestPassed); + + remoteMachine.SetCallBack(ConfigChangedCallBack,this); + + pageRemoteDirectory->SetSectionTitle(sectionTitle); + pageRemoteDirectoryTest->SetSectionTitle(sectionTitle); + remoteMachine.SetSectionTitle(sectionTitle); + + SetGroupPrefix(); + + ResizePages(); +} + +void GUIWizardPagesWebsite::ResizePages() +{ + pageRemoteDirectory->Resize(); + pageRemoteDirectoryTest->Resize(); +} + +void GUIWizardPagesWebsite::SetDirectory() +{ + wxString directory; + + directory=pageRemoteDirectory->GetValue(); + pageRemoteDirectoryTest->SetDirectory(directory); +} + +void GUIWizardPagesWebsite::ConfigChangedCallBack(void *object) +{ + GUIWizardPagesWebsite *websiteWizard; + websiteWizard = (GUIWizardPagesWebsite *)object; + websiteWizard->SetDirectory(); +} + +GUIWizardPageRemoteDirectoryTest::GUIWizardPageRemoteDirectoryTest(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + statusCtrl = new wxStaticText(this,-1,"Test Not Run"); + errorCtrl = new wxRichTextCtrl(this,-1,""); + errorCtrl->SetEditable(false); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Test Remote Directory"); + fileDirectory = ""; + lastResult = false; +} + +GUIWizardPageRemoteDirectoryTest::~GUIWizardPageRemoteDirectoryTest() +{ + lastResult = false; +} + +void GUIWizardPageRemoteDirectoryTest::SetGroupPrefix(wxString &groupPrefixIn) +{ + groupPrefix = groupPrefixIn; +} + +bool GUIWizardPageRemoteDirectoryTest::TestResult() +{ + return (lastResult); +} + +wxString GUIWizardPageRemoteDirectoryTest::GetValue() +{ + wxString retVal; + + if (TestResult()) + { + retVal="TRUE"; + } + else + { + retVal="FALSE"; + } + + return (retVal); +} + +bool GUIWizardPageRemoteDirectoryTest::PerformTest() +{ + RemoteMachine remoteMachine(groupPrefix); + RestartingFTP ftpConnection; + wxString msg; + int fileCount; + wxString filename="*.*"; + wxArrayString filenameList; + + statusCtrl->SetLabel("Connecting To Remote Host"); + errorCtrl->SetValue(""); + lastResult =remoteMachine.Connect(ftpConnection); + + if (lastResult) + { + statusCtrl->SetLabel("Retrieving Directory Listing"); + lastResult = remoteMachine.GetRemoteDirectoryListing(fileDirectory,filename,filenameList); + fileCount=filenameList.GetCount(); + + if (lastResult) + { + msg.Printf("Retrieving Directory Listing: OK - %d files located",fileCount); + statusCtrl->SetLabel(msg); + } + else + { + statusCtrl->SetLabel("Retrieving Directory Listing: Failed"); + errorCtrl->SetValue(remoteMachine.GetLastErrorMessage()); + } + } + else + { + statusCtrl->SetLabel("Connecting To Remote Host: Failed"); + errorCtrl->SetValue(remoteMachine.GetLastErrorMessage()); + } + + return (lastResult); +} + +void GUIWizardPageRemoteDirectoryTest::OnButtonPressed(wxCommandEvent &event) +{ + PerformTest(); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +wxSize GUIWizardPageRemoteDirectoryTest::ResizeControl(int x,int y,int width,bool resize) +{ + int statusX; + int statusY; + int statusWidth; + int statusHeight; + + int errorX; + int errorY; + int errorWidth; + int errorHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + wxSize objectSize; + + wxSize controlSize; + + if (statusCtrl!=NULL) + { + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =y; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + statusX =x; + statusY =buttonY + buttonHeight; + statusWidth =width; + statusHeight =30; + + errorX =x; + errorY =statusY + statusHeight; + errorWidth =width; + errorHeight =90; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + statusCtrl->SetSize(statusX,statusY,statusWidth,statusHeight); + errorCtrl->SetSize(errorX,errorY,errorWidth,errorHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + statusHeight + errorHeight); + } + + return (controlSize); +} + +void GUIWizardPageRemoteDirectoryTest::ResetTestResult() +{ + statusCtrl->SetLabel("Test Not Run"); + errorCtrl->SetValue(""); + lastResult = false; +} + +void GUIWizardPageRemoteDirectoryTest::SetDirectory(wxString &fileDirectoryIn) +{ + fileDirectory = fileDirectoryIn; +} + +GUIWizardPagesFullConfig::GUIWizardPagesFullConfig() +{ +} + +GUIWizardPagesFullConfig::~GUIWizardPagesFullConfig() +{ +} + +void GUIWizardPagesFullConfig::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wizard = wizardIn; + pageServers.SetPageID("FULLCONFIG","SERVERS"); + pageServers.CreateWizardPages(wizard); + pageWebsite.SetPageID("FULLCONFIG","WEBSITE"); + pageWebsite.CreateWizardPages(wizard); +} + +StatsgenWizard::StatsgenWizard(wxWindow *parent, + int id, + wxString &title, + const wxBitmap &bitmap, + const wxPoint &pos, + long style): wxWizard(parent,WINDOW_ID_WIZARD,title,bitmap,pos,style) +{ + initialised = false; +} +void StatsgenWizard::OnWizardFinish(wxWizardEvent &event) +{ + globalStatistics.configData.CommitChanges(); + globalStatistics.ClearServers(); + globalStatistics.ReadServersFromConfig(); +} + +void StatsgenWizard::OnWizardCancel(wxWizardEvent &event) +{ + globalStatistics.configData.RollbackChanges(); +} + +void StatsgenWizard::OnWizardPageChanged(wxWizardEvent &event) +{ + GUIWizardPageStatsgen *page; + page = (GUIWizardPageStatsgen *)GetCurrentPage(); + if (IsShown()) + { + UpdatePageLinks(false); + if (!initialised) + { + initialised=true; + ResizePages(); + } + } + page->UpdateProgress(); +} + +void StatsgenWizard::ResizePages() +{ + pageLinks.ResizePages(); +} + +void StatsgenWizard::SetInitialPageLinks() +{ + UpdatePageLinks(true); + pageLinks.SetPageCounters(); +} + +void StatsgenWizard::PageContentsChanged() +{ + if (IsShown()) + { + UpdatePageLinks(false); + } +} + +void StatsgenWizard::AddPageLink(GUIWizardPageStatsgen *page, + const char *allowRule, + const char *continueRule) +{ + pageLinks.AddPageLink(page,allowRule,continueRule); +} + +void StatsgenWizard::UpdatePageLinks(bool fullList) +{ + pageLinks.SetPageLinks(fullList); +} + +GUIWizardPageStatsgen *StatsgenWizard::GetFirstPage() +{ + GUIWizardPageStatsgen *page = NULL; + + page = pageLinks.GetFirstPage(); + + return (page); +} + +GUIWizardPages::GUIWizardPages() +{ + pageID = ""; +} + +GUIWizardPages::~GUIWizardPages() +{ +} + +void GUIWizardPages::SetPageID(wxString parentID,wxString pageIDIn) +{ + pageID=parentID+pageIDIn; +} + +GUIWizardPageConfigWildcard::GUIWizardPageConfigWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfig(wizard,parentPageID,thisPageID) +{ + valueCtrl = FALSE; + directoryLabel = FALSE; + wildcardLabel = FALSE; + wildcardCtrl = FALSE; + browseButton = FALSE; + CreateControl(); +} + +GUIWizardPageConfigWildcard::~GUIWizardPageConfigWildcard() +{ + valueCtrl = FALSE; + wildcardCtrl = FALSE; + browseButton = FALSE; +} + +void GUIWizardPageConfigWildcard::CreateControl() +{ + valueCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + wildcardCtrl = new wxTextCtrl(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + wildcardLabel = new wxStaticText(this,-1,"Wildcard"); + directoryLabel = new wxStaticText(this,-1,"Directory"); + browseButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Browse For Directory"); +} + +wxString GUIWizardPageConfigWildcard::GetWildcard() +{ + return (wildcardValue); +} + +wxSize GUIWizardPageConfigWildcard::ResizeControl(int x,int y,int width,bool resize) +{ + wxSize baseControlSize; + wxSize controlSize; + int baseX; + int baseY; + int baseWidth; + int baseHeight; + int valueX; + int valueY; + int valueWidth; + int valueHeight; + int wildcardX; + int wildcardY; + int wildcardWidth; + int wildcardHeight; + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + int directoryLabelX; + int directoryLabelY; + int directoryLabelWidth; + int directoryLabelHeight; + int wildcardLabelX; + int wildcardLabelY; + int wildcardLabelWidth; + int wildcardLabelHeight; + wxSize objectSize; + + objectSize = browseButton->GetSize(); + + buttonWidth = objectSize.GetWidth(); + buttonHeight = objectSize.GetHeight(); + + if (width < buttonWidth) + { + width = buttonWidth; + } + + + baseX = x; + baseY = y; + baseControlSize = GUIWizardPageConfig::ResizeControl(baseX,baseY,width,resize); + baseWidth = baseControlSize.GetWidth(); + baseHeight = baseControlSize.GetHeight(); + + objectSize =directoryLabel->GetSize(); + directoryLabelWidth =objectSize.GetWidth(); + directoryLabelX = x; + directoryLabelY = baseY + baseHeight; + directoryLabelHeight = 30; + + valueX = directoryLabelX + directoryLabelWidth + 5; + valueY = baseY + baseHeight; + valueWidth = width - (5 + directoryLabelWidth); + valueHeight = 30; + + objectSize =wildcardLabel->GetSize(); + wildcardLabelWidth =objectSize.GetWidth(); + wildcardLabelX = x; + wildcardLabelY = valueY + valueHeight; + wildcardLabelHeight = 30; + + wildcardX = wildcardLabelX + wildcardLabelWidth + 5; + wildcardY = valueY + valueHeight; + wildcardWidth = width - (5 + wildcardLabelWidth); + wildcardHeight = 30; + + buttonX = x; + buttonY = wildcardY + wildcardHeight; + + controlSize.SetWidth(width); + controlSize.SetHeight(baseHeight + valueHeight + wildcardHeight + buttonHeight); + + if (resize) + { + valueCtrl->SetSize(valueX,valueY,valueWidth,valueHeight); + wildcardCtrl->SetSize(wildcardX,wildcardY,wildcardWidth,wildcardHeight); + browseButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + directoryLabel->SetSize(directoryLabelX,directoryLabelY,directoryLabelWidth,directoryLabelHeight); + wildcardLabel->SetSize(wildcardLabelX,wildcardLabelY,wildcardLabelWidth,wildcardLabelHeight); + } + + return (controlSize); +} + +void GUIWizardPageConfigWildcard::SetCtrlFromValue() +{ + VetoCtrlUpdates(); + wildcardCtrl->SetValue(wildcardValue); + valueCtrl->SetValue(value); + AllowCtrlUpdates(); + UpdateConfigFromValue(); +} + +bool GUIWizardPageConfigWildcard::ScreenReady() +{ + return (valueCtrl!=NULL); +} + +void GUIWizardPageConfigWildcard::SetValueFromCtrl() +{ + value = valueCtrl->GetValue(); + wildcardValue = wildcardCtrl->GetValue(); +} + +void GUIWizardPageConfigWildcard::GetConfigKeys(wxString &configKeyDirectory, + wxString &configKeyFilename) +{ + configKeyDirectory = configKey + "Directory"; + configKeyFilename = configKey + "Wildcard"; +} + +void GUIWizardPageConfigWildcard::OnButtonPressed(wxCommandEvent &event) +{ + wxString userDirectory; + + userDirectory = GetDirectoryFromUser(); + if (userDirectory.Length()>0) + { + value=userDirectory; + SetCtrlFromValue(); + } +} + +void GUIWizardPageConfigWildcard::UpdateConfigFromValue() +{ + wxString configKeyDirectory; + wxString configKeyFilename; + + if (ConfigReady()) + { + GetConfigKeys(configKeyDirectory,configKeyFilename); + globalStatistics.configData.WriteTextValue(configKeyDirectory,value); + globalStatistics.configData.WriteTextValue(configKeyFilename,wildcardValue); + if (callBack!=NULL) + { + callBack(callBackObject); + } + } +} + +void GUIWizardPageConfigWildcard::UpdateValueFromConfig() +{ + wxString configKeyDirectory; + wxString configKeyFilename; + wxString msg; + + if (ConfigReady()) + { + GetConfigKeys(configKeyDirectory,configKeyFilename); + globalStatistics.configData.ReadTextValue(configKeyDirectory,&value); + globalStatistics.configData.ReadTextValue(configKeyFilename,&wildcardValue); + if (value.Length()==0) + { + globalStatistics.configData.WriteTextValue(configKeyDirectory,defaultValue); + } + } +} + +GUIWizardPageConfigLocalWildcard::GUIWizardPageConfigLocalWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfigWildcard(wizard,parentPageID,thisPageID) +{ +} + +GUIWizardPageConfigLocalWildcard::~GUIWizardPageConfigLocalWildcard() +{ +} + +wxString GUIWizardPageConfigLocalWildcard::GetDirectoryFromUser() +{ + wxString message; + wxString result; + wxString userSelection; + + message="Select Directory"; + userSelection=wxDirSelector(message,value); + + return (userSelection); +} + +GUIWizardPageConfigRemoteWildcard::GUIWizardPageConfigRemoteWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID) : GUIWizardPageConfigWildcard(wizard,parentPageID,thisPageID) +{ +} + +GUIWizardPageConfigRemoteWildcard::~GUIWizardPageConfigRemoteWildcard() +{ +} + +wxString GUIWizardPageConfigRemoteWildcard::GetDirectoryFromUser() +{ + wxString message; + bool result; + wxString groupPrefix; + wxString userDirectory; + + message="Select Directory"; + + groupPrefix = configKey.AfterFirst('/'); + groupPrefix = groupPrefix.BeforeFirst('/'); + + GenericOKCancelDialog dialog(this,-1, + message, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + FTPBrowserPanel *browserPanel=new FTPBrowserPanel( + groupPrefix, + value, + false); + browserPanel->Create(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + browserPanel->CreateScreen(); + + dialog.SetPanel(browserPanel); + dialog.CreateDialog(); + result=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + userDirectory=""; + if (result) + { + userDirectory=browserPanel->GetCurrentSelection(); + } + + return (userDirectory); +} + +void GUIPageLinks::ResizePages() +{ + int pageCount; + int pageIndex; + GUIWizardPageStatsgen *page; + int maxHeight=0; + wxSize pageSize; + int pageHeight=0; + + pageCount=guiPages.GetCount(); + for (pageIndex=0;pageIndexGetSize(); + pageHeight=pageSize.GetHeight(); + if (pageHeight>maxHeight) + { + maxHeight=pageHeight; + } + } + for (pageIndex=0;pageIndexResize(maxHeight); + } +} + +void GUIPageLinks::SetPageCounters() +{ + int pageCount; + int pageIndex; + GUIWizardPageStatsgen *page; + + pageCount=guiPages.GetCount(); + for (pageIndex=0;pageIndexSetPageCounter(pageIndex,pageCount); + } +} + +void GUIPageLinks::AddPageLink(GUIWizardPageStatsgen *page, + const char *allowRule, + const char *continueRule) +{ + wxString allowStr; + wxString continueStr; + + allowStr = allowRule; + continueStr = continueRule; + + guiPages.Add(page); + allowRules.Add(allowStr); + continueRules.Add(continueStr); +} + +void GUIPageLinks::SetPageLinks(bool ignoreRules) +{ + int pageCount; + int pageIndex; + GUIWizardPageStatsgen *page; + GUIWizardPageStatsgen *prevPage; + GUIWizardPageStatsgen *nextPage; + wxString allowStr; + wxString continueStr; + wxString rule; + wxString prevPageID; + wxString nextPageID; + wxString prevPageValue; + wxString nextPageValue; + wxString msg; + + pageCount = guiPages.GetCount(); + page = NULL; + for (pageIndex = 0;pageIndex < pageCount;pageIndex++) + { + page = (GUIWizardPageStatsgen *)guiPages.Item(pageIndex); + nextPage = FindPage(pageIndex,+1,ignoreRules); + prevPage = FindPage(pageIndex,-1,ignoreRules); + continueStr = continueRules.Item(pageIndex); + if (!EvaluateRule(continueStr,ignoreRules)) + { + nextPage=page; + } + page->SetPreviousPage(prevPage); + page->SetNextPage(nextPage); + if (prevPage!=NULL) + { + prevPageID=prevPage->GetPageID(); + prevPageValue=prevPage->GetValue(); + } + else + { + prevPageID="NULL"; + prevPageValue=""; + } + if (nextPage!=NULL) + { + nextPageID=nextPage->GetPageID(); + nextPageValue=nextPage->GetValue(); + } + else + { + nextPageID="NULL"; + nextPageValue=""; + } + /* + msg.Printf("%d [%s](%s) -> [%s](%s) -> [%s](%s)", + pageIndex, + prevPageID.GetData(), + prevPageValue.GetData(), + page->GetPageID().GetData(), + page->GetValue().GetData(), + nextPageID.GetData(), + nextPageValue.GetData()); + wxMessageBox(msg); + */ + } +} + +GUIWizardPageStatsgen *GUIPageLinks::GetFirstPage() +{ + GUIWizardPageStatsgen *page; + + if (guiPages.GetCount()==0) + { + page = NULL; + } + else + { + page=(GUIWizardPageStatsgen *)guiPages.Item(0); + } + + return (page); +} + +GUIWizardPageStatsgen *GUIPageLinks::FindPage(int pageIndex,int direction,bool ignoreRules) +{ + int pageCount; + GUIWizardPageStatsgen *page; + GUIWizardPageStatsgen *foundPage=NULL; + wxString allowStr; + + pageCount = guiPages.GetCount(); + + pageIndex+=direction; + while ((pageIndex < pageCount) && (pageIndex >= 0)) + { + page = (GUIWizardPageStatsgen *)guiPages.Item(pageIndex); + allowStr = allowRules.Item(pageIndex); + if (EvaluateRule(allowStr,ignoreRules)) + { + foundPage = page; + break; + } + + pageIndex+=direction; + } + + return (foundPage); +} + +bool GUIPageLinks::EvaluateRule(wxString &rule,bool ignoreRules) +{ + bool result; + + rule.Replace(" ",""); + + + if ((rule.Length()==0)|| ignoreRules) + { + result = true; + } + else + { + result = EvaluateRuleSub(rule); + } + + return (result); +} + +bool GUIPageLinks::EvaluateRuleSub(wxString &rule) +{ + char ruleChar; + char operatorChar; + wxString value1; + wxString value2; + wxString id; + bool finished; + wxString msg; + bool debugOn; + wxArrayString valueQueue; + + + if (rule.Contains(')')) + { + debugOn=false; + } + else + { + debugOn=false; + } + id =""; + value1 =""; + value2 =""; + operatorChar =' '; + finished =false; + while ((rule.Length()>=0) && (!finished)) + { + if (debugOn) + { + wxMessageBox(rule); + } + if (rule.Length()==0) + { + finished = true; + ruleChar = 0; + } + else + { + ruleChar = rule[0]; + rule=rule.Mid(1); + } + switch (ruleChar) + { + case '&': + case '=': + case '!': + case '|': + case '(': + case ')': + case 0: + // End of ID Char + value1=GetValue(id); +msg.Printf("rulechar found[%c], ID=[%s] value=[%s]",ruleChar,id.GetData(),value1.GetData());if (debugOn) wxMessageBox(msg); + if (id.Length()>0) + { + PushValue(valueQueue,value1); + } + if (ValueCount(valueQueue) == 2) + { + value2=PopValue(valueQueue); + value1=PopValue(valueQueue); +msg.Printf("2 on stack:value1=[%s],value2=[%s] operatorChar=[%c]",value1.GetData(),value2.GetData(),operatorChar);if (debugOn) wxMessageBox(msg); + switch (operatorChar) + { + case '&': +msg.Printf("& val1=[%s] val2=[%s]",value1.GetData(),value2.GetData()); if (debugOn) wxMessageBox(msg); + value1=Bool2Value((Value2Bool(value1) && Value2Bool(value2))); + PushValue(valueQueue,value1); +msg.Printf("& result value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + break; + case '!': +msg.Printf("! val1=[%s] val2=[%s]",value1.GetData(),value2.GetData()); if (debugOn) wxMessageBox(msg); + value1=Bool2Value(value1.CmpNoCase(value2)!=0); + PushValue(valueQueue,value1); +msg.Printf("! result value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + break; + case '=': +msg.Printf("= val1=[%s] val2=[%s]",value1.GetData(),value2.GetData()); if (debugOn) wxMessageBox(msg); + value1=Bool2Value(value1.CmpNoCase(value2)==0); + PushValue(valueQueue,value1); +msg.Printf("= result value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + break; + case '|': +msg.Printf("| val1=[%s] val2=[%s]",value1.GetData(),value2.GetData()); if (debugOn) wxMessageBox(msg); + value1=Bool2Value((Value2Bool(value1) || Value2Bool(value2))); + PushValue(valueQueue,value1); +msg.Printf("| result value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + break; + } + } + switch (ruleChar) + { + case '&': + case '=': + case '!': + case '|': + operatorChar = ruleChar; + break; + case '(': + value1=Bool2Value(EvaluateRuleSub(rule)); + PushValue(valueQueue,value1); +msg.Printf("( result value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + break; + case ')': + case 0: + value1=PopValue(valueQueue); +msg.Printf(")/Null value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + return (Value2Bool(value1)); + break; + } + id=""; + break; + default: + id+=ruleChar; + } + } + + value1=PopValue(valueQueue); +msg.Printf("final value1=[%s]",value1.GetData());if (debugOn) wxMessageBox(msg); + return (Value2Bool(value1)); +} + +void GUIPageLinks::PushValue(wxArrayString &valueQueue,wxString &value) +{ + valueQueue.Add(value); +} + + +wxString GUIPageLinks::PopValue(wxArrayString &valueQueue) +{ + wxString value=""; + int queueSize; + + queueSize=ValueCount(valueQueue); + if (queueSize>0) + { + value = valueQueue.Item(queueSize-1); + valueQueue.RemoveAt(queueSize-1); + } + + return (value); +} + +int GUIPageLinks::ValueCount(wxArrayString &valueQueue) +{ + return(valueQueue.GetCount()); +} + +wxString GUIPageLinks::Bool2Value(bool valueBool) +{ + wxString value; + if (valueBool) + { + value="TRUE"; + } + else + { + value="FALSE"; + } + + return (value); +} + +bool GUIPageLinks::Value2Bool(wxString &value) +{ + bool valueBool; + + valueBool = (value.CmpNoCase("TRUE")==0); + + return (valueBool); +} + +wxString GUIPageLinks::GetValue(wxString &id) +{ + wxString value; + int pageCount; + int pageIndex; + GUIWizardPageStatsgen *page; + wxString pageID; + int idLength; + + if (id.StartsWith("\"")) + { + value = id.AfterFirst('\"'); + value = value.BeforeLast('\"'); + } + else + { + idLength=id.Length(); + pageCount=guiPages.GetCount(); + for (pageIndex=0;pageIndexGetPageID(); + if (id.CmpNoCase(pageID.Right(idLength))==0) + { + // matching id found + value=page->GetValue(); + //wxMessageBox("Found Match"); + //wxMessageBox(value); + break; + } + } + } + + return (value); +} + +GUIWizardPagesFirstConfig::GUIWizardPagesFirstConfig() +{ +} + +GUIWizardPagesFirstConfig::~GUIWizardPagesFirstConfig() +{ +} + +void GUIWizardPagesFirstConfig::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wxString rule; + const char *titleChars="Test Run"; + + wizard = wizardIn; + pageServers.SetPageID("FULLCONFIG","SERVERS"); + pageServers.CreateWizardPages(wizard); + + pageWebsite.SetPageID("FULLCONFIG","WEBSITE"); + pageWebsite.CreateWizardPages(wizard); + + pageMessaging.SetPageID("FULLCONFIG","MESSAGING"); + pageMessaging.CreateWizardPages(wizard); + + pageTestRun = new GUIWizardPageRun(wizard,pageID,_T("TESTRUN")); + pageTestRun->SetSectionTitle(titleChars); + pageTestRun->SetHelp("[b]Press the button[/b] to perform an initial test run of the stats.\n" + "Once the run has completed a small amount of the stats pages will be " + "uploaded to your website in the directory you have configured.\n" + "\nYou will be missing images and style settings so the pages may look " + "a little rubbish at the moment - the image pack and style uploads " + "are in the next step"); + + rule.Printf("%s=\"TRUE\"",pageTestRun->GetPageID().GetData()); + wizard->AddPageLink(pageTestRun, "", rule); + pageImagePacks.SetPageID("FULLCONFIG","IMAGEPACKS"); + pageImagePacks.CreateWizardPages(wizard); +} + +GUIWizardPageRun::GUIWizardPageRun(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + statusCtrl = new wxStaticText(this,-1,"Test Not Run"); + errorCtrl = new wxRichTextCtrl(this,-1,""); + errorCtrl->SetEditable(false); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Test Stats Run"); + SetHelp("[b]Press the button[/b] to perform a stats run"); + progressPanel=new ProgressPanel; + progressPanel->Create(this,-1,wxDefaultPosition,wxDefaultSize, + wxRAISED_BORDER); + progressPanel->EnableTimeToGo(); + progressPanel->counterEnabled=true; + + progress->SetClone(NULL); + runSuccessful = false; +} + +GUIWizardPageRun::~GUIWizardPageRun() +{ + progress->SetClone(NULL); +} + +bool GUIWizardPageRun::TestResult() +{ + return (runSuccessful); +} + +wxString GUIWizardPageRun::GetValue() +{ + wxString retVal; + + if (TestResult()) + { + retVal="TRUE"; + } + else + { + retVal="FALSE"; + } + + return (retVal); +} + +void GUIWizardPageRun::SetTestParameters(bool testRun) +{ + wxString listGroup ="SERVERS"; + wxString listPrefix ="Server"; + wxString serverID; + wxArrayString serverIDs; + wxString serverConfigPrefix; + wxString configKey; + wxString configValue; + int serverCount; + int serverIndex; + int logfileLimit; + int roundsPerPlayer; + int playersPerRound; + long totalLogfileSize; + long logFileSize; + Server *server; + + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverCount=serverIDs.GetCount(); + for (serverIndex=0;serverIndexFindLogfiles(); + server->CreateLogFiles(); + logFileSize = server->LogfileSize(); + totalLogfileSize+=logFileSize; + } + roundsPerPlayer =0; + playersPerRound =0; + + if (totalLogfileSize > (1024 * 1024) * 10) + { + roundsPerPlayer =5; + playersPerRound =2; + } + if (totalLogfileSize > (1024 * 1024) * 30) + { + roundsPerPlayer =10; + playersPerRound =4; + } + if (totalLogfileSize > (1024 * 1024) * 50) + { + roundsPerPlayer =15; + playersPerRound =4; + } + if (totalLogfileSize > (1024 * 1024) * 70) + { + roundsPerPlayer =20; + playersPerRound =4; + } + if (totalLogfileSize > (1024 * 1024) * 90) + { + roundsPerPlayer =30; + playersPerRound =4; + } + } + configKey="/General/MinRoundsPerPlayer"; + configValue.Printf("%d",roundsPerPlayer); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/General/MinPlayersInRound"; + configValue.Printf("%d",playersPerRound); + globalStatistics.configData.WriteTextValue(configKey,configValue); +} + +void GUIWizardPageRun::SetSelection(const char *selection) +{ + statusCtrl->SetLabel(selection); +} + +bool GUIWizardPageRun::PerformTest() +{ + + SetTestParameters(true); + SetSelection("Test Running"); + + progress->EventUpdating(false); + progressPanel->EventUpdating(false); + progressPanel->ClearErrors(); + + { + wxBusyCursor cursor; + wizard->Enable(false); + + progress->SetClone(progressPanel); + globalStatistics.statsgenDatabase.OpenDB(); + globalStatistics.statsgenDatabase.Zap(); + globalStatistics.ReadServersFromConfig(); + globalStatistics.FlagStartOfRun(); + + progressPanel->ClearErrors(); + + globalStatistics.ProduceStatsInitiate(); + globalStatistics.ProduceStatsDownload(); + globalStatistics.ProduceStatsProcess(); + globalStatistics.ProduceStatsTransfer(); + globalStatistics.ProduceStatsFinalise(); + wizard->Enable(true); + globalStatistics.statsgenDatabase.OpenDB(); + globalStatistics.statsgenDatabase.Zap(); + } + SetSelection("Test Completed"); + progress->EventUpdating(true); + + runSuccessful = + (wxYES == wxMessageBox( + _T("Your initial stats run is now complete and the pages " + "have been uploaded to your website, check your website " + "to ensure you can see pages correctly.\nIf you see a red X " + "in the progress bar this generally indicates an error that " + "needs correcting, press the red X to get details of the " + "failure (you can ignore any errors regarding progressbar).\n " + "\n" + "remember your webpages won't have any style settings or " + "images yet so they may look a little odd.\n" + "\n" + "Press Yes if you see the stats pages."), + _T("Can you see pages?"), + wxYES_NO)); + + SetTestParameters(false); + + return (runSuccessful); +} + +void GUIWizardPageRun::OnButtonPressed(wxCommandEvent &event) +{ + PerformTest(); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +wxSize GUIWizardPageRun::ResizeControl(int x,int y,int width,bool resize) +{ + int statusX; + int statusY; + int statusWidth; + int statusHeight; + + int errorX; + int errorY; + int errorWidth; + int errorHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + + int progressX; + int progressY; + int progressWidth; + int progressHeight; + wxSize objectSize; + + wxSize controlSize; + + if (statusCtrl!=NULL) + { + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =y; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + progressX =x; + progressY =buttonY + buttonHeight; + progressWidth =width; + progressHeight =30; + + statusX =x; + statusY =progressY + progressHeight; + statusWidth =width; + statusHeight =30; + + errorX =x; + errorY =statusY + statusHeight; + errorWidth =width; + errorHeight =90; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + statusCtrl->SetSize(statusX,statusY,statusWidth,statusHeight); + errorCtrl->SetSize(errorX,errorY,errorWidth,errorHeight); + progressPanel->SetSize(progressX,progressY,progressWidth,progressHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + progressHeight + statusHeight + errorHeight); + } + + return (controlSize); +} + +void GUIWizardPageRun::ResetTestResult() +{ + statusCtrl->SetLabel("Test Not Run"); + errorCtrl->SetValue(""); +} + +GUIWizardPageImagePacks::GUIWizardPageImagePacks(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + imagesCtrl = new wxScrolledWindow(this, + -1, + wxDefaultPosition, + wxDefaultSize, + wxVSCROLL); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Upload Image Packs"); + SetHelp("[b]Press the button[/b] to perform a stats run"); + progressPanel=new ProgressPanel; + progressPanel->Create(this,-1,wxDefaultPosition,wxDefaultSize, + wxRAISED_BORDER); + progress->SetClone(NULL); + statsgenSite.GetImagePackList(fileDescriptions,filePaths,serverTypes,upgradeFiles,thumbnails); + CreateImagePackPanels(); + SelectImagePackPanels(); +} + +void GUIWizardPageImagePacks::CreateImagePackPanels() +{ + int imagePackCount; + int imagePackIndex; + ImagePackPanel *imagePackPanel; + wxString fileDescription; + wxString filePath; + wxString serverType; + wxString thumbnail; + wxString upgradeFile; + wxString msg; + + imagePackCount=fileDescriptions.GetCount(); + for (imagePackIndex=0;imagePackIndexGetServerType())==0) + { + imagePackPanel->SelectForUpload(); + } + } +} + +void GUIWizardPageImagePacks::SelectImagePackPanels() +{ + wxString listGroup ="SERVERS"; + wxString listPrefix ="Server"; + wxString groupPrefix; + wxString serverID; + int serverCount; + int serverIndex; + wxArrayString serverIDs; + wxString serverType; + wxString configKey; + + globalStatistics.configData.ReadList(listGroup,serverIDs); + serverCount=serverIDs.GetCount(); + for (serverIndex=0;serverIndexSetClone(NULL); +} + +wxString GUIWizardPageImagePacks::GetValue() +{ + wxString value="TRUE"; + + return (value); +} + +void GUIWizardPageImagePacks::OnButtonPressed(wxCommandEvent &event) +{ + int imagePackCount; + int imagePackIndex; + ImagePackPanel *imagePackPanel; + wxString filePath; + wxString fileDescription; + wxString upgradeFile; + wxBusyCursor busy; + bool storeLocally=false; + wxString localOutputFolder; + wxString configKey="/General/LocalOutput"; + + globalStatistics.configData.ReadTextValue(configKey,&localOutputFolder); + progress->SetClone(progressPanel); + imagePackCount=imagePackPanels.GetCount(); + wizard->Enable(false); + storeLocally=( + wxMessageBox("Store Image Packs Locally?","Confirm",wxYES_NO)==wxYES); + for (imagePackIndex=0;imagePackIndexSelected()) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); + filePath=imagePackPanel->GetFilePath(); + fileDescription=imagePackPanel->GetDescription(); + upgradeFile=imagePackPanel->GetUpgradeFile(); + statsgenSite.UploadImagePack(fileDescription,filePath,storeLocally,localOutputFolder,upgradeFile); + progress->Finalise(); + } + } + wizard->Enable(true); + + progress->SetClone(NULL); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +void GUIWizardPageImagePacks::ResizeImagePackPanels() +{ + int imagePackCount; + int imagePackIndex; + ImagePackPanel *imagePackPanel; + int x; + int y; + wxSize imagePackSize; + wxString msg; + int scrollRate=10; + int width=100; + + imagePackCount=imagePackPanels.GetCount(); + x=0; + y=0; + for (imagePackIndex=0;imagePackIndexResizeControl( + x,y, + imagePackSize.GetWidth(), + imagePackSize.GetHeight(), + false); + imagePackPanel->ResizeControl(x,y, + imagePackSize.GetWidth(), + imagePackSize.GetHeight(), + true); + y+=imagePackSize.GetHeight(); + y+=5; + width=imagePackSize.GetWidth(); + scrollRate=imagePackSize.GetHeight(); + } + imagesCtrl->SetScrollbars(1,1,width,y); + imagesCtrl->SetScrollRate(10,10); + imagesCtrl->SetVirtualSize(width,y); +} + +wxSize GUIWizardPageImagePacks::ResizeControl(int x,int y,int width,bool resize) +{ + int imagesX; + int imagesY; + int imagesWidth; + int imagesHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + + int progressX; + int progressY; + int progressWidth; + int progressHeight; + wxSize objectSize; + + wxSize controlSize; + + if (imagesCtrl!=NULL) + { + width =650; + + imagesX =x; + imagesY =y; + imagesWidth =width; + imagesHeight =300; + + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =imagesY+imagesHeight; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + progressX =x; + progressY =buttonY + buttonHeight; + progressWidth =width; + progressHeight =30; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + ResizeImagePackPanels(); + imagesCtrl->SetSize(imagesX,imagesY,imagesWidth,imagesHeight); + progressPanel->SetSize(progressX,progressY,progressWidth,progressHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + progressHeight + imagesHeight); + } + + return (controlSize); +} + +GUIWizardPagesImagePacks::GUIWizardPagesImagePacks() +{ + pageImagePacks = NULL; +} + +GUIWizardPagesImagePacks::~GUIWizardPagesImagePacks() +{ +} + +void GUIWizardPagesImagePacks::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wizard = wizardIn; + + const char *sectionTitle="Image Packs"; + pageImagePacks = new GUIWizardPageImagePacks(wizard,pageID,_T("IMAGEPACKS")); + + pageImagePacks->SetHelp( + "[b]Place a check[/b] in the appropriate image packs and then [b]press " + "the Upload button[/b] to download them from the statsgen website and " + "then upload them to your website" + ); + + + wizard->AddPageLink(pageImagePacks, "",""); + + pageImagePacks->SetSectionTitle(sectionTitle); + + ResizePages(); +} + +void GUIWizardPagesImagePacks::ResizePages() +{ + pageImagePacks->Resize(); +} + +ImagePackPanel::ImagePackPanel(wxWindow *parent, + wxString &fileDescriptionIn, + wxString &filePathIn, + wxString &serverTypeIn, + wxString &upgradeFileIn, + wxString &thumbnailIn) : wxPanel(parent,-1) +{ + wxString label=""; + wxString localimage="thumbnail."; + + fileDescription =fileDescriptionIn; + filePath =filePathIn; + serverType =serverTypeIn; + thumbnail =thumbnailIn; + upgradeFile =upgradeFileIn; + + if (thumbnail.EndsWith("jpg")) + { + localimage+="jpg"; + } + if (thumbnail.EndsWith("gif")) + { + localimage+="gif"; + } + checkCtrl =new wxCheckBox(this,-1,label); + descriptionCtrl =new wxStaticText(this,-1,fileDescription); + if (thumbnail.Length()>0) + { + StatsgenWeb statsgenSite; + WebFile *webFile; + + webFile=statsgenSite.GetWebFile(thumbnail); + webFile->Get(localimage); + thumbnailImage.LoadFile(localimage); + + delete(webFile); + } + thumbnailPanel =new ImagePanel(this,-1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("")); + thumbnailPanel->SetImage(thumbnailImage); +} + +ImagePackPanel::~ImagePackPanel() +{ +} + +wxString ImagePackPanel::GetServerType() +{ + return (serverType); +} +wxString ImagePackPanel::GetDescription() +{ + return (fileDescription); +} +wxString ImagePackPanel::GetFilePath() +{ + return (filePath); +} +wxString ImagePackPanel::GetUpgradeFile() +{ + return (upgradeFile); +} +bool ImagePackPanel::Selected() +{ + return (checkCtrl->GetValue()); +} +void ImagePackPanel::SelectForUpload() +{ + checkCtrl->SetValue(true); +} + +wxSize ImagePackPanel::ResizeControl(int x,int y,int width,int height,bool resize) +{ + wxSize panelSize; + wxSize objectSize; + + int panelX; + int panelY; + int panelWidth; + int panelHeight; + + int checkX; + int checkY; + int checkWidth; + int checkHeight; + + int thumbX; + int thumbY; + int thumbWidth; + int thumbHeight; + + int descriptionX; + int descriptionY; + int descriptionWidth; + int descriptionHeight; + int minImageWidth=325; + + objectSize =checkCtrl->GetSize(); + checkX =0; + checkY =0; + checkWidth =objectSize.GetWidth(); + checkHeight =objectSize.GetHeight(); + + thumbX =checkX+5+checkWidth; + thumbY =0; + thumbWidth =thumbnailImage.GetWidth(); + thumbHeight =thumbnailImage.GetHeight(); + + if (thumbWidthGetSize(); + descriptionX =thumbX+5+thumbWidth; + descriptionY =0; + descriptionWidth =objectSize.GetWidth(); + descriptionHeight =objectSize.GetHeight(); + + panelX =x; + panelY =y; + panelWidth =descriptionX+descriptionWidth; + if (checkHeight>descriptionHeight) + { + panelHeight =checkHeight; + } + else + { + panelHeight =descriptionHeight; + } + if (thumbHeight>panelHeight) + { + panelHeight=thumbHeight; + } + panelSize.SetWidth(panelWidth); + panelSize.SetHeight(panelHeight); + + if (resize) + { + checkCtrl->SetSize(checkX,checkY,checkWidth,checkHeight); + descriptionCtrl->SetSize(descriptionX,descriptionY,descriptionWidth,descriptionHeight); + thumbnailPanel->SetSize(thumbX,thumbY,thumbWidth,thumbHeight); + SetSize(panelX,panelY,panelWidth,panelHeight); + } + + return (panelSize); +} + +GUIWizardPagesMessaging::GUIWizardPagesMessaging() +{ + pageMessagingEnabled = NULL; + pageMessagingFrequency = NULL; + pageMessagingPort = NULL; +} + +GUIWizardPagesMessaging::~GUIWizardPagesMessaging() +{ +} + +void GUIWizardPagesMessaging::UpdateConfigKeys() +{ + wxString configKey; + wxString configValue; + + if (pageMessagingEnabled != NULL) + { + configKey="/RCONSettings/Enabled"; + pageMessagingEnabled->SetConfigKey(configKey,"Y"); + + configKey="/RCONSettings/MessageIntervalTimer"; + pageMessagingFrequency->SetConfigKey(configKey,"60"); + + configKey="/RCONSettings/ClientPort"; + pageMessagingPort->SetConfigKey(configKey,"8000"); + + configKey="/RCONSettings/CustomMessageInterval"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"0"); + + configKey="/RCONSettings/MessagePrefix"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"^7"); + } +} + +void GUIWizardPagesMessaging::CreateWizardPages(StatsgenWizard *wizardIn) +{ + const char *sectionTitle="Configure Messaging"; + wxString ruleMessagingEnabled; + + wizard=wizardIn; + + pageMessagingEnabled = new GUIWizardPageConfigBoolean(wizard,pageID,_T("ENABLED")); + pageMessagingFrequency = new GUIWizardPageConfigText(wizard,pageID,_T("FREQUENCY")); + pageMessagingPort = new GUIWizardPageConfigText(wizard,pageID,_T("PORT")); + + pageMessagingEnabled->SetConfigTitle("Enable Messaging"); + pageMessagingEnabled->SetHelp( + "Global Messaging Enabled / Disabled\n" + "This switches on / off messaging for the entire system, irrespective " + "of any individual server settings" + ); + pageMessagingEnabled->SetTrueFalseLabels("Yes", "No"); + + pageMessagingFrequency->SetConfigTitle("Message Frequency"); + pageMessagingFrequency->SetHelp( + "How often messages should be sent to the server, in seconds" + ); + + pageMessagingPort->SetConfigTitle("Messaging Client Port"); + pageMessagingPort->SetHelp( + "This is the local port used during communications with the game " + "servers.\n" + "You should have a [b]different value[/b] for this for every instance of " + "statsgen you are running.\n" + "[b]This is NOT the RCON port number[/b].\n" + "\nGood values are 8000, 8001, 8002" + ); + + pageMessagingEnabled->SetCallBack(ConfigChangedCallBack,this); + pageMessagingFrequency->SetCallBack(ConfigChangedCallBack,this); + pageMessagingPort->SetCallBack(ConfigChangedCallBack,this); + + ruleMessagingEnabled.Printf("(%s=\"%s\")", pageMessagingEnabled->GetPageID().GetData(),"Y"); + + wizard->AddPageLink(pageMessagingEnabled, "" ,""); + wizard->AddPageLink(pageMessagingFrequency, ruleMessagingEnabled ,""); + wizard->AddPageLink(pageMessagingPort, ruleMessagingEnabled ,""); + SetSectionTitle(sectionTitle); + + UpdateConfigKeys(); + + ResizePages(); +} + +void GUIWizardPagesMessaging::SetSectionTitle(const char *sectionTitle) +{ + pageMessagingEnabled->SetSectionTitle(sectionTitle); + pageMessagingFrequency->SetSectionTitle(sectionTitle); + pageMessagingPort->SetSectionTitle(sectionTitle); +} + +void GUIWizardPagesMessaging::ResizePages() +{ + pageMessagingEnabled->Resize(); + pageMessagingFrequency->Resize(); + pageMessagingPort->Resize(); +} + +void GUIWizardPagesMessaging::ConfigChangedCallBack(void *object) +{ + GUIWizardPagesMessaging *wizard; + wizard = (GUIWizardPagesMessaging *)object; +} + +GUIWizardPageTemplatePacks::GUIWizardPageTemplatePacks(StatsgenWizard *wizardIn,wxString parentPageID,wxString thisPageID) : GUIWizardPageStatsgen(wizardIn,parentPageID,thisPageID) +{ + imagesCtrl = new wxScrolledWindow(this, + -1, + wxDefaultPosition, + wxDefaultSize, + wxVSCROLL); + testButton = new wxButton(this,WINDOW_ID_BUTTON_NEW,"Upload Template Packs"); + SetHelp("[b]Press the button[/b] to perform a stats run"); + progressPanel=new ProgressPanel; + progressPanel->Create(this,-1,wxDefaultPosition,wxDefaultSize, + wxRAISED_BORDER); + progress->SetClone(NULL); + statsgenSite.GetTemplateList(fileDescriptions,filePaths,serverTypes,secondFilePaths,templateFilenames,upgradePaths,thumbnails); + CreateTemplatePackPanels(); + SelectTemplatePackPanels(); +} + +void GUIWizardPageTemplatePacks::CreateTemplatePackPanels() +{ + int imagePackCount; + int imagePackIndex; + TemplatePackPanel *imagePackPanel; + wxString fileDescription; + wxString filePath; + wxString secondFilePath; + wxString templateFilename; + wxString serverType; + wxString upgradePath; + wxString thumbnail; + wxString msg; + + imagePackCount=fileDescriptions.GetCount(); + for (imagePackIndex=0;imagePackIndexSetClone(NULL); +} + +wxString GUIWizardPageTemplatePacks::GetValue() +{ + wxString value="TRUE"; + + return (value); +} + +void GUIWizardPageTemplatePacks::OnButtonPressed(wxCommandEvent &event) +{ + int imagePackCount; + int imagePackIndex; + TemplatePackPanel *templatePackPanel; + wxString filePath; + wxString secondFilePath; + wxString upgradePath; + wxString templateFilename; + wxString fileDescription; + wxBusyCursor busy; + + progress->SetClone(progressPanel); + imagePackCount=templatePackPanels.GetCount(); + wizard->Enable(false); + for (imagePackIndex=0;imagePackIndexSelected()) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); + filePath=templatePackPanel->GetFilePath(); + secondFilePath=templatePackPanel->GetSecondFilePath(); + upgradePath=templatePackPanel->GetUpgradePath(); + templateFilename=templatePackPanel->GetTemplateFilename(); + fileDescription=templatePackPanel->GetDescription(); + statsgenSite.UploadTemplatePack(fileDescription,filePath,secondFilePath,upgradePath,templateFilename); + progress->Finalise(); + } + } + wizard->Enable(true); + + progress->SetClone(NULL); + if (callBack!=NULL) + { + callBack(callBackObject); + } + PageContentsChanged(); +} + +void GUIWizardPageTemplatePacks::ResizeTemplatePackPanels() +{ + int imagePackCount; + int imagePackIndex; + TemplatePackPanel *templatePackPanel; + int x; + int y; + wxSize imagePackSize; + wxString msg; + int scrollRate=10; + int width=100; + + imagePackCount=templatePackPanels.GetCount(); + x=0; + y=0; + for (imagePackIndex=0;imagePackIndexResizeControl( + x,y, + imagePackSize.GetWidth(), + imagePackSize.GetHeight(), + false); + templatePackPanel->ResizeControl(x,y, + imagePackSize.GetWidth(), + imagePackSize.GetHeight(), + true); + y+=imagePackSize.GetHeight(); + y+=5; + width=imagePackSize.GetWidth(); + scrollRate=imagePackSize.GetHeight(); + } + imagesCtrl->SetScrollbars(1,1,width,y); + imagesCtrl->SetScrollRate(10,10); + imagesCtrl->SetVirtualSize(width,y); +} + +wxSize GUIWizardPageTemplatePacks::ResizeControl(int x,int y,int width,bool resize) +{ + int imagesX; + int imagesY; + int imagesWidth; + int imagesHeight; + + int buttonX; + int buttonY; + int buttonWidth; + int buttonHeight; + + int progressX; + int progressY; + int progressWidth; + int progressHeight; + wxSize objectSize; + + wxSize controlSize; + + if (imagesCtrl!=NULL) + { + width =650; + + imagesX =x; + imagesY =y; + imagesWidth =width; + imagesHeight =300; + + objectSize = testButton->GetSize(); + buttonX =x; + buttonY =imagesY+imagesHeight; + buttonWidth =objectSize.GetWidth(); + buttonHeight =objectSize.GetHeight(); + + if (buttonWidth > width) + { + width = buttonWidth; + } + + progressX =x; + progressY =buttonY + buttonHeight; + progressWidth =width; + progressHeight =30; + + if (resize) + { + testButton->SetSize(buttonX,buttonY,buttonWidth,buttonHeight); + ResizeTemplatePackPanels(); + imagesCtrl->SetSize(imagesX,imagesY,imagesWidth,imagesHeight); + progressPanel->SetSize(progressX,progressY,progressWidth,progressHeight); + } + controlSize.SetWidth(width); + controlSize.SetHeight(buttonHeight + progressHeight + imagesHeight); + } + + return (controlSize); +} + +GUIWizardPagesTemplatePacks::GUIWizardPagesTemplatePacks() +{ + pageTemplatePacks = NULL; +} + +GUIWizardPagesTemplatePacks::~GUIWizardPagesTemplatePacks() +{ +} + +void GUIWizardPagesTemplatePacks::CreateWizardPages(StatsgenWizard *wizardIn) +{ + wizard = wizardIn; + + const char *sectionTitle="Template Packs"; + pageTemplatePacks = new GUIWizardPageTemplatePacks(wizard,pageID,_T("TEMPLATEPACKS")); + + pageTemplatePacks->SetHelp( + "[b]Place a check[/b] in the appropriate template and then [b]press " + "the Upload button[/b] to download them from the statsgen website and " + "then upload them to your website" + ); + + + wizard->AddPageLink(pageTemplatePacks, "",""); + + pageTemplatePacks->SetSectionTitle(sectionTitle); + + ResizePages(); +} + +void GUIWizardPagesTemplatePacks::ResizePages() +{ + pageTemplatePacks->Resize(); +} + +TemplatePackPanel::TemplatePackPanel(wxWindow *parent, + wxString &fileDescriptionIn, + wxString &filePathIn, + wxString &serverTypeIn, + wxString &secondFilePathIn, + wxString &upgradePathIn, + wxString &templateFilenameIn, + wxString &thumbnailIn) : wxPanel(parent,-1) +{ + wxString label=""; + wxString localimage="thumbnail."; + + fileDescription =fileDescriptionIn; + filePath =filePathIn; + serverType =serverTypeIn; + secondFilePath =secondFilePathIn; + templateFilename=templateFilenameIn; + upgradePath =upgradePathIn; + thumbnail =thumbnailIn; + + if (thumbnail.EndsWith("jpg")) + { + localimage+="jpg"; + } + if (thumbnail.EndsWith("gif")) + { + localimage+="gif"; + } + checkCtrl =new wxCheckBox(this,-1,label); + descriptionCtrl =new wxStaticText(this,-1,fileDescription); + if (thumbnail.Length()>0) + { + StatsgenWeb statsgenSite; + WebFile *webFile; + + webFile=statsgenSite.GetWebFile(thumbnail); + webFile->Get(localimage); + thumbnailImage.LoadFile(localimage); + + delete(webFile); + } + thumbnailPanel =new ImagePanel(this,-1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("")); + thumbnailPanel->SetImage(thumbnailImage); +} + +TemplatePackPanel::~TemplatePackPanel() +{ +} + +wxString TemplatePackPanel::GetServerType() +{ + return (serverType); +} +wxString TemplatePackPanel::GetDescription() +{ + return (fileDescription); +} +wxString TemplatePackPanel::GetFilePath() +{ + return (filePath); +} +wxString TemplatePackPanel::GetSecondFilePath() +{ + return (secondFilePath); +} +wxString TemplatePackPanel::GetUpgradePath() +{ + return (upgradePath); +} +wxString TemplatePackPanel::GetTemplateFilename() +{ + return (templateFilename); +} +bool TemplatePackPanel::Selected() +{ + return (checkCtrl->GetValue()); +} +void TemplatePackPanel::SelectForUpload() +{ + checkCtrl->SetValue(true); +} + +wxSize TemplatePackPanel::ResizeControl(int x,int y,int width,int height,bool resize) +{ + wxSize panelSize; + wxSize objectSize; + + int panelX; + int panelY; + int panelWidth; + int panelHeight; + + int checkX; + int checkY; + int checkWidth; + int checkHeight; + + int thumbX; + int thumbY; + int thumbWidth; + int thumbHeight; + + int descriptionX; + int descriptionY; + int descriptionWidth; + int descriptionHeight; + int minImageWidth=325; + + objectSize =checkCtrl->GetSize(); + checkX =0; + checkY =0; + checkWidth =objectSize.GetWidth(); + checkHeight =objectSize.GetHeight(); + + thumbX =checkX+5+checkWidth; + thumbY =0; + thumbWidth =thumbnailImage.GetWidth(); + thumbHeight =thumbnailImage.GetHeight(); + + if (thumbWidthGetSize(); + descriptionX =thumbX+5+thumbWidth; + descriptionY =0; + descriptionWidth =objectSize.GetWidth(); + descriptionHeight =objectSize.GetHeight(); + + panelX =x; + panelY =y; + panelWidth =descriptionX+descriptionWidth; + if (checkHeight>descriptionHeight) + { + panelHeight =checkHeight; + } + else + { + panelHeight =descriptionHeight; + } + if (thumbHeight>panelHeight) + { + panelHeight=thumbHeight; + } + panelSize.SetWidth(panelWidth); + panelSize.SetHeight(panelHeight); + + if (resize) + { + checkCtrl->SetSize(checkX,checkY,checkWidth,checkHeight); + descriptionCtrl->SetSize(descriptionX,descriptionY,descriptionWidth,descriptionHeight); + thumbnailPanel->SetSize(thumbX,thumbY,thumbWidth,thumbHeight); + SetSize(panelX,panelY,panelWidth,panelHeight); + } + + return (panelSize); +} + diff --git a/GUIWizards.h b/GUIWizards.h new file mode 100644 index 0000000..914e68b --- /dev/null +++ b/GUIWizards.h @@ -0,0 +1,851 @@ +#ifndef _GUIWIZARDS_H +#define _GUIWIZARDS_H + +#include +#include +#include +#include + +#include "WindowIDs.h" +#include "ProgressPanel.h" +#include "StatsgenWeb.h" +#include "ImagePanel.h" + +#define WIZARD_CHOICE_GAMESERVER "gameserver" +#define WIZARD_CHOICE_HOMEPC "homepc" + +#define WIZARD_CHOICE_NEW "New" +#define WIZARD_CHOICE_EDIT "Edit" +#define WIZARD_CHOICE_DELETE "Delete" + +class StatsgenWizard; +class GUIWizardPageStatsgen : public wxWizardPage +{ + public: + GUIWizardPageStatsgen(StatsgenWizard *wizardIn,wxString parentPageID,wxString pageID); + virtual ~GUIWizardPageStatsgen(); + virtual wxWizardPage *GetPrev() const; + virtual wxWizardPage *GetNext() const; + void SetPreviousPage(wxWizardPage *page); + void SetNextPage(wxWizardPage *page); + void SetHelp(const char *helpTextIn); + + void SetCallBack(void(* callBackIn)(void *object),void *callBackObjectIn ); + void SetPageCounter(int pageIndexIn,int pageCountIn); + void UpdateProgress(); + void Resize(int maxHeight=-1); + virtual bool AutoAdvance(); + void SetSectionTitle(const char *titleChars); + virtual wxString GetValue()=0; + wxString GetPageID(); + void PageContentsChanged(); + + StatsgenWizard *wizard; + protected: + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + + protected: + virtual void UpdateScreen(); + void (* callBack)(void *object); + void *callBackObject; + + int pageIndex; + int wizardPageCount; + + private: + wxWizardPage *previousPage; + wxWizardPage *nextPage; + wxString helpText; + wxRichTextCtrl *helpTextCtrl; + wxGauge *installProgress; + wxStaticText *sectionTitle; + wxString pageID; + +}; + +class GUIPageLinks +{ + public: + void AddPageLink(GUIWizardPageStatsgen *page, + const char *allowRule, + const char *continueRule); + void SetPageLinks(bool ignoreRules); + void SetPageCounters(); + GUIWizardPageStatsgen *GetFirstPage(); + void ResizePages(); + private: + GUIWizardPageStatsgen *FindPage(int pageIndex,int direction,bool ignoreRules); + bool EvaluateRule(wxString &rule,bool ignoreRules); + bool EvaluateRuleSub(wxString &rule); + void PushValue(wxArrayString &valueQueue,wxString &value); + wxString PopValue(wxArrayString &valueQueue); + int ValueCount(wxArrayString &valueQueue); + wxString Bool2Value(bool value); + bool Value2Bool(wxString &value); + wxString GetValue(wxString &id); + wxArrayPtrVoid guiPages; + wxArrayString allowRules; + wxArrayString continueRules; +}; + +class GUIWizardPageNull : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageNull(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageNull(); + virtual wxString GetValue(); + virtual bool AutoAdvance(); +}; + +class GUIWizardPageConfig : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageConfig(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfig(); + void SetConfigKey(wxString &configKeyIn,const char *defaultValueIn=NULL); + void SetDefault(const char *defaultValueIn); + void SetConfigTitle(const char *titleIn); + virtual void OnValueChanged(wxCommandEvent &event); + virtual wxString GetValue(); + virtual void UpdateValueFromConfig(); + void VetoCtrlUpdates(); + void AllowCtrlUpdates(); + bool CtrlUpdatesAllowed(); + protected: + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual void UpdateConfigFromValue(); + virtual void UpdateCtrlFromValue(); + virtual bool ConfigReady(); + virtual void UpdateScreen(); + + virtual bool ScreenReady()=0; + virtual void SetCtrlFromValue()=0; + virtual void SetValueFromCtrl()=0; + + wxString value; + wxString title; + wxString configKey; + wxString defaultValue; + private: + wxStaticText *titleCtrl; + bool vetoUpdates; +}; + +class GUIWizardPageConfigText : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigText(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigText(); + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + protected: + wxTextCtrl *valueCtrl; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageConfigBoolean : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigBoolean(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigBoolean(); + void SetTrueFalseLabels(const char *trueLabelIn,const char *falseLabelIn); + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + protected: + wxCheckBox *valueCtrl; + private: + wxString trueLabel; + wxString falseLabel; + void UpdateLabel(); + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageConfigFile : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigFile(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigFile(); + void OnButtonPressed(wxCommandEvent &event); + virtual void UpdateValueFromConfig(); + virtual void SplitValue(wxString &valueDirectory, + wxString &valueFilename)=0; + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + virtual void UpdateConfigFromValue(); + virtual wxString RequestFileFromUser()=0; + protected: + wxTextCtrl *valueCtrl; + wxButton *browseButton; + protected: + void GetConfigKeys(wxString &configDirectory, + wxString &configFilename); + virtual void CombineValue(); + + wxString directory; + wxString filename; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageConfigRemoteFile : public GUIWizardPageConfigFile +{ + public: + GUIWizardPageConfigRemoteFile(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigRemoteFile(); + virtual void SplitValue(wxString &valueDirectory, + wxString &valueFilename); + protected: + virtual wxString RequestFileFromUser(); + virtual void CombineValue(); +}; + +class GUIWizardPageConfigLocalFile : public GUIWizardPageConfigFile +{ + public: + GUIWizardPageConfigLocalFile(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual void SplitValue(wxString &valueDirectory, + wxString &valueFilename); + protected: + virtual wxString RequestFileFromUser(); + virtual void CombineValue(); +}; + +class GUIWizardPageConfigWildcard : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigWildcard(); + void OnButtonPressed(wxCommandEvent &event); + virtual void UpdateValueFromConfig(); + virtual wxString GetDirectoryFromUser()=0; + wxString GetWildcard(); + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + virtual void UpdateConfigFromValue(); + protected: + wxTextCtrl *valueCtrl; + wxTextCtrl *wildcardCtrl; + wxButton *browseButton; + wxString wildcardValue; + wxStaticText *directoryLabel; + wxStaticText *wildcardLabel; + private: + void GetConfigKeys(wxString &configDirectory, + wxString &configFilename); + + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageConfigLocalWildcard : public GUIWizardPageConfigWildcard +{ + public: + GUIWizardPageConfigLocalWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigLocalWildcard(); + virtual wxString GetDirectoryFromUser(); +}; + +class GUIWizardPageConfigRemoteWildcard : public GUIWizardPageConfigWildcard +{ + public: + GUIWizardPageConfigRemoteWildcard(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigRemoteWildcard(); + virtual wxString GetDirectoryFromUser(); +}; + +class GUIWizardPageConfigRemoteDirectory : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigRemoteDirectory(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageConfigRemoteDirectory(); + void OnButtonPressed(wxCommandEvent &event); + virtual void UpdateValueFromConfig(); + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + virtual void UpdateConfigFromValue(); + protected: + wxTextCtrl *valueCtrl; + wxButton *browseButton; + + DECLARE_EVENT_TABLE(); +}; + + +class GUIWizardPageConfigChoice : public GUIWizardPageConfig +{ + public: + GUIWizardPageConfigChoice(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID, + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn); + virtual ~GUIWizardPageConfigChoice(); + wxString TestResult(); + void OnButtonPressed(wxCommandEvent &event); + wxString GetChoice(); + protected: + virtual void CreateControl(); + virtual void SetCtrlFromValue(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + virtual bool ScreenReady(); + virtual void SetValueFromCtrl(); + public: + + void SetSelection(const char *selection); + void SetSelection(wxString &selection); + protected: + + wxArrayPtrVoid buttons; + wxArrayPtrVoid labels; + wxArrayString answerCodes; + wxArrayString buttonTexts; + wxArrayString buttonDescriptions; + wxTextCtrl *valueCtrl; + wxStaticText *selectionLabel; + + wxString choice; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageRemoteTest : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageRemoteTest(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageRemoteTest(); + void SetGroupPrefix(wxString &groupPrefixIn); + bool TestResult(); + bool PerformTest(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + void ResetTestResult(); + virtual wxString GetValue(); + + private: + wxStaticText *statusCtrl; + wxRichTextCtrl *errorCtrl; + wxButton *testButton; + + wxString groupPrefix; + private: + bool lastConnectionResult; + + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageRun : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageRun(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageRun(); + bool TestResult(); + bool PerformTest(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + void ResetTestResult(); + virtual wxString GetValue(); + void SetTestParameters(bool testRun); + void SetSelection(const char *selection); + + private: + wxStaticText *statusCtrl; + wxRichTextCtrl *errorCtrl; + wxButton *testButton; + ProgressPanel *progressPanel; + + private: + bool runSuccessful; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageImagePacks : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageImagePacks(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageImagePacks(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + virtual wxString GetValue(); + + private: + wxScrolledWindow *imagesCtrl; + wxButton *testButton; + ProgressPanel *progressPanel; + StatsgenWeb statsgenSite; + + private: + void CreateImagePackPanels(); + void SelectImagePackPanel(wxString &serverType); + void SelectImagePackPanels(); + void ResizeImagePackPanels(); + + private: + wxArrayString fileDescriptions; + wxArrayString filePaths; + wxArrayString serverTypes; + wxArrayString thumbnails; + wxArrayString upgradeFiles; + wxArrayPtrVoid imagePackPanels; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageRemoteFileTest : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageRemoteFileTest(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageRemoteFileTest(); + void SetGroupPrefix(wxString &groupPrefixIn); + bool TestResult(); + bool PerformTest(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + void ResetTestResult(); + void SetFile(wxString &fileDirectoryIn, wxString &fileNameIn); + virtual wxString GetValue(); + + private: + wxStaticText *statusCtrl; + wxRichTextCtrl *errorCtrl; + wxButton *testButton; + + wxString groupPrefix; + wxString fileDirectory; + wxString fileName; + private: + bool lastResult; + wxArrayString filenameList; + wxArrayInt filesizeList; + + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPageRemoteDirectoryTest : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageRemoteDirectoryTest(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageRemoteDirectoryTest(); + void SetGroupPrefix(wxString &groupPrefixIn); + bool TestResult(); + bool PerformTest(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + void ResetTestResult(); + void SetDirectory(wxString &fileDirectoryIn); + virtual wxString GetValue(); + + private: + wxStaticText *statusCtrl; + wxRichTextCtrl *errorCtrl; + wxButton *testButton; + + wxString groupPrefix; + wxString fileDirectory; + private: + bool lastResult; + + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPages +{ + public: + GUIWizardPages(); + virtual ~GUIWizardPages(); + void SetPageID(wxString parentID,wxString pageIDIn); + virtual void CreateWizardPages(StatsgenWizard *wizard)=0; + protected: + wxString pageID; + StatsgenWizard *wizard; +}; + +class GUIWizardPagesRemoteMachine : public GUIWizardPages +{ + public: + GUIWizardPagesRemoteMachine(); + virtual ~GUIWizardPagesRemoteMachine(); + void SetGroupPrefix(wxString &groupPrefixIn); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + static void ConfigChangedCallBack(void *callingObject); + void SetCallBack(void(* callBackIn)(void *object),void *callBackObjectIn ); + static void ConnectionTestCallBack(void *callingObject); + void SetSectionTitle(const char *titleChars); + void PopCallBack(); + + bool IsFTPEnabled(); + wxString GetEnabledPageID(); + + private: + void UpdateConfigKeys(); + void ConnectionTest(); + + private: + wxString groupPrefix; + GUIWizardPageConfigText *pageHostname; + GUIWizardPageConfigBoolean *pageEnabled; + GUIWizardPageConfigText *pageUsername; + GUIWizardPageConfigText *pagePassword; + GUIWizardPageConfigText *pageFTPPort; + GUIWizardPageConfigBoolean *pagePassive; + GUIWizardPageRemoteTest *pageTest; + + void (* callBack)(void *object); + void *callBackObject; +}; + +class GUIWizardPageChoice : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageChoice( + StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID, + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn); + virtual ~GUIWizardPageChoice(); + void UpdateChoices( + wxArrayString &answerCodesIn, + wxArrayString &buttonTextsIn, + wxArrayString &buttonDescriptionsIn); + wxString TestResult(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + wxString GetChoice(); + void SelectChoice(wxString &choiceIn); + virtual wxString GetValue(); + + public: + void SetSelection(const char *selection); + void SetSelection(wxString &selection); + private: + wxArrayPtrVoid buttons; + wxArrayPtrVoid labels; + wxArrayString answerCodes; + wxArrayString buttonTexts; + wxArrayString buttonDescriptions; + wxStaticText *selectedChoice; + wxStaticText *selectionLabel; + + wxString choice; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPagesServer : public GUIWizardPages +{ + public: + GUIWizardPagesServer(); + virtual ~GUIWizardPagesServer(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + void SetTestParameters(); + + void SetGroupPrefix(wxString &groupPrefixIn); + + void UpdateConfigKeys(); + static void ConfigChangedCallBack(void *callingObject); + void SetSectionTitle(const char *titleChars); + void PrepareServerConfig(); + void SetLogfileLimit(int limit); + void SetLogfileLimit(); + + private: + wxString groupPrefix; + GUIWizardPagesRemoteMachine remoteMachine; + GUIWizardPageConfigChoice *pageServerType; + GUIWizardPageConfigChoice *pageLocalOrRemote; + GUIWizardPageConfigBoolean *pageMessagingEnabled; + GUIWizardPageConfigText *pageRCONPassword; + GUIWizardPageConfigText *pageRCONPort; + GUIWizardPageConfigRemoteDirectory *pagePBRemoteDirectory; + GUIWizardPageRemoteDirectoryTest *pagePBRemoteDirectoryTest; + GUIWizardPageConfigRemoteFile *pageRemoteLatestFilename; + GUIWizardPageRemoteFileTest *pageRemoteLatestFilenameTest; + GUIWizardPageConfigRemoteFile *pageRemoteLatestSecondaryFilename; + GUIWizardPageRemoteFileTest *pageRemoteLatestSecondaryFilenameTest; + GUIWizardPageConfigRemoteWildcard *pageRemoteArchiveFilename; + GUIWizardPageRemoteFileTest *pageRemoteArchiveFilenameTest; + GUIWizardPageConfigLocalFile *pageLocalLatestFilename; + GUIWizardPageConfigLocalWildcard *pageLocalArchiveFilename; + GUIWizardPageConfigLocalFile *pageLocalLatestSecondaryFilename; + + int logfileLimit; +}; + +class GUIWizardPagesMessaging : public GUIWizardPages +{ + public: + GUIWizardPagesMessaging(); + virtual ~GUIWizardPagesMessaging(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + void SetSectionTitle(const char *sectionTitle); + static void ConfigChangedCallBack(void *object); + void UpdateConfigKeys(); + private: + GUIWizardPageConfigBoolean *pageMessagingEnabled; + GUIWizardPageConfigText *pageMessagingFrequency; + GUIWizardPageConfigText *pageMessagingPort; +}; + +class GUIWizardPagesServers : public GUIWizardPages +{ + public: + GUIWizardPagesServers(); + virtual ~GUIWizardPagesServers(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + + static void DeleteEditNewCallBack(void *callingObject); + static void ServerSelectedCallBack(void *callingObject); + void SetServerChoices(); + void SetDeleteEditNewChoices(); + void SelectServer(); + void SelectServer(wxString &prefix); + wxString GetDeleteEditNewChoice(); + void PrepareServerConfig(); + void SetLogfileLimit(); + void SetLogfileLimit(int limit); + + private: + GUIWizardPagesServer pageServer; + GUIWizardPageChoice *pageDeleteEditNew; + GUIWizardPageChoice *pageServerSelection; + + int logfileLimit; +}; + +class GUIWizardPagesWebsite : public GUIWizardPages +{ + public: + GUIWizardPagesWebsite(); + virtual ~GUIWizardPagesWebsite(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + + void UpdateConfigKeys(); + void SetGroupPrefix(); + static void ConfigChangedCallBack(void *callingObject); + void SetDirectory(); + + private: + GUIWizardPagesRemoteMachine remoteMachine; + GUIWizardPageConfigRemoteDirectory *pageRemoteDirectory; + GUIWizardPageRemoteDirectoryTest *pageRemoteDirectoryTest; + + wxString groupPrefix; +}; +class ImagePackPanel : wxPanel +{ + public: + ImagePackPanel(wxWindow *parent, + wxString &fileDescriptionIn, + wxString &filePathIn, + wxString &serverTypeIn, + wxString &upgradeFileIn, + wxString &thumbnailIn); + virtual ~ImagePackPanel(); + + wxString GetServerType(); + wxString GetDescription(); + wxString GetFilePath(); + wxString GetUpgradeFile(); + void SelectForUpload(); + bool Selected(); + wxSize ResizeControl(int x,int y,int width,int height,bool resize); + + private: + wxString fileDescription; + wxString filePath; + wxString serverType; + wxString thumbnail; + wxString upgradeFile; + wxCheckBox *checkCtrl; + wxStaticText *descriptionCtrl; + wxImage thumbnailImage; + ImagePanel *thumbnailPanel; +}; + +class GUIWizardPagesImagePacks : public GUIWizardPages +{ + public: + GUIWizardPagesImagePacks(); + virtual ~GUIWizardPagesImagePacks(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + + private: + GUIWizardPageImagePacks *pageImagePacks; + + +}; + +class GUIWizardPagesFullConfig : public GUIWizardPages +{ + public: + GUIWizardPagesFullConfig(); + virtual ~GUIWizardPagesFullConfig(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + + + private: + GUIWizardPagesServers pageServers; + GUIWizardPagesWebsite pageWebsite; + +}; + +class StatsgenWizard : public wxWizard +{ + public: + StatsgenWizard(wxWindow *parent, + int id = -1, + wxString &title = wxEmptyString, + const wxBitmap &bitmap=wxNullBitmap, + const wxPoint &pos = wxDefaultPosition, + long style = wxDEFAULT_DIALOG_STYLE); + void OnWizardPageChanged(wxWizardEvent &event); + void OnWizardFinish(wxWizardEvent &event); + void OnWizardCancel(wxWizardEvent &event); + void ResizePages(); + GUIPageLinks pageLinks; + void AddPageLink(GUIWizardPageStatsgen *page, + const char *allowRule, + const char *continueRule); + void UpdatePageLinks(bool fullList); + void PageContentsChanged(); + void SetInitialPageLinks(); + GUIWizardPageStatsgen *GetFirstPage(); + private: + bool initialised; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPagesFirstConfig : public GUIWizardPages +{ + public: + GUIWizardPagesFirstConfig(); + virtual ~GUIWizardPagesFirstConfig(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + + + private: + GUIWizardPagesServers pageServers; + GUIWizardPagesWebsite pageWebsite; + GUIWizardPagesMessaging pageMessaging; + GUIWizardPagesImagePacks pageImagePacks; + GUIWizardPageRun *pageTestRun; + +}; + +class GUIWizardPageTemplatePacks : public GUIWizardPageStatsgen +{ + public: + GUIWizardPageTemplatePacks(StatsgenWizard *wizard,wxString parentPageID,wxString thisPageID); + virtual ~GUIWizardPageTemplatePacks(); + virtual wxSize ResizeControl(int x,int y,int width,bool resize); + void OnButtonPressed(wxCommandEvent &event); + virtual wxString GetValue(); + + private: + wxScrolledWindow *imagesCtrl; + wxButton *testButton; + ProgressPanel *progressPanel; + StatsgenWeb statsgenSite; + + private: + void CreateTemplatePackPanels(); + void SelectTemplatePackPanel(wxString &serverType); + void SelectTemplatePackPanels(); + void ResizeTemplatePackPanels(); + + private: + wxArrayString fileDescriptions; + wxArrayString filePaths; + wxArrayString secondFilePaths; + wxArrayString templateFilenames; + wxArrayString serverTypes; + wxArrayString upgradePaths; + wxArrayString thumbnails; + wxArrayPtrVoid templatePackPanels; + + DECLARE_EVENT_TABLE(); +}; + +class GUIWizardPagesTemplatePacks : public GUIWizardPages +{ + public: + GUIWizardPagesTemplatePacks(); + virtual ~GUIWizardPagesTemplatePacks(); + virtual void CreateWizardPages(StatsgenWizard *wizard); + void ResizePages(); + + private: + GUIWizardPageTemplatePacks *pageTemplatePacks; + + +}; + +class TemplatePackPanel : wxPanel +{ + public: + TemplatePackPanel(wxWindow *parent, + wxString &fileDescriptionIn, + wxString &filePathIn, + wxString &serverTypeIn, + wxString &secondPathIn, + wxString &upgradePathIn, + wxString &templateFilenameIn, + wxString &thumbnailIn); + virtual ~TemplatePackPanel(); + + wxString GetServerType(); + wxString GetDescription(); + wxString GetFilePath(); + wxString GetUpgradePath(); + wxString GetSecondFilePath(); + wxString GetTemplateFilename(); + void SelectForUpload(); + bool Selected(); + wxSize ResizeControl(int x,int y,int width,int height,bool resize); + + private: + wxString fileDescription; + wxString filePath; + wxString upgradePath; + wxString secondFilePath; + wxString templateFilename; + wxString serverType; + wxString thumbnail; + wxCheckBox *checkCtrl; + wxStaticText *descriptionCtrl; + wxImage thumbnailImage; + ImagePanel *thumbnailPanel; +}; + +#endif diff --git a/GenericConfigGUI.cpp b/GenericConfigGUI.cpp new file mode 100644 index 0000000..1a73175 --- /dev/null +++ b/GenericConfigGUI.cpp @@ -0,0 +1,181 @@ +// Statsgen Includes +#include "GenericConfigGUI.h" +#include "GenericConfigPanel.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(GenericConfigGUI, wxDialog) + EVT_SIZE(GenericConfigGUI::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,GenericConfigGUI::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,GenericConfigGUI::OnQuit) +END_EVENT_TABLE() + +GenericConfigGUI::GenericConfigGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ + configPanel=NULL; + firstTimeResize=false; +} + +void GenericConfigGUI::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void GenericConfigGUI::OnSave(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +GenericConfigGUI::~GenericConfigGUI() +{ +} + +void GenericConfigGUI::SetConfigPanel(GenericConfigPanel *configPanelIn) +{ + configPanel=configPanelIn; +} + +void GenericConfigGUI::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxSizeEvent event; + GroupedConfigItemsPanel *configPanel; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + + + + OnResize(event); +} + +void GenericConfigGUI::DisplayDialog() +{ + int dialogRetVal; + + // Called when we want to pop the dialog box + // into existance for the first time + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + // We have been asked to save the changes + // just commit the config changes + globalStatistics.configData.CommitChanges(); + break; + case WINDOW_ID_BUTTON_QUIT: + default: + // We have been asked to quit without saving + // rollback the config changes + globalStatistics.configData.RollbackChanges(); + break; + } +} + +void GenericConfigGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + int configPanelWidth; + int configPanelHeight; + wxSize itemSize; + wxPoint itemPosition; + int yPosition; + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + configPanelHeight=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + configPanelWidth=dialogWidth; + + // Config Panel + yPosition=0; + // Config Panels resize themselves to fit + if (configPanel!=NULL) + { + itemSize=configPanel->GetSize(); + if (firstTimeResize) + { + configPanelHeight=itemSize.GetHeight(); + dialogHeight=configPanelHeight+ + saveHeight+ + DIALOG_BOTTOM_BORDER_SIZE; + } + configPanel->SetSize(0,yPosition,configPanelWidth, + configPanelHeight); + itemSize=configPanel->GetSize(); + if (firstTimeResize) + { + configPanelHeight=itemSize.GetHeight(); + dialogHeight=configPanelHeight+ + saveHeight+ + DIALOG_BOTTOM_BORDER_SIZE; + } + } + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x=saveWidth+BUTTON_WIDTH_GAP+BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + + if (firstTimeResize) + { + SetSize(dialogWidth,dialogHeight); + } + firstTimeResize=false; +} + diff --git a/GenericConfigGUI.h b/GenericConfigGUI.h new file mode 100644 index 0000000..87858b8 --- /dev/null +++ b/GenericConfigGUI.h @@ -0,0 +1,43 @@ +#ifndef __GENERICCONFIGGUI +#define __GENERICCONFIGGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" +#include "GenericConfigPanel.h" + +class GenericConfigGUI : public wxDialog +{ + public: + GenericConfigGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~GenericConfigGUI(); + + void OnQuit(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + void OnResize(wxSizeEvent& event); + + void DisplayDialog(); + void SetConfigPanel(GenericConfigPanel *configPanel); + + protected: + void CreateDialog(); + + private: + GenericConfigPanel *configPanel; + wxButton saveButton; + wxButton quitButton; + bool firstTimeResize; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GenericConfigPanel.cpp b/GenericConfigPanel.cpp new file mode 100644 index 0000000..bbb3d8a --- /dev/null +++ b/GenericConfigPanel.cpp @@ -0,0 +1,158 @@ +// Statsgen Includes +#include "GenericConfigPanel.h" +#include "GenericNumberedConfigPanel.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(GenericConfigPanel, wxPanel) + EVT_SIZE(GenericConfigPanel::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GenericConfigPanel::OnTextChange) +END_EVENT_TABLE() + +GenericConfigPanel::GenericConfigPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxPanel(parent, + id, + pos, + size, + style, + name) + +{ +} + +GenericConfigPanel::~GenericConfigPanel() +{ +} + +void GenericConfigPanel::AddConfigGroup(GroupedConfigItemsPanel *configPanel) +{ + wxSizeEvent dummy; + panelTypes.Add(1); + configItems.Add((void *)configPanel); + OnResize(dummy); +} + +void GenericConfigPanel::AddConfigGroup(wxPanel *configPanel) +{ + wxSizeEvent dummy; + panelTypes.Add(0); + configItems.Add((void *)configPanel); + OnResize(dummy); +} + +void GenericConfigPanel::AddConfigGroup(GenericNumberedConfigPanel *configPanel) +{ + wxSizeEvent dummy; + panelTypes.Add(2); + configItems.Add((void *)configPanel); + OnResize(dummy); +} + +bool GenericConfigPanel::UpdateFromTrigger() +{ + bool panelTriggered; + int panelCount; + int panelIndex; + int panelType; + + panelTriggered=false; + panelCount=configItems.GetCount(); + for (panelIndex=0;panelIndexUpdateFromTrigger()) + { + panelTriggered=true; + } + } + if (panelType==2) + { + GenericNumberedConfigPanel *configPanel; + configPanel=(GenericNumberedConfigPanel *)configItems.Item(panelIndex); + if (configPanel->UpdateFromTrigger()) + { + panelTriggered=true; + } + } + } + wxSizeEvent dummyEvent; + OnResize(dummyEvent); + return (panelTriggered); +} + +void GenericConfigPanel::OnTextChange(wxCommandEvent &event) +{ + UpdateFromTrigger(); +} + + +void GenericConfigPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + wxSize itemSize; + wxPoint itemPosition; + int configPanelHeight; + int configPanelWidth; + GroupedConfigItemsPanel *configPanel; + int configPanelCount; + int configPanelIndex; + int yPosition; + int panelType; + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + configPanelHeight=dialogHeight; + configPanelWidth=dialogWidth; + + // Config Panel + configPanelCount=configItems.GetCount(); + yPosition=0; + // Config Panels resize themselves to fit + for (configPanelIndex=0;configPanelIndexPreferredHeight(); + } + break; + case 2: + { + GenericNumberedConfigPanel *thisPanel; + thisPanel=(GenericNumberedConfigPanel *)configItems.Item(configPanelIndex); + configPanelHeight=dialogHeight-yPosition; + } + break; + default: + configPanelHeight=dialogHeight-yPosition; + break; + } + if (configPanelHeight<10) + { + configPanelHeight=10; + } + configPanel->SetSize(0,yPosition,configPanelWidth,configPanelHeight); + // Move to the next panel + yPosition+=configPanelHeight; + } +} + diff --git a/GenericConfigPanel.h b/GenericConfigPanel.h new file mode 100644 index 0000000..523d5ea --- /dev/null +++ b/GenericConfigPanel.h @@ -0,0 +1,40 @@ +#ifndef __GENERICCONFIGPANEL +#define __GENERICCONFIGPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" +#include "GenericNumberedConfigPanel.h" + +class GenericConfigPanel : public wxPanel +{ + public: + GenericConfigPanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~GenericConfigPanel(); + + void OnResize(wxSizeEvent& event); + + void AddConfigGroup(GroupedConfigItemsPanel *configPanel); + void AddConfigGroup(GenericNumberedConfigPanel *configPanel); + void AddConfigGroup(wxPanel *configPanel); + void OnTextChange(wxCommandEvent &event); + bool UpdateFromTrigger(); + + protected: + + private: + ArrayOfPointers configItems; + wxArrayInt panelTypes; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GenericKey.cpp b/GenericKey.cpp new file mode 100644 index 0000000..9062688 --- /dev/null +++ b/GenericKey.cpp @@ -0,0 +1,68 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "GenericKey.h" +#include "GlobalStatistics.h" + +GenericKey::GenericKey() +{ +} + +GenericKey::~GenericKey() +{ +} + +wxString GenericKey::SQLCreateTable(char *tableName) +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "idx integer," + "%s," + "%s," + "%s" + ")", + tableName, + StatsgenDatabase::StringFieldDefinition("id","generickeyid",FIELD_WIDTH_KEY_ID).GetData(), + StatsgenDatabase::StringFieldDefinition("realname","generickeyname",FIELD_WIDTH_KEY_REALNAME).GetData(), + StatsgenDatabase::StringFieldDefinition("image","generickeyimage",FIELD_WIDTH_KEY_IMAGE).GetData() + ); + + return SQL; +} + + +bool GenericKey::WriteToDatabase(char *tableName,int keyIndex) +{ + wxString SQL; + bool retVal=true; + wxString image; + wxString realName=""; + wxString configKey=""; + + if (id.Length()>0) + { + configKey.Printf("/Images/%s_%s",tableName,id.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&image,""); + configKey.Printf("/RealNames/%s_%s",tableName,id.GetData()); + globalStatistics.configData.ReadTextValue(configKey,&realName,(char *)id.GetData()); + } + + SQL.Printf("insert into %s" + "(idx,id,realname,image)" + "values" + "('%d','%s','%s','%s')", + tableName, + keyIndex, + StatsgenDatabase::SafeForInsert(id).GetData(), + StatsgenDatabase::SafeForInsert(realName).GetData(), + StatsgenDatabase::SafeForInsert(image).GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + + return retVal; +} + diff --git a/GenericKey.h b/GenericKey.h new file mode 100644 index 0000000..8ed546a --- /dev/null +++ b/GenericKey.h @@ -0,0 +1,26 @@ +#ifndef __GENERICKEY +#define __GENERICKEY + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class GenericKey; + +WX_DECLARE_OBJARRAY(GenericKey,ArrayOfGenericKey); +class GenericKey +{ + public: + GenericKey(); + virtual ~GenericKey(); + wxString id; + static wxString SQLCreateTable(char *tableName); + bool WriteToDatabase(char *tableName,int keyIndex); + +}; + + +#endif diff --git a/GenericNumberedConfigGUI.cpp b/GenericNumberedConfigGUI.cpp new file mode 100644 index 0000000..614dec2 --- /dev/null +++ b/GenericNumberedConfigGUI.cpp @@ -0,0 +1,338 @@ +// Statsgen Includes +#include "GenericNumberedConfigGUI.h" +#include "GenericConfigPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(GenericNumberedConfigGUI, wxDialog) + EVT_SIZE(GenericNumberedConfigGUI::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,GenericNumberedConfigGUI::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,GenericNumberedConfigGUI::OnQuit) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,GenericNumberedConfigGUI::OnNew) + EVT_BUTTON(WINDOW_ID_BUTTON_DELETE,GenericNumberedConfigGUI::OnDelete) + EVT_COMBOBOX(WINDOW_ID_LISTBOX_CONFIGITEMS,GenericNumberedConfigGUI::OnListItemSelected) +END_EVENT_TABLE() + +GenericNumberedConfigGUI::GenericNumberedConfigGUI( +// GenericConfigPanel * (*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + wxPanel * (*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + wxString &listGroupIn, + wxString &listGroupPrefixIn, + wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ + configPanel=NULL; + listGroup=listGroupIn; + listGroupPrefix=listGroupPrefixIn; + newPanelFunction=newPanelFunctionIn; +} + +void GenericNumberedConfigGUI::OnListItemSelected(wxCommandEvent& event) +{ + wxSizeEvent dummyEvent; + // we have a new selection + // remove the current panel (if present) and retrieve + // a new one using the retrieve function + wxString currentSelection; + + if (configPanel!=NULL) + { + // first remove the old panel + configPanel->Destroy(); + //delete(configPanel); + configPanel=NULL; + } + currentSelection=idList.GetValue(); + if (currentSelection.Length()>0) + { + configPanel=newPanelFunction(this,currentSelection); + //configPanel->OnResize(dummyEvent); + SetConfigPanel(configPanel); + } + OnResize(dummyEvent); +} + +void GenericNumberedConfigGUI::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void GenericNumberedConfigGUI::OnSave(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void GenericNumberedConfigGUI::WriteIDList() +{ + int idCount; + int idIndex; + wxArrayString ids; + wxString id; + + idCount=idList.GetCount(); + for (idIndex=0;idIndex0) + { + SafeString(chosen); + idList.Append(chosen); + idList.SetValue(chosen); + OnListItemSelected(dummyEvent); + WriteIDList(); + } +} + +void GenericNumberedConfigGUI::OnDelete(wxCommandEvent& event) +{ + wxString currentSelection; + wxString group; + int currentSelectionIndex; + wxCommandEvent dummyEvent; + int idCount; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("GenericNumberedConfigGUI","OnDelete") + currentSelection=idList.GetValue(); + + if (currentSelection.Length()>0) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,currentSelection) + currentSelectionIndex=idList.GetSelection(); +msg.Printf("currentSelectionIndex=%d",currentSelectionIndex); +STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (currentSelectionIndex!=wxNOT_FOUND) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Found it") + // delete the group from the config file + group=listGroupPrefix+currentSelection; + globalStatistics.configData.DeleteGroup(group); + + // delete the current selection from the id list + idList.Delete(currentSelectionIndex); + + // select another panel + idCount=idList.GetCount(); + if (idCount>0) + { + idList.SetSelection(0); + } + + // Need to force the selection event + OnListItemSelected(dummyEvent); + + // Write the ID List back to the config + WriteIDList(); + } + // Write the ID List to the config + } + STATSGEN_DEBUG_FUNCTION_END +} + +GenericNumberedConfigGUI::~GenericNumberedConfigGUI() +{ +} + +//void GenericNumberedConfigGUI::SetConfigPanel(GenericConfigPanel *configPanelIn) +void GenericNumberedConfigGUI::SetConfigPanel(wxPanel *configPanelIn) +{ + configPanel=configPanelIn; +} + +void GenericNumberedConfigGUI::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxCommandEvent event; + GroupedConfigItemsPanel *configPanel; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + wxArrayString ids; + wxString initialSelection=""; + + + globalStatistics.configData.ReadList(listGroup,ids); + + if (ids.GetCount()>0) + { + initialSelection=ids.Item(0); + } + idList.Create(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + initialSelection, + wxDefaultPosition, + wxDefaultSize, + ids, + wxCB_DROPDOWN | wxCB_READONLY | wxLB_SINGLE + ); + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT), + wxDefaultPosition); + deleteButton.Create(this, + WINDOW_ID_BUTTON_DELETE, + _T(WINDOW_ID_BUTTON_DELETE_TEXT), + wxDefaultPosition); + newButton.Create(this, + WINDOW_ID_BUTTON_NEW, + _T(WINDOW_ID_BUTTON_NEW_TEXT), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + + + + OnListItemSelected(event); +} + +void GenericNumberedConfigGUI::DisplayDialog() +{ + int dialogRetVal; + + // Called when we want to pop the dialog box + // into existance for the first time + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + // We have been asked to save the changes + // just commit the config changes + globalStatistics.configData.CommitChanges(); + break; + case WINDOW_ID_BUTTON_QUIT: + default: + // We have been asked to quit without saving + // rollback the config changes + globalStatistics.configData.RollbackChanges(); + break; + } +} + +void GenericNumberedConfigGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + int newWidth; + int newHeight; + int deleteWidth; + int deleteHeight; + int configPanelWidth; + int configPanelHeight; + wxSize itemSize; + wxPoint itemPosition; + int yPosition; + int listWidth; + int listHeight; + + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + itemSize=idList.GetSize(); + listWidth=itemSize.GetWidth(); + if (listWidth<150) + { + listWidth=150; + } + idList.SetSize(listWidth,listHeight); + listHeight=itemSize.GetHeight(); + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + itemSize=newButton.GetSize(); + newWidth=itemSize.GetWidth(); + newHeight=itemSize.GetHeight(); + + itemSize=deleteButton.GetSize(); + deleteWidth=itemSize.GetWidth(); + deleteHeight=itemSize.GetHeight(); + + configPanelHeight=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + configPanelWidth=dialogWidth; + + // ID List + idList.SetSize(0,0,listWidth,listHeight); + // Config Panel + yPosition=listHeight; + // Config Panels resize themselves to fit + if (configPanel!=NULL) + { + configPanel->SetSize(0,yPosition,configPanelWidth,configPanelHeight-listHeight); + } + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x+=(saveWidth+BUTTON_WIDTH_GAP); + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + + // new button + itemPosition.x+=(quitWidth+BUTTON_WIDTH_GAP); + itemPosition.y=dialogHeight-newHeight-DIALOG_BOTTOM_BORDER_SIZE; + newButton.SetPosition(itemPosition); + + // delete button + itemPosition.x+=(newWidth+BUTTON_WIDTH_GAP); + itemPosition.y=dialogHeight-deleteHeight-DIALOG_BOTTOM_BORDER_SIZE; + deleteButton.SetPosition(itemPosition); + +} + diff --git a/GenericNumberedConfigGUI.h b/GenericNumberedConfigGUI.h new file mode 100644 index 0000000..cffb1cf --- /dev/null +++ b/GenericNumberedConfigGUI.h @@ -0,0 +1,61 @@ +#ifndef __GENERICNUMBEREDCONFIGGUI +#define __GENERICNUMBEREDCONFIGGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" +#include "GenericConfigPanel.h" + +class GenericNumberedConfigGUI : public wxDialog +{ + public: + GenericNumberedConfigGUI( + wxPanel * (*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + //GenericConfigPanel * (*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + wxString &group, + wxString &listGroupPrefix, + wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~GenericNumberedConfigGUI(); + + void OnQuit(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + void OnNew(wxCommandEvent& event); + void OnDelete(wxCommandEvent& event); + void OnResize(wxSizeEvent& event); + void OnListItemSelected(wxCommandEvent &event); + + void DisplayDialog(); + //void SetConfigPanel(GenericConfigPanel *configPanel); + void SetConfigPanel(wxPanel *configPanel); + + protected: + void CreateDialog(); + + private: + void WriteIDList(); + wxComboBox idList; + //GenericConfigPanel * (*newPanelFunction)(wxWindow *parentID,wxString &listID); + wxPanel * (*newPanelFunction)(wxWindow *parentID,wxString &listID); + //GenericConfigPanel *configPanel; + wxPanel *configPanel; + wxButton saveButton; + wxButton quitButton; + wxButton newButton; + wxButton deleteButton; + wxString listGroup; + wxString listGroupPrefix; + bool firstTimeResize; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GenericNumberedConfigPanel.cpp b/GenericNumberedConfigPanel.cpp new file mode 100644 index 0000000..1d4116e --- /dev/null +++ b/GenericNumberedConfigPanel.cpp @@ -0,0 +1,162 @@ +// Statsgen Includes +#include "GenericNumberedConfigPanel.h" +#include "GenericConfigPanel.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(GenericNumberedConfigPanel, wxPanel) + EVT_SIZE(GenericNumberedConfigPanel::OnResize) + EVT_COMBOBOX(WINDOW_ID_LISTBOX_CONFIGITEMS,GenericNumberedConfigPanel::OnListItemSelected) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GenericNumberedConfigPanel::OnTextChange) +END_EVENT_TABLE() + +GenericNumberedConfigPanel::GenericNumberedConfigPanel( + GenericConfigPanel * (*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + wxString &listGroupIn, + wxString &listGroupPrefixIn, + wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxPanel(parent, + id, + pos, + size, + style, + name) + +{ + configPanel=NULL; + listGroup=listGroupIn; + listGroupPrefix=listGroupPrefixIn; + newPanelFunction=newPanelFunctionIn; +} + +bool GenericNumberedConfigPanel::UpdateFromTrigger() +{ + if (configPanel!=NULL) + { + configPanel->UpdateFromTrigger(); + } + return (true); +} + +void GenericNumberedConfigPanel::OnTextChange(wxCommandEvent &event) +{ + UpdateFromTrigger(); + if (GetParent()!=NULL) + { + GetParent()->AddPendingEvent(event); + } +} + + +void GenericNumberedConfigPanel::OnListItemSelected(wxCommandEvent& event) +{ + wxSizeEvent dummyEvent; + // we have a new selection + // remove the current panel (if present) and retrieve + // a new one using the retrieve function + wxString currentSelection; + + if (configPanel!=NULL) + { + // first remove the old panel + configPanel->Destroy(); + configPanel=NULL; + } + currentSelection=idList.GetValue(); + if (currentSelection.Length()>0) + { + configPanel=newPanelFunction(this,currentSelection); + configPanel->OnResize(dummyEvent); + SetConfigPanel(configPanel); + } + OnResize(dummyEvent); +} + +GenericNumberedConfigPanel::~GenericNumberedConfigPanel() +{ +} + +void GenericNumberedConfigPanel::SetConfigPanel(GenericConfigPanel *configPanelIn) +{ + configPanel=configPanelIn; +} + +void GenericNumberedConfigPanel::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxCommandEvent event; + GroupedConfigItemsPanel *configPanel; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + wxArrayString ids; + wxString initialSelection=""; + + + globalStatistics.configData.ReadList(listGroup,ids); + + if (ids.GetCount()>0) + { + initialSelection=ids.Item(0); + } + idList.Create(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + initialSelection, + wxDefaultPosition, + wxDefaultSize, + ids, + wxCB_DROPDOWN | wxCB_READONLY + ); + + OnListItemSelected(event); +} + +void GenericNumberedConfigPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int configPanelWidth; + int configPanelHeight; + wxSize itemSize; + wxPoint itemPosition; + int yPosition; + int listWidth; + int listHeight; + + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + itemSize=idList.GetSize(); + listWidth=itemSize.GetWidth(); + if (listWidth<150) + { + listWidth=150; + } + idList.SetSize(listWidth,listHeight); + listHeight=itemSize.GetHeight(); + + configPanelHeight=dialogHeight-listHeight; + configPanelWidth=dialogWidth; + + // ID List + idList.SetSize(0,0,listWidth,listHeight); + // Config Panel + yPosition=listHeight; + // Config Panels resize themselves to fit + if (configPanel!=NULL) + { + configPanel->SetSize(0,yPosition,configPanelWidth,configPanelHeight); + } + +} + diff --git a/GenericNumberedConfigPanel.h b/GenericNumberedConfigPanel.h new file mode 100644 index 0000000..310ed26 --- /dev/null +++ b/GenericNumberedConfigPanel.h @@ -0,0 +1,48 @@ +#ifndef __GENERICNUMBEREDCONFIGPANEL +#define __GENERICNUMBEREDCONFIGPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" + +class GenericConfigPanel; +class GenericNumberedConfigPanel : public wxPanel +{ + public: + GenericNumberedConfigPanel( + GenericConfigPanel *(*newPanelFunctionIn)(wxWindow *parentID,wxString &listID), + wxString &group, + wxString &listGroupPrefix, + wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~GenericNumberedConfigPanel(); + bool UpdateFromTrigger(); + + + void OnListItemSelected(wxCommandEvent &event); + void OnTextChange(wxCommandEvent &event); + void OnResize(wxSizeEvent &event); + + void CreateDialog(); + void SetConfigPanel(GenericConfigPanel *configPanel); + + protected: + + private: + wxComboBox idList; + GenericConfigPanel * (*newPanelFunction)(wxWindow *parentID,wxString &listID); + GenericConfigPanel *configPanel; + wxString listGroup; + wxString listGroupPrefix; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GenericOKCancelDialog.cpp b/GenericOKCancelDialog.cpp new file mode 100644 index 0000000..091b6d9 --- /dev/null +++ b/GenericOKCancelDialog.cpp @@ -0,0 +1,159 @@ +// Statsgen Includes +#include +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(GenericOKCancelDialog, wxDialog) + EVT_SIZE(GenericOKCancelDialog::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,GenericOKCancelDialog::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,GenericOKCancelDialog::OnQuit) +END_EVENT_TABLE() + +GenericOKCancelDialog::GenericOKCancelDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ + configPanel=NULL; +} + +void GenericOKCancelDialog::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void GenericOKCancelDialog::OnSave(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +GenericOKCancelDialog::~GenericOKCancelDialog() +{ +} + +void GenericOKCancelDialog::SetPanel(wxPanel *configPanelIn) +{ + configPanel=configPanelIn; +} + +void GenericOKCancelDialog::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxSizeEvent event; + wxPanel *configPanel; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + STATSGEN_DEBUG_FUNCTION_START("GenericOKCancelDialog","CreateDialog") + + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + + + + OnResize(event); + STATSGEN_DEBUG_FUNCTION_END +} + +bool GenericOKCancelDialog::DisplayDialog(wxPanel *panel) +{ + int dialogRetVal; + bool retVal; + + // Called when we want to pop the dialog box + // into existance for the first time + SetPanel(panel); + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + retVal=true; + break; + case WINDOW_ID_BUTTON_QUIT: + default: + retVal=false; + break; + } + + return (retVal); +} + +void GenericOKCancelDialog::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + int panelWidth; + int panelHeight; + wxSize itemSize; + wxPoint itemPosition; + int yPosition; + + STATSGEN_DEBUG_FUNCTION_START("GenericOKCancelDialog","OnResize") + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + panelHeight=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + panelWidth=dialogWidth; + + // Panel + yPosition=0; + configPanel->SetSize(0,yPosition,panelWidth,panelHeight); + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x=saveWidth+BUTTON_WIDTH_GAP+BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/GenericOKCancelDialog.h b/GenericOKCancelDialog.h new file mode 100644 index 0000000..2aa631d --- /dev/null +++ b/GenericOKCancelDialog.h @@ -0,0 +1,39 @@ +#ifndef __GENERICOKCANCELDIALOG +#define __GENERICOKCANCELDIALOG + +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" + +class GenericOKCancelDialog : public wxDialog +{ + public: + GenericOKCancelDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~GenericOKCancelDialog(); + + virtual void OnQuit(wxCommandEvent& event); + virtual void OnSave(wxCommandEvent& event); + virtual void OnResize(wxSizeEvent& event); + virtual void CreateDialog(); + + virtual bool DisplayDialog(wxPanel *panel); + void SetPanel(wxPanel *configPanel); + + protected: + + wxPanel *configPanel; + wxButton saveButton; + wxButton quitButton; + private: + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/GlobalStatistics.cpp b/GlobalStatistics.cpp new file mode 100644 index 0000000..f42d7f4 --- /dev/null +++ b/GlobalStatistics.cpp @@ -0,0 +1,2973 @@ +// wxWindows includes +#include + +// Statsgen includes +#include "GlobalStatistics.h" +#include "Player.h" +#include "GenericKey.h" +#include "TemplateFile.h" +#include "Server.h" +#include "Website.h" +#include "AwardDefinition.h" +#include "Progress.h" +#include "KillTotal.h" +#include "ExternalDatabase.h" +#include "AliasCacheEntry.h" +#include "Cheater.h" +#include "Version.h" + +GlobalStatistics globalStatistics; + +GlobalStatistics::GlobalStatistics() +{ + hiddenFeatures=false; + currentRunningThread=NULL; + aliasCacheEnabled=false; + aliasCache=NULL; + aliasPrimaryCache=NULL; + aliasCache=new ArrayOfAliasCacheEntry(AliasCacheEntry::Compare); + aliasPrimaryCache=new ArrayOfAliasCacheEntry(AliasCacheEntry::Compare); + + playerDataAvatars=new PlayerDataList("/General/PlayerDataFilenameAvatar", + "playerdataavatars", + "playerdataavatar.txt"); + playerDataWebsite=new PlayerDataList("/General/PlayerDataFilenameWebsite", + "playerdatawebsite", + "playerdatawebsite.txt"); + playerDataPicture=new PlayerDataList("/General/PlayerDataFilenamePicture", + "playerdatapicture", + "playerdatapicture.txt"); + playerDataXfire=new PlayerDataList("/General/PlayerDataFilenameXfire", + "playerdataxfire", + "playerdataxfire.txt"); + playerDataClanRole=new PlayerDataList("/General/PlayerDataFilenameClanRole", + "playerdataclanrole", + "playerdataclanrole.txt"); + + playerDataRealName=new PlayerDataList("/General/PlayerDataFilenameRealName", + "playerdatarealname", + "playerdatarealname.txt"); + playerDataMisc1=new PlayerDataList("/General/PlayerDataFilenameMisc1", + "playerdatamisc1", + "playerdatamisc1.txt"); + playerDataMisc2=new PlayerDataList("/General/PlayerDataFilenameMisc2", + "playerdatamisc2", + "playerdatamisc2.txt"); + // Read the schedule configs + //ReadScheduleConfig(); + FlagEndOfRun(); +} + +void GlobalStatistics::FlagStartOfRun() +{ + statsRunning = true; +} + +void GlobalStatistics::FlagEndOfRun() +{ + statsRunning = false; +} + +bool GlobalStatistics::AreStatsRunning() +{ + return (statsRunning); +} + +void GlobalStatistics::EmptyAliasCache() +{ + if (aliasCache!=NULL) + { + int aliasCacheCount; + int aliasCacheIndex; + AliasCacheEntry *cacheEntry; + aliasCacheCount=aliasCache->GetCount(); + for (aliasCacheIndex=0;aliasCacheIndexItem(aliasCacheIndex); + if (cacheEntry!=NULL) + { + delete cacheEntry; + } + } + + aliasCache->Clear(); + } + if (aliasPrimaryCache!=NULL) + { + int aliasCacheCount; + int aliasCacheIndex; + AliasCacheEntry *cacheEntry; + aliasCacheCount=aliasPrimaryCache->GetCount(); + for (aliasCacheIndex=0;aliasCacheIndexItem(aliasCacheIndex); + if (cacheEntry!=NULL) + { + delete cacheEntry; + } + } + + aliasPrimaryCache->Clear(); + } +} + +GlobalStatistics::~GlobalStatistics() +{ + if (aliasCache!=NULL) + { + EmptyAliasCache(); + delete aliasCache; + aliasCache=NULL; + } + if (aliasPrimaryCache!=NULL) + { + delete aliasPrimaryCache; + aliasPrimaryCache=NULL; + } + if (playerDataAvatars!=NULL) + { + delete playerDataAvatars; + } + if (playerDataPicture=NULL) + { + delete playerDataPicture; + } + if (playerDataWebsite!=NULL) + { + delete playerDataWebsite; + } + if (playerDataClanRole!=NULL) + { + delete playerDataClanRole; + } + if (playerDataXfire!=NULL) + { + delete playerDataXfire; + } + if (playerDataRealName!=NULL) + { + delete playerDataRealName; + } + if (playerDataMisc1!=NULL) + { + delete playerDataMisc1; + } + if (playerDataMisc2!=NULL) + { + delete playerDataMisc2; + } + ClearServers(); +} + +Player GlobalStatistics::GetPlayer(int index) +{ + Player player; + + //player=players.Item(index); + player=playerList.GetPlayer(index); + return(player); +} + +int GlobalStatistics::FindPlayerIndex(wxString &name) +{ + /* + int playerCount; + int playerIndex; + Player player; + int foundIndex=-1; + + playerCount=players.GetCount(); + for (playerIndex=0;playerIndexInitiate((long)rounds.GetCount(), + " rounds", + 1, + " rounds", + 1); + beginTransaction="begin"; + endTransaction="commit"; + statsgenDatabase.SimpleExecute(beginTransaction); + + skillWeights.WriteToDatabase(); + scoreWeights.WriteToDatabase(); + cheaters.WriteToDatabase(); + + keyCount=keysXP.GetCount(); + for (keyIndex=0;keyIndexWriteToDatabase(); + playerDataRealName->WriteToDatabase(); + playerDataPicture->WriteToDatabase(); + playerDataWebsite->WriteToDatabase(); + playerDataXfire->WriteToDatabase(); + playerDataClanRole->WriteToDatabase(); + playerDataMisc1->WriteToDatabase(); + playerDataMisc2->WriteToDatabase(); + + STATSGEN_DEBUG(DEBUG_ALWAYS,"Writing award definition") + awardCount=awardDefinitions.GetCount(); + for (awardIndex=0;awardIndexWriteToDatabase(clanIndex); + clans.Add(clan); + } + STATSGEN_DEBUG(DEBUG_ALWAYS,"Written clan definition") + + killTotalLists.WriteToDatabase(); + totalXP.WriteToDatabase(); + + // Write Server Info + STATSGEN_DEBUG(DEBUG_ALWAYS,"Writing server info") + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexWriteToDatabase(serverIndex); + //servers.Add(server); + } + + // Write AKA Info + STATSGEN_DEBUG(DEBUG_ALWAYS,"Writing AKA info") + AKACount=AKAList.GetCount(); + for (AKAIndex=0;AKAIndexUpdate((long)(roundIndex+1)); + STATSGEN_DEBUG_CODE(msg.Printf("Writing Round %d of %d to database", roundIndex+1,roundCount);) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + round=rounds.Item(roundIndex); + if ((roundIndex % 100)==0) + { + if (roundIndex!=0) + { + statsgenDatabase.SimpleExecute(endTransaction); + } + statsgenDatabase.SimpleExecute(beginTransaction); + } + round.WriteToDatabase(statsgenDatabase.NextRoundIndex()+roundIndex); + } + + if (roundCount!=0) + { + statsgenDatabase.SimpleExecute(endTransaction); + } + + // Update rounds and players based upon changed drop status + statsgenDatabase.WriteChangedPlayersList(droppedPlayersChanged); + statsgenDatabase.WriteChangedRoundsList(); + // update rounds and players based upon newly created rounds + statsgenDatabase.WriteChangedPlayersList(playersChanged); + statsgenDatabase.WriteChangedRoundsList(roundsChanged); + + //statsgenDatabase.CreateIndexes(); + STATSGEN_DEBUG_FUNCTION_END + return retVal; +} + +int GlobalStatistics::FindGUIDIndex(wxString &guid) +{ + return (playerList.FindGUIDIndex(guid)); + /* + int playerCount; + int playerIndex; + Player player; + int foundIndex=-1; + + playerCount=players.GetCount(); + for (playerIndex=0;playerIndexSetStatus(status); + configData.ReadTextValue(configKey,&configValue,"aliaslist.dat"); + aliasList.Clear(); + EmptyAliasCache(); + if (wxFileExists(configValue)) + { + retVal=fp.Open(configValue); + if (retVal) + { + aliasCount=fp.GetLineCount()/2; + progress->Initiate(aliasCount, + "", + (long)1, + "", + 1); + for (aliasIndex=0;aliasIndexUpdate(aliasIndex+1); + aliasListEntry.ReadFromFile(&fp,aliasIndex); + aliasList.Add(aliasListEntry); + AddToAliasCache(aliasCache, + aliasListEntry.aliasName, + aliasListEntry.aliasGUID, + aliasIndex); + AddToAliasCache(aliasPrimaryCache, + aliasListEntry.primaryName, + aliasListEntry.primaryGUID, + aliasIndex); + } + } + } +} + +void GlobalStatistics::WriteAliasList() +{ + AliasListEntry aliasListEntry; + int aliasCount; + int aliasIndex; + FILE *fp; + wxString configKey="/General/aliaslist"; + wxString configValue; + + configData.ReadTextValue(configKey,&configValue,"aliaslist.dat"); + fp=fopen(configValue.GetData(),"w"); + if (fp!=NULL) + { + aliasCount=aliasList.GetCount(); + for (aliasIndex=0;aliasIndexIndex(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + aliasCacheEntry=new AliasCacheEntry; + aliasCacheEntry->guid=guid; + aliasCacheEntry->name=name; + aliasCacheEntry->index=index; + cache->Add(aliasCacheEntry); + } +} + +void GlobalStatistics::AddAlias(AliasListEntry &aliasEntry) +{ + wxString msg; + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","AddAlias") + if ((aliasEntry.primaryGUID.Cmp(aliasEntry.aliasGUID)!=0) || + (aliasEntry.primaryName.Cmp(aliasEntry.aliasName)!=0)) + { + msg.Printf("primary [%s,%s] alias [%s,%s]", + aliasEntry.primaryGUID.GetData(), + aliasEntry.primaryName.GetData(), + aliasEntry.aliasGUID.GetData(), + aliasEntry.aliasName.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (!FindAlias(aliasEntry)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Alias does not already exist") + // alias does not already exist - so safe to add + aliasList.Add(aliasEntry); + if (aliasCacheEnabled) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Alias Cache Enabled") + AddToAliasCache(aliasCache, + aliasEntry.aliasName, + aliasEntry.aliasGUID, + aliasList.GetCount()-1); + AddToAliasCache(aliasPrimaryCache, + aliasEntry.primaryName, + aliasEntry.primaryGUID, + aliasList.GetCount()-1); + } + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +bool GlobalStatistics::FindAlias(AliasListEntry &aliasEntry) +{ + int count; + int index; + bool found; + AliasListEntry foundAliasEntry; + int foundIndex; + int searchIndex; + wxString msg; + + found=false; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","FindAlias") + + msg.Printf("finding alias for [%s,%s]", + aliasEntry.aliasGUID.GetData(), + aliasEntry.aliasName.GetData()); + STATSGEN_DEBUG(DEBUG_RARELY,msg); + + if (aliasCacheEnabled) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Alias Cache Enabled") + AliasCacheEntry searchKey; + searchKey.guid=aliasEntry.aliasGUID; + searchKey.name=aliasEntry.aliasName; + + // See if the alias is a primary name + searchIndex=aliasPrimaryCache->Index(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + found=false; + } + else + { + AliasCacheEntry *foundKey; + foundKey=aliasPrimaryCache->Item(searchIndex); + foundIndex=foundKey->index; + foundAliasEntry=aliasList.Item(foundIndex); + aliasEntry.primaryGUID=foundAliasEntry.primaryGUID; + aliasEntry.primaryName=foundAliasEntry.primaryName; + found=true; + } + if (!found) + { + // This is not a primary (already created) alias + // is it a child of a primary alias? + searchIndex=aliasCache->Index(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + found=false; + } + else + { + AliasCacheEntry *foundKey; + foundKey=aliasCache->Item(searchIndex); + foundIndex=foundKey->index; + foundAliasEntry=aliasList.Item(foundIndex); + aliasEntry.primaryGUID=foundAliasEntry.primaryGUID; + aliasEntry.primaryName=foundAliasEntry.primaryName; + found=true; + } + } + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Alias Cache Not Enabled") + count=aliasList.GetCount(); + for (index=0;indexDisableTimeToGo(); + progress->Initiate(topValue, + " Steps", + (long)1, + " Steps", + (long)1); + DropRounds(); + progress->Update(1); + DropPlayers(); + //progress->Update(2); + //DropInactiveRounds(); + progress->Update(3); + DropExistingPlayers(); + progress->Update(4); + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ProduceStats( + bool fullRun, + wxArrayInt &allowedSteps, + TemplateFile &templateFile) +{ + int serverCount; + int serverIndex; + wxString templateFilename; + wxString configKey; + wxString configValue; + Website website; + wxString msg; + bool result; + static time_t startTime; + + wxBusyCursor busyCursor; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ProduceStats") + configKey=AutomaticAliasConfigKey(); + configData.ReadTextValue(configKey,&configValue,"n"); + useAutomaticAliases=(configValue.CmpNoCase("y")==0); + + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS,allowedSteps)) + { + startTime=time(&startTime); + + progress->ClearErrors(); + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_GENERAL); + + // Make sure the group gets deleted + configData.DeleteGroup("MessageCentreValues"); + configData.CommitChanges(); + + configData.ReadList("BannedSpeech",bannedSpeech); + + ReadDeathmatchGametypes(); + ReadTeamSwapWeapons(); + skillWeights.Initiate("SkillWeights"); + scoreWeights.Initiate("ScoreWeights"); + if (fullRun) + { + // Make everything start from scratch + configKey="/Template/FullRun"; + OpenSpeechFile(); + } + else + { + configKey="/Template/QuickRun"; + } + configData.ReadTextValue(configKey,&templateFilename,""); + progress->LogError(templateFilename); + ReadAliasList(); + ReadAwardDefinitions(); + ReadClanDefinitions(); + dropList.Load(); + + progress->Finalise(); + InitiateSkillCalculationType(); + } + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexChoosePanel(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS); + } + if (StepAllowed(STEP_DOWNLOAD_LOGS)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Downloading files") + server->DownloadBanFiles(); + server->DownloadFiles(); + } + + if (serverIndex==(serverCount-1)) + { + progress->Finalise(); + } + } + } + + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS,allowedSteps)) + { + if (serverIndex==0) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS); + playerList.EnableCache(); + aliasCacheEnabled=true; + } + if (StepAllowed(STEP_CREATE_LOG_FILES)) + { + server->FindLogfiles(); + } + + if (fullRun) + { + server->ProcessBanFiles(); + } + + if (StepAllowed(STEP_CREATE_LOG_FILES)) + { + server->CreateLogFiles(); + } + + if (StepAllowed(STEP_PROCESS_LOG_FILES)) + { + server->ProcessLogFiles(serverIndex); + } + } + + //servers.Add(server); + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS,allowedSteps)) + { + if (serverIndex==(serverCount-1)) + { + progress->Finalise(); + playerList.DisableCache(); + aliasCacheEnabled=false; + } + } + } + + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS,allowedSteps)) + { + if (useAutomaticAliases) + { + WriteAliasList(); + } + if (fullRun) + { + CloseSpeechFile(); + dropList.Write(); + } + + // By now all the stats have been gathered together - we + // no longer need the server objects + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS); + if (StepAllowed(STEP_DROP_PLAYERS)) + { + // drop players who have not played enough rounds + DropPlayersAndRounds(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1); + if (StepAllowed(STEP_CALCULATE_SCORES)) + { + CalculateScores(); + } + progress->Finalise(); + + //Debug(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE); + if (StepAllowed(STEP_CREATE_DATABASE)) + { + statsgenDatabase.Create(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE); + if (StepAllowed(STEP_EMPTY_DATABASE)) + { + statsgenDatabase.Empty(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); + if (StepAllowed(STEP_WRITE_DATABASE)) + { + playerDataAvatars->ReadFromFile(); + playerDataRealName->ReadFromFile(); + playerDataWebsite->ReadFromFile(); + playerDataPicture->ReadFromFile(); + playerDataXfire->ReadFromFile(); + playerDataClanRole->ReadFromFile(); + playerDataMisc1->ReadFromFile(); + playerDataMisc2->ReadFromFile(); + WriteToDatabase(); + statsgenDatabase.WriteMiscellaneousStatistic("starttime",startTime); + statsgenDatabase.WriteMiscellaneousStatistic("roundsprocessed", + (int)rounds.GetCount()); + } + progress->Finalise(); + + } + + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE,allowedSteps)) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE); + if (StepAllowed(STEP_TRANSFER_DATABASE)) + { + if (fullRun) + { + ExternalDatabase externalDatabase; + externalDatabase.TransferFromInternal(); + } + } + progress->Finalise(); + } + + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE,allowedSteps)) + { + if (fullRun) + { + configKey="/Template/FullRun"; + } + else + { + configKey="/Template/QuickRun"; + } + configData.ReadTextValue(configKey,&templateFilename,""); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE); + progress->DisableTimeToGo(); + if (StepAllowed(STEP_READ_TEMPLATE)) + { + result=templateFile.ReadTemplate(templateFilename); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); + progress->DisableTimeToGo(); + if (StepAllowed(STEP_PROCESS_TEMPLATE)) + { + // Delete the existing message centre values +// templateFile.Debug(); + templateFile.Process(); + } + + if (StepAllowed(STEP_POST_PROCESS_TEMPLATE)) + { + PlayerListToPlayerCache(); + WritePlayerCache(); + } + + progress->Finalise(); + + } + if (ProcessStepAllowed(WINDOW_ID_PROGRESS_PANEL_WEBSITE,allowedSteps)) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); + if (StepAllowed(STEP_WEBSITE)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Website Transfer Step Allowed"); + // Now time to transfer to the website + if (fullRun) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Website Transfer Full Run"); + wxArrayString createdFiles; + + templateFile.GetCreatedFiles(createdFiles); + website.TransferFiles(createdFiles); + } + } + progress->Finalise(); + + // Commit any config changes made during production + configData.CommitChanges(); + // Reset the message centres with the newly produced stats + InitiateMessageCentres(); + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::CalculateScores() +{ + int roundCount; + int roundIndex; + Round currentRound; + Player *player; + wxString msg; + int playerCount; + int playerIndex; + int killCount; + int killIndex; + KillData killData; + int minRoundIndex; + int maxRoundIndex; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","CalculateScores") + roundCount=rounds.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("rounds=%d",roundCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + playerCount=playerList.GetCount(); + progress->Initiate( + (long)roundCount, + " Rounds", + 1, + " Rounds", + 1); + + for (roundIndex=0;roundIndexLogError(msg,SeverityCaution); + } + for (roundIndex=0;roundIndexUpdate((long)roundIndex+1); + currentRound=rounds.Item(0); + currentRound.CalculateScores(roundIndex); + // remove existing round and add it to the end of the list + // as we keep removing Round 0 it should add them back in order + rounds.RemoveAt(0); + rounds.Add(currentRound); + } + + progress->Finalise(); + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES2); + progress->Initiate( + (long)playerCount, + " Players", + 1, + " Players", + 1); + STATSGEN_DEBUG_CODE(msg.Printf("players=%d",playerCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + for (playerIndex=0;playerIndexUpdate((long)playerIndex+1); + player=playerList.Detach(0); + if (player->actualPlayerIndex < statsgenDatabase.NextPlayerIndex()) + { + // This player already exists so we need to gather the existing + // kill totals them from the DB + statsgenDatabase.UpdatePlayerKillTotals(playerIndex, + player->actualPlayerIndex, + killTotalLists.maps, + killTotalLists.gameTypes, + killTotalLists.weapons, + killTotalLists.locations, + killTotalLists.teams, + killTotalLists.classes); + + } + player->clanIndex=ClanIndex(player->name); + if(player->rounds>0) + { + player->scoreWeighted=((player->score)/((float)player->rounds)); + player->skillWeighted=((player->skill)/((float)player->rounds)); + } + else + { + player->scoreWeighted=0.0; + player->skillWeighted=0.0; + } + playerList.Add(player); + minRoundIndex=player->firstRoundPlayed; + maxRoundIndex=player->lastRoundPlayed; + if (minRoundIndex<0) + { + continue; + } + + if (minRoundIndex==-1) + { + minRoundIndex=0; + } + // Calculate Totals for this player + for (roundIndex=minRoundIndex; + roundIndex<=maxRoundIndex;roundIndex++) + { + currentRound=rounds.Item(roundIndex); + if (!currentRound.dropped) + { + killCount=currentRound.kills.GetCount(); + for (killIndex=0; + killIndexSetStatus(status); + awardDefinitions.Clear(); + + configData.ReadList("AWARDLIST",awardList); + awardCount=awardList.GetCount(); + for (awardIndex=0;awardIndexSetStatus(status); + configData.ReadList("SERVERS",serverIDs); + + // Match up the config server id's to the active server id's + configServerCount=serverIDs.GetCount(); + activeServerCount=servers.GetCount(); + if (activeServerCount==0) + { + for (configServerIndex=0; + configServerIndexSetID(configServerID); + server->Initiate(); + server->CreateLogFiles(); + servers.Add(server); + } + } + else + { + // servers have already been loaded don't do it again + } + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ReadClanDefinitions() +{ + wxArrayString clanList; + wxString clanID; + int clanIndex; + int clanCount; + wxString status; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ReadClanDefinitions") + status="Read Clan Definitions"; progress->SetStatus(status); + clans.Clear(); + + configData.ReadList("CLANS",clanList); + clanCount=clanList.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("CLAN COUNT READ=%d",clanCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + for (clanIndex=0;clanIndexIsMember(name)) + { + retVal=clanIndex; + } + } + } + + return (retVal); +} + +void GlobalStatistics::ReadScheduleConfig() +{ + ReadMessageTimerConfig(); + ReadQuickRunTimerConfig(); + ReadProductionRunTimerConfig(); +} + +void GlobalStatistics::ReadMessageTimerConfig() +{ + wxString configKey; + wxString configValue; + wxString interval; + + configKey="/RCONSettings/MessageIntervalTimer"; + configData.ReadTextValue(configKey,&interval,"60"); + messageTimer.IntervalStart(interval); +} + +void GlobalStatistics::ReadProductionRunTimerConfig() +{ + wxString configKey; + wxString configValue; + wxString baseTime; + wxString interval; + + configKey="/Schedule/ProductionRun"; + configData.ReadTextValue(configKey,&configValue,"00:00:00,86400"); + baseTime=configValue.BeforeFirst(','); + interval=configValue.AfterFirst(','); + productionRunTimer.ScheduledStart(baseTime,interval); +} + +void GlobalStatistics::ReadQuickRunTimerConfig() +{ + wxString configKey; + wxString configValue; + wxString interval; + + configKey="/Schedule/QuickRun"; + configData.ReadTextValue(configKey,&interval,"0"); + + quickRunTimer.IntervalStart(interval); +} + +bool GlobalStatistics::StepAllowed(const char *step) +{ + wxString configKey; + wxString configValue; + bool stepAllowed; + + configKey.Printf("/Debug/Step%s",step); + configData.ReadTextValue(configKey,&configValue,"y"); + stepAllowed=(configValue.CmpNoCase("y")==0); + + return (stepAllowed); +} + +void GlobalStatistics::ClearServers() +{ + int serverCount; + int serverIndex; + ResetProcessingStatus(); + + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexStartFromBeginning(); + //servers.Add(server); + } +} + +void GlobalStatistics::InitiateMessageCentres() +{ + int serverCount; + int serverIndex; + + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexInitiateMessageCentre(); + //servers.Add(server); + } +} + +void GlobalStatistics::SendMessages() +{ + int serverCount; + int serverIndex; + static bool firstTimeRun=true; + + if (firstTimeRun) + { + InitiateMessageCentres(); + firstTimeRun=false; + } + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexSendMessage(); + //servers.Add(server); + } +} + +void GlobalStatistics::ReadTeamSwapWeapons() +{ + int teamSwapCount; + wxString teamSwap; + + configData.ReadList("TEAMSWAP",teamSwapWeapons); + teamSwapCount=teamSwapWeapons.GetCount(); + if (teamSwapCount==0) + { + teamSwap="COD1_MOD_SUICIDE";teamSwapWeapons.Add(teamSwap); + teamSwap="COD2_MOD_SUICIDE";teamSwapWeapons.Add(teamSwap); + configData.WriteList("TEAMSWAP",teamSwapWeapons); + } +} + +void GlobalStatistics::ReadDeathmatchGametypes() +{ + int gametypeCount; + wxString gametype; + + configData.ReadList("DEATHMATCH",deathmatchGametypes); + gametypeCount=deathmatchGametypes.GetCount(); + if (gametypeCount==0) + { + gametype="COD1_dm";deathmatchGametypes.Add(gametype); + gametype="COD2_dm";deathmatchGametypes.Add(gametype); + configData.WriteList("DEATHMATCH",deathmatchGametypes); + } +} + +bool GlobalStatistics::IsDeathmatchGametype(wxString &gametypeSearch) +{ + int gametypeCount; + int gametypeIndex; + wxString gametype; + bool retVal=false; + + gametypeCount=deathmatchGametypes.GetCount(); + for (gametypeIndex=0;gametypeIndex0) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Speech File Opened") + speechfp=fopen(filename.GetData(),"a"); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::CloseSpeechFile() +{ + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","CloseSpeechFile") + if (speechfp!=NULL) + { + fclose(speechfp); + } + speechfp=NULL; + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::WriteSpeechFile( + wxDateTime &speechTime, + wxString &guid, + wxString &playername, + wxString &speech + ) +{ + wxString timeString; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","WriteSpeechFile") + + timeString=speechTime.Format("%d/%m/%Y %H:%M:%S"); + if (speechfp!=NULL) + { + STATSGEN_DEBUG(DEBUG_RARELY,speech) + fprintf(speechfp,"%s %32s (%s): %s\n", + timeString.GetData(), + playername.GetData(), + guid.GetData(), + speech.GetData()); + } + STATSGEN_DEBUG_FUNCTION_END +} + +wxString GlobalStatistics::SkillCalculationTypeConfigKey() +{ + wxString configKey="/General/AllowNegativeSkill"; + + return (configKey); +} + +void GlobalStatistics::InitiateSkillCalculationType() +{ + wxString configKey; + wxString configValue; + + configKey=SkillCalculationTypeConfigKey(); + + configData.ReadTextValue(configKey,&configValue,"y"); + negativeSkillAllowed=(configValue.CmpNoCase("y")==0); +} + +bool GlobalStatistics::AllowNegativeSkill() +{ + return (negativeSkillAllowed); +} + +void GlobalStatistics::GenerateUpgrade(wxString &filename) +{ + wxFileName iniFilename(filename); + ConfigData upgradeConfigData; + wxArrayString awardIDs; + wxString awardID; + wxString description; + int awardCount; + int awardIndex; + wxString awardKey; + wxString configKey; + wxArrayString upgradeList; + wxString configValue; + + upgradeList.Clear(); + upgradeConfigData.Initiate(iniFilename); + configKey="/UPGRADELIST/Description"; + configValue.Printf("Full Upgrade File for Statsgen Version %s",PROGRAM_VERSION); + upgradeConfigData.WriteTextValue(configKey,configValue); + + configKey="/UPGRADELIST/UpgradeType"; + configValue=UPGRADE_TYPE_CONFIG; + upgradeConfigData.WriteTextValue(configKey,configValue); + + configData.ReadList("AWARDLIST",awardIDs); + awardCount=awardIDs.GetCount(); + upgradeConfigData.Export(upgradeList,configData,"Which Gametypes Are Deathmatch","DEATHMATCH",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Overwrite"); + upgradeConfigData.Export(upgradeList,configData,"Which Weapons Are Team Swap","TEAMSWAP",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Overwrite"); + upgradeConfigData.Export(upgradeList,configData,"MOHAA Line Identification","LINEIDMOHAA",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Overwrite"); + upgradeConfigData.Export(upgradeList,configData,"Wolfenstein Line Identification","LINEIDWOLFENSTEIN",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Overwrite"); + upgradeConfigData.Export(upgradeList,configData,"Which GUIDs should not be auto aliased","AutoAliasBlockedGUIDS",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Overwrite"); + upgradeConfigData.Export(upgradeList,configData,"RCON Message Formats","MessageCentreFormats",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Do Nothing"); + upgradeConfigData.Export(upgradeList,configData,"Award Definitions","AWARDLIST",CONFIG_EXPORT_SET_ONLY,CONFIG_ANSWER_TYPE_ASK,"Do Nothing"); + for (awardIndex=0;awardIndexRecoveryMode(); + if (!recoveryMode) + { + progress->ClearErrors(); + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_GENERAL); + + configKey=AutomaticAliasConfigKey(); + configData.ReadTextValue(configKey,&configValue,"n"); + useAutomaticAliases=(configValue.CmpNoCase("y")==0); + + + + // Make sure the group gets deleted + configData.DeleteGroup("MessageCentreValues"); + configData.CommitChanges(); + + configData.ReadList("BannedSpeech",bannedSpeech); + + ReadDeathmatchGametypes(); + ReadTeamSwapWeapons(); + skillWeights.Initiate("SkillWeights"); + scoreWeights.Initiate("ScoreWeights"); + + OpenSpeechFile(); + ReadAliasList(); + ReadAwardDefinitions(); + ReadClanDefinitions(); + dropList.Load(); + + InitiateSkillCalculationType(); + + ClearServers(); + ReadServersFromConfig(); + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE); + if (StepAllowed(STEP_CREATE_DATABASE)) + { + statsgenDatabase.Create(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_APPLY_ALIASES); + if (StepAllowed(STEP_APPLY_ALIASES)) + { + statsgenDatabase.ApplyAliases(playersChanged); + UpdateExistingPlayersClan(); + } + progress->Finalise(); + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ProduceStatsDownload() +{ + int serverCount; + int serverIndex; + Server *server; + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ProduceStatsDownload") + + if (!recoveryMode) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS); + if (StepAllowed(STEP_DOWNLOAD_LOGS)) + { + serverCount=servers.GetCount(); + for (serverIndex=0;serverIndexDownloadBanFiles(); + server->DownloadFiles(); + } + } + progress->Finalise(); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ProduceStatsProcess() +{ + int serverCount; + int serverIndex; + Server *server; + wxString configKey; + wxString templateFilename; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ProduceStatsProcess") + + if (!recoveryMode) + { + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DATABASE_READ_STATIC); + if (StepAllowed(STEP_DATABASE_READ_STATIC)) + { + ReadStaticItemsFromDatabase(); + statsgenDatabase.UpdatePlayerCount(); + statsgenDatabase.UpdateRoundCount(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE); + if (StepAllowed(STEP_EMPTY_DATABASE)) + { + statsgenDatabase.Empty(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS); + if (StepAllowed(STEP_PROCESS_LOG_FILES)) + { + serverCount=servers.GetCount(); + + playerList.EnableCache(); + aliasCacheEnabled=true; + + for (serverIndex=0;serverIndexProcessBanFiles(); + server->FindLogfiles(); + server->CreateLogFiles(); + server->AdjustLogfilePosition(); + } + for (serverIndex=0;serverIndexProcessLogFiles(serverIndex); + } + playerList.DisableCache(); + aliasCacheEnabled=false; + if (useAutomaticAliases) + { + WriteAliasList(); + } + CloseSpeechFile(); + dropList.Write(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DATABASE_LOCATE_EXISTING_PLAYERS); + if (StepAllowed(STEP_DATABASE_LOCATE_EXISTING_PLAYERS)) + { + LocateExistingPlayers(); + } + progress->Finalise(); + // By now all the stats have been gathered together - we + // no longer need the server objects + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS); + if (StepAllowed(STEP_DROP_PLAYERS)) + { + // drop players who have not played enough rounds + DropPlayersAndRounds(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1); + if (StepAllowed(STEP_CALCULATE_SCORES)) + { + CalculateScores(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); + if (StepAllowed(STEP_WRITE_DATABASE)) + { + playerDataAvatars->ReadFromFile(); + playerDataRealName->ReadFromFile(); + playerDataWebsite->ReadFromFile(); + playerDataPicture->ReadFromFile(); + playerDataXfire->ReadFromFile(); + playerDataClanRole->ReadFromFile(); + playerDataMisc1->ReadFromFile(); + playerDataMisc2->ReadFromFile(); + WriteToDatabase(); + statsgenDatabase.WriteMiscellaneousStatistic("starttime",startTime); + statsgenDatabase.WriteMiscellaneousStatistic("roundsprocessed", + (int)rounds.GetCount()); + statsgenDatabase.Optimize(); + } + progress->Finalise(); + } + + configKey="/Template/FullRun"; + configData.ReadTextValue(configKey,&templateFilename,""); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE); + progress->DisableTimeToGo(); + if (StepAllowed(STEP_READ_TEMPLATE)) + { + templateFile.ReadTemplate(templateFilename); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); + progress->DisableTimeToGo(); + if (StepAllowed(STEP_PROCESS_TEMPLATE)) + { + templateFile.Process(); + } + + if (StepAllowed(STEP_POST_PROCESS_TEMPLATE)) + { + PlayerListToPlayerCache(); + WritePlayerCache(); + } + + progress->Finalise(); + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ProduceStatsTransfer() +{ + Website website; + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ProduceStatsTransfer") + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE); + if (StepAllowed(STEP_TRANSFER_DATABASE)) + { + ExternalDatabase externalDatabase; + externalDatabase.TransferFromInternal(); + } + progress->Finalise(); + + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); + if (StepAllowed(STEP_WEBSITE)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Website Transfer Step Allowed"); + // Now time to transfer to the website + STATSGEN_DEBUG(DEBUG_ALWAYS,"Website Transfer Full Run"); + wxArrayString createdFiles; + + templateFile.GetCreatedFiles(createdFiles); + website.TransferFiles(createdFiles); + } + progress->Finalise(); + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ProduceStatsFinalise() +{ + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","ProduceStatsFinalise") + configData.CommitChanges(); + // Reset the message centres with the newly produced stats + ClearServers(); + ReadServersFromConfig(); + InitiateMessageCentres(); + configData.CloseWeaponGroupCache(); + FlagEndOfRun(); + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::ReadGenericKeyFromDatabase(ArrayOfGenericKey &keyList, + const char *tableName) +{ + TemplateOpenQuery query; + wxString sql; + wxString property; + wxString id; + GenericKey key; + + keyList.Clear(); + property="id"; + + sql.Printf("select * from %s order by idx asc", tableName); + query.Initiate(sql,statsgenDatabase.DBHandle()); + while (query.NextRow()) + { + id=query.RetrieveProperty(property); + key.id=id; + keyList.Add(key); + } +} + +void GlobalStatistics::ReadStaticItemsFromDatabase() +{ + ReadGenericKeyFromDatabase(keysAction, TABLE_NAME_KEY_ACTION); + ReadGenericKeyFromDatabase(keysAmmo, TABLE_NAME_KEY_AMMO); + ReadGenericKeyFromDatabase(keysMap, TABLE_NAME_KEY_MAP); + ReadGenericKeyFromDatabase(keysWeapon, TABLE_NAME_KEY_WEAPON); + ReadGenericKeyFromDatabase(keysClass, TABLE_NAME_KEY_CLASS); + ReadGenericKeyFromDatabase(keysTeam, TABLE_NAME_KEY_TEAM); + ReadGenericKeyFromDatabase(keysGametype, TABLE_NAME_KEY_GAMETYPE); + ReadGenericKeyFromDatabase(keysLocation, TABLE_NAME_KEY_LOCATION); + ReadGenericKeyFromDatabase(keysXP, TABLE_NAME_KEY_XP); + scoreWeights.ReadFromDatabase(); + skillWeights.ReadFromDatabase(); +} + +void GlobalStatistics::LocateExistingPlayers() +{ + int playerCount; + int playerIndex; + Player *player; + int databasePlayerCount; + int newPlayerIndex; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","LocateExistingPlayers") + + databasePlayerCount=statsgenDatabase.NextPlayerIndex(); + newPlayerIndex=databasePlayerCount; + playerCount=playerList.GetCount(); + msg.Printf("db count=%d playercount=%d",databasePlayerCount,playerCount); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->Initiate(playerCount," players", 1, "players ", 1); + for (playerIndex=0;playerIndexUpdate(playerIndex); + msg.Printf("playerindex=%d newplayerIndex=%d",playerIndex,newPlayerIndex); + STATSGEN_DEBUG(DEBUG_RARELY,msg); + player=playerList.Detach(0); + if (!player->UpdateFromDatabase(newPlayerIndex)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"not from db") + newPlayerIndex++; + } + playersChanged.Add(player->actualPlayerIndex); + playerList.Add(player); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::DropExistingPlayers() +{ + wxArrayInt newlyDroppedPlayers; + wxArrayInt newlyInstatedPlayers; + wxString sql; + TemplateOpenQuery query; + wxString propertyName="name"; + wxString propertyRounds="rounds"; + wxString propertyPlayerIndex="playerindex"; + wxString propertyDropped="dropped"; + wxString name; + int rounds; + int playerIndex; + bool dropped; + bool dbDropped; + Player player; + wxString minRoundsPerPlayerString; + int minRoundsPerPlayer; + bool cheat; + wxString msg; + int worldPlayerIndex=-1; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","DropExistingPlayers") + name=WORLD_PLAYER_NAME; + sql.Printf("update player set dropped='Y' where name='%s'",StatsgenDatabase::SafeForInsert(name).GetData()); + statsgenDatabase.SimpleExecute(sql); + globalStatistics.configData.ReadTextValue( + "/General/MinRoundsPerPlayer", + &minRoundsPerPlayerString, + "1"); + + minRoundsPerPlayer=atoi(minRoundsPerPlayerString.GetData()); + + sql="select * from player"; + + query.Initiate(sql,statsgenDatabase.DBHandle()); + while (query.NextRow()) + { + name=query.RetrieveProperty(propertyName); + if (name.Cmp(WORLD_PLAYER_NAME)==0) + { + continue; + } + cheat=false; + rounds=atoi(query.RetrieveProperty(propertyRounds).GetData()); + dbDropped=(query.RetrieveProperty(propertyDropped).CmpNoCase("Y")==0); + playerIndex=atoi(query.RetrieveProperty(propertyPlayerIndex).GetData()); + player.name=name; + player.rounds=rounds; + dropped=(rounds<=minRoundsPerPlayer) || dropList.IsDropped(name,&cheat); + msg.Printf( + "dbDropped=[%d],dropped=[%d],playerIndex=[%d],name=[%s],rounds=[%d],minRounds=[%d]", + dbDropped, + dropped, + playerIndex, + name.GetData(), + rounds, + minRoundsPerPlayer); +STATSGEN_DEBUG(DEBUG_RARELY,msg) + if (cheat) + { + // This existing player has been classified as a cheat + // We need to drop existing cheats complete from the stats + // Adjusting the scores of anybody affected by the cheats + DropExistingCheat(playerIndex,worldPlayerIndex); + cheaters.Add(name); + } + else + { + if (dropped != dbDropped) + { + // this player was dropped but isn't now - or vice versa + if (dropped) + { + newlyDroppedPlayers.Add(playerIndex); + } + else + { + newlyInstatedPlayers.Add(playerIndex); + } + } + } + } + UpdateExistingPlayersDropStatus(newlyDroppedPlayers,true); + UpdateExistingPlayersDropStatus(newlyInstatedPlayers,false); + STATSGEN_DEBUG_FUNCTION_END +} + +void GlobalStatistics::UpdateExistingPlayersClan() +{ + wxString propertyClan="clanindex"; + wxString propertyName="name"; + wxString propertyPlayerIndex="playerindex"; + wxString sql; + TemplateOpenQuery query; + int existingClanIndex; + int existingPlayerIndex; + int newClanIndex; + wxString existingName; + + sql="select name,playerIndex,clanindex from player"; + + query.Initiate(sql,statsgenDatabase.DBHandle()); + while (query.NextRow()) + { + existingClanIndex=atoi(query.RetrieveProperty(propertyClan).GetData()); + existingName=query.RetrieveProperty(propertyName); + newClanIndex=ClanIndex(existingName); + if (newClanIndex!=existingClanIndex) + { + existingPlayerIndex=atoi(query.RetrieveProperty(propertyPlayerIndex).GetData()); + sql.Printf("update player set clanindex=%d where playerindex=%d", + newClanIndex,existingPlayerIndex); + statsgenDatabase.SimpleExecute(sql); + playersChanged.Add(existingPlayerIndex); + } + } +} + +void GlobalStatistics::UpdateExistingPlayersDropStatus( + wxArrayInt &playerIndexList, + bool dropped) +{ + char dropChar; + int playerIndexCount; + int playerListIndex; + int playerIndex; + wxString sql; + int playersChangedCount; + int playersChangedIndex; + bool alreadyAdded; + + STATSGEN_DEBUG_FUNCTION_START("GlobalStatistics","UpdateExistingPlayersDropStatus") + if (dropped) + { + dropChar='Y'; + } + else + { + dropChar='N'; + } + + playerIndexCount=playerIndexList.GetCount(); + for (playerListIndex=0;playerListIndex +#include +#include + +// statsgen includes +#include "Cheater.h" +#include "Player.h" +#include "Round.h" +#include "ConfigData.h" +#include "StatsgenDatabase.h" +#include "GenericKey.h" +#include "PlayerCacheEntry.h" +#include "AKAListEntry.h" +#include "AliasListEntry.h" +#include "AwardDefinition.h" +#include "Server.h" +#include "Clan.h" +#include "DropList.h" +#include "ScheduleItem.h" +#include "KillTotalLists.h" +#include "PlayerDataList.h" +#include "WeightList.h" +#include "TemplateFile.h" +#include "PlayerList.h" +#include "AliasCacheEntry.h" +#include "XPPoints.h" +#include "XPTotals.h" +#include "WebServer.h" +#include "TemplateFile.h" + +#define CONFIG_KEY_SPEECHFILE "/General/Speechfile" + +#define STEP_APPLY_ALIASES "ApplyAliases" +#define STEP_DATABASE_READ_STATIC "DatabaseReadStatic" +#define STEP_DATABASE_LOCATE_EXISTING_PLAYERS "DatabaseLocateExistingPlayers" +#define STEP_DOWNLOAD_LOGS "DownloadLogFile" +#define STEP_CREATE_LOG_FILES "CreateLogfileObjects" +#define STEP_PROCESS_LOG_FILES "ProcessLogfiles" +#define STEP_DROP_PLAYERS "DropPlayersAndRounds" +#define STEP_CALCULATE_SCORES "CalculateScores" +#define STEP_CREATE_DATABASE "CreateDatabase" +#define STEP_EMPTY_DATABASE "EmptyDatabase" +#define STEP_WRITE_DATABASE "WriteDatabase" +#define STEP_TRANSFER_DATABASE "TransferDatabase" +#define STEP_READ_TEMPLATE "ReadTemplate" +#define STEP_PROCESS_TEMPLATE "ProcessTemplate" +#define STEP_POST_PROCESS_TEMPLATE "PostProcessTemplate" +#define STEP_WEBSITE "Website" + +class TemplateFile; + +class GlobalStatistics +{ + public: + GlobalStatistics(); + ~GlobalStatistics(); + void CalculateScores(); + void InitiateSkillCalculationType(); + wxString SkillCalculationTypeConfigKey(); + bool AllowNegativeSkill(); + bool ProcessStepAllowed(int step,wxArrayInt &allowedSteps); + void ProduceStatsInitiate(); + void ProduceStatsDownload(); + void ProduceStatsProcess(); + void ProduceStatsTransfer(); + void ProduceStatsFinalise(); + void ProduceStats( + bool fullRun, + wxArrayInt &allowedSteps, + TemplateFile &templateFile); + void DropPlayersAndRounds(); + void DropPlayers(); + void DropRounds(); + void DropInactiveRounds(); + int FindPlayerIndex(wxString &name); + int FindGUIDIndex(wxString &guid); + int AddPlayer(wxString &name,wxString &id); + Player GetPlayer(int index); + int GenericKeyIndex(ArrayOfGenericKey &keyArray, + wxString &id); + wxString GenericKeyID(ArrayOfGenericKey &keyArray, + int index); + int GenericKeyAdd(ArrayOfGenericKey &keyArray, + wxString &id); + void Debug(); + bool WriteToDatabase(); + void GenericKeyDebug( + ArrayOfGenericKey &arrayKey, + char *tableName); + void ReadPlayerCache(); + void WritePlayerCache(); + void PlayerListToPlayerCache(); + void ReadAliasList(); + void WriteAliasList(); + void AddAlias(AliasListEntry &aliasEntry); + void DeleteAlias(AliasListEntry &aliasEntry); + bool FindAlias(AliasListEntry &aliasEntry); + void ReadAwardDefinitions(); + void ReadClanDefinitions(); + void ReadServersFromConfig(); + void ClearServers(); + int ClanIndex(wxString &name); + void ReadScheduleConfig(); + void ReadMessageTimerConfig(); + void ReadProductionRunTimerConfig(); + void ReadQuickRunTimerConfig(); + + bool StepAllowed(const char *step); + void ResetProcessingStatus(); + + void InitiateMessageCentres(); + void SendMessages(); + void ReadDeathmatchGametypes(); + void ReadTeamSwapWeapons(); + bool IsDeathmatchGametype(wxString &gametype); + bool IsDeathmatchGametype(int gametype); + bool IsTeamSwapWeapon(int weapon); + bool IsTeamSwapWeapon(wxString &weapon); + void OpenSpeechFile(); + void CloseSpeechFile(); + void WriteSpeechFile(wxDateTime &speechTime,wxString &guid,wxString &playerName,wxString &speech); + void GenerateUpgrade(wxString &filename); + void AddAKA(int playerIndex,wxString &name); + float ScoreWeight(const char *key,float defaultValue); + float ScoreWeight(const char *key,const char *prefix,float defaultValue); + float ScoreWeight(wxString &key,float defaultValue); + float GametypeScoreWeight(wxString &gametype); + float GametypeScoreWeight(int gametype); + float GametypeSkillWeight(wxString &gametype); + float GametypeSkillWeight(int gametype); + float SkillWeight(const char *key,float defaultValue); + float SkillWeight(const char *key,const char *prefix,float defaultValue); + float SkillWeight(wxString &key,float defaultValue); + int ReadPriority(bool fullRun); + void WritePriority(bool fullRun,int priority); + wxString AutomaticAliasConfigKey(); + void EmptyAliasCache(); + void AddToAliasCache(ArrayOfAliasCacheEntry *cache, + wxString &name, + wxString &guid, + int index); + void ReadStaticItemsFromDatabase(); + void ReadGenericKeyFromDatabase(ArrayOfGenericKey &keyList, + const char *tableName); + void LocateExistingPlayers(); + void DropExistingPlayers(); + void UpdateExistingPlayersDropStatus(wxArrayInt &playerIndexList,bool dropped); + void UpdateExistingPlayersClan(); + void DropExistingCheat(int playerIndex,int worldPlayerIndex); + void FlagStartOfRun(); + void FlagEndOfRun(); + bool AreStatsRunning(); + + public: + TemplateFile templateFile; + time_t startTime; + PlayerDataList *playerDataAvatars; + PlayerDataList *playerDataWebsite; + PlayerDataList *playerDataPicture; + PlayerDataList *playerDataXfire; + PlayerDataList *playerDataClanRole; + PlayerDataList *playerDataRealName; + PlayerDataList *playerDataMisc1; + PlayerDataList *playerDataMisc2; + ArrayOfPlayerCacheEntry playerCache; + //ArrayOfServer servers; + ArrayOfPointers servers; + ArrayOfAliasListEntry aliasList; + ArrayOfAKAListEntry AKAList; + DropList dropList; + //ArrayOfPlayers players; + PlayerList playerList; + ArrayOfRounds rounds; + ArrayOfAwardDefinition awardDefinitions; + ArrayOfClan clans; + ConfigData configData; + StatsgenDatabase statsgenDatabase; + + ArrayOfGenericKey keysAction; + ArrayOfGenericKey keysAmmo; + ArrayOfGenericKey keysMap; + ArrayOfGenericKey keysWeapon; + ArrayOfGenericKey keysClass; + ArrayOfGenericKey keysTeam; + ArrayOfGenericKey keysGametype; + ArrayOfGenericKey keysLocation; + ArrayOfGenericKey keysXP; + wxArrayInt playersChanged; + wxArrayInt droppedPlayersChanged; + wxArrayInt roundsChanged; + + KillTotalLists killTotalLists; + XPTotals totalXP; + + int roundsAlreadyProcessed; + + ScheduleItem messageTimer; + ScheduleItem productionRunTimer; + ScheduleItem quickRunTimer; + wxArrayString deathmatchGametypes; + wxArrayString teamSwapWeapons; + wxArrayString bannedSpeech; + + FILE *speechfp; + + bool negativeSkillAllowed; + WeightList skillWeights; + WeightList scoreWeights; + wxThread *currentRunningThread; + wxEvtHandler *mainEventHandler; + + bool useAutomaticAliases; + bool aliasCacheEnabled; + ArrayOfAliasCacheEntry *aliasCache; + ArrayOfAliasCacheEntry *aliasPrimaryCache; + Cheaters cheaters; + + WebServer webServer; + + bool hiddenFeatures; + + bool recoveryMode; + + bool statsRunning; +}; + +extern GlobalStatistics globalStatistics; +#endif diff --git a/GroupedConfigItemsPanel.cpp b/GroupedConfigItemsPanel.cpp new file mode 100644 index 0000000..6039660 --- /dev/null +++ b/GroupedConfigItemsPanel.cpp @@ -0,0 +1,434 @@ +// Statsgen Includes +#include "GroupedConfigItemsPanel.h" +#include "GlobalStatistics.h" +#include "BaseConfigItemGUI.h" +#include "TextConfigItemGUI.h" +#include "FileConfigItemGUI.h" +#include "DirectoryConfigItemGUI.h" +#include "BooleanConfigItemGUI.h" +#include "RemoteFileConfigItemGUI.h" +#include "RemoteDirectoryConfigItemGUI.h" +#include "SelectionConfigItemGUI.h" +#include "ScheduleConfigItemGUI.h" +#include "Progress.h" + + +BEGIN_EVENT_TABLE(GroupedConfigItemsPanel, wxPanel) + EVT_SIZE(GroupedConfigItemsPanel::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,GroupedConfigItemsPanel::OnTextChange) +END_EVENT_TABLE() + + +GroupedConfigItemsPanel::GroupedConfigItemsPanel(char *titleIn) +{ + title=titleIn; + staticBoxAdded=false; +} + +GroupedConfigItemsPanel::~GroupedConfigItemsPanel() +{ +} + +bool GroupedConfigItemsPanel::UpdateFromTrigger() +{ + bool panelTriggered; + int panelCount; + int panelIndex; + BaseConfigItemGUI *configPanel; + + panelTriggered=false; + panelCount=configItemPanels.GetCount(); + for (panelIndex=0;panelIndexUpdateFromTrigger()) + { + panelTriggered=true; + } + } + wxSizeEvent dummyEvent; + OnResize(dummyEvent); + return (panelTriggered); +} + +void GroupedConfigItemsPanel::OnTextChange(wxCommandEvent &event) +{ + STATSGEN_DEBUG_FUNCTION_START("GroupedConfigItemsPanel","OnTextChange") + UpdateFromTrigger(); + if (GetParent()!=NULL) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Popping Event") + GetParent()->AddPendingEvent(event); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void GroupedConfigItemsPanel::Add(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + GUITriggerList *triggerList) +{ + TextConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new TextConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,charWidth); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } +} + +int GroupedConfigItemsPanel::PreferredHeight() +{ + BaseConfigItemGUI *configItemGUI; + int configItemCount; + int configItemIndex; + int panelHeight; + + panelHeight=0; + configItemCount=configItemPanels.GetCount(); + for (configItemIndex=0;configItemIndexIsShown()) + { + panelHeight+=configItemGUI->PreferredHeight(); + } + } + + panelHeight+=STATIC_BOX_TOP_GAP; + panelHeight+=STATIC_BOX_BOTTOM_GAP; + + return (panelHeight); +} + +void GroupedConfigItemsPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + int configItemCount; + int configItemIndex; + BaseConfigItemGUI *configItemGUI; + int yPosition; + wxSize itemSize; + int panelWidth; + int panelHeight; + int itemWidth; + int itemHeight; + int labelWidth; + int maxLabelWidth; + int staticBoxWidth; + int staticBoxHeight; + wxPoint panelPosition; + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + staticBoxWidth=panelWidth-STATIC_BOX_LEFT_GAP-STATIC_BOX_RIGHT_GAP; + staticBoxHeight=panelHeight; + + + configItemCount=configItemPanels.GetCount(); + + yPosition=STATIC_BOX_TOP_GAP; + + // First - normalise the labels + maxLabelWidth=0; + for (configItemIndex=0;configItemIndexIsShown()) + { + labelWidth=configItemGUI->GetLabelWidth(); + if (labelWidth>maxLabelWidth) + { + maxLabelWidth=labelWidth; + } + } + } + + for (configItemIndex=0;configItemIndexIsShown()) + { + configItemGUI->SetLabelWidth(maxLabelWidth); + itemSize=configItemGUI->GetSize(); + itemWidth=itemSize.GetWidth(); + itemHeight=configItemGUI->PreferredHeight(); + if (itemHeight<2) + { + itemHeight=2; + } + + itemWidth=staticBoxWidth-STATIC_BOX_LEFT_GAP- + STATIC_BOX_RIGHT_GAP- + STATIC_BOX_LEFT_GAP; + + + configItemGUI->SetSize(STATIC_BOX_LEFT_GAP+STATIC_BOX_LEFT_GAP, + yPosition,itemWidth,itemHeight); + yPosition+=itemHeight; + } + } + + staticBoxHeight=yPosition+STATIC_BOX_BOTTOM_GAP; + staticBox.SetSize(STATIC_BOX_LEFT_GAP, + 0, + staticBoxWidth, + staticBoxHeight); + + panelPosition=GetPosition(); + if (panelWidth<10) + { + panelWidth=10; + } + if (staticBoxHeight<10) + { + staticBoxHeight=10; + } + /*SetSize(panelWidth, + staticBoxHeight);*/ + /* + SetSize(panelPosition.x, + panelPosition.y, + panelWidth, + staticBoxHeight); + */ + +} + +void GroupedConfigItemsPanel::AddBoolean(char *label, + wxString &configKey, + bool defaultValue, + GUITriggerList *triggerList) +{ + BooleanConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr; + + newPanel=new BooleanConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + if(defaultValue) + { + defaultStr="Y"; + } + else + { + defaultStr="N"; + } + newPanel->Set(configKey,labelStr,defaultStr); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } +} + +FileConfigItemGUI *GroupedConfigItemsPanel::AddFile(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + DirectoryConfigItemGUI *directoryGUI, + GUITriggerList *triggerList) +{ + FileConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new FileConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,charWidth,directoryGUI); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } + return (newPanel); +} + +DirectoryConfigItemGUI *GroupedConfigItemsPanel::AddDirectory(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + GUITriggerList *triggerList) +{ + DirectoryConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new DirectoryConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,charWidth); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } + return (newPanel); +} + +RemoteFileConfigItemGUI *GroupedConfigItemsPanel::AddRemoteFile(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + wxString &FTPID, + RemoteDirectoryConfigItemGUI *directoryGUI, + GUITriggerList *triggerList) +{ + RemoteFileConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new RemoteFileConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,charWidth, + FTPID,directoryGUI); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } + return (newPanel); +} + +RemoteDirectoryConfigItemGUI *GroupedConfigItemsPanel::AddRemoteDirectory( + char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + wxString &FTPID, + GUITriggerList *triggerList) +{ + RemoteDirectoryConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new RemoteDirectoryConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,charWidth, + FTPID); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } + return (newPanel); +} + +void GroupedConfigItemsPanel::AddSelection(char *label, + wxString &configKey, + char *defaultValue, + wxArrayString &codes, + wxArrayString &names, + GUITriggerList *triggerList) +{ + SelectionConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new SelectionConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,codes,names); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } +} + +void GroupedConfigItemsPanel::AddSchedule(char *label, + wxString &configKey, + wxString &defaultValue, + bool intervalWithBase, + GUITriggerList *triggerList) +{ + ScheduleConfigItemGUI *newPanel; + wxString labelStr=label; + + newPanel=new ScheduleConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultValue,intervalWithBase); + + configItemPanels.Add((void *)newPanel); + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } +} + +void GroupedConfigItemsPanel::AddSelectionFreeForm(char *label, + wxString &configKey, + char *defaultValue, + wxArrayString &codes, + wxArrayString &names, + int charWidth, + GUITriggerList *triggerList) +{ + SelectionFreeFormConfigItemGUI *newPanel; + wxString labelStr=label; + wxString defaultStr=defaultValue; + + newPanel=new SelectionFreeFormConfigItemGUI(); + newPanel->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newPanel->Set(configKey,labelStr,defaultStr,codes,names,charWidth); + + configItemPanels.Add((void *)newPanel); + if (!staticBoxAdded) + { + staticBoxAdded=true; + staticBox.Create(this,-1,title); + } + if (triggerList!=NULL) + { + newPanel->SetTriggerCondition(*triggerList); + } +} + diff --git a/GroupedConfigItemsPanel.h b/GroupedConfigItemsPanel.h new file mode 100644 index 0000000..b6eaf26 --- /dev/null +++ b/GroupedConfigItemsPanel.h @@ -0,0 +1,90 @@ +#ifndef __GROUPEDCONFIGITEMSPANEL +#define __GROUPEDCONFIGITEMSPANEL + +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "SelectionFreeFormConfigItemGUI.h" +#include "TextConfigItemGUI.h" +#include "FileConfigItemGUI.h" +#include "RemoteFileConfigItemGUI.h" +#include "RemoteDirectoryConfigItemGUI.h" +#include "DirectoryConfigItemGUI.h" +#include "DynamicArrays.h" +#include "GUITriggerList.h" + +class GroupedConfigItemsPanel : public wxPanel +{ + public: + int PreferredHeight(); + GroupedConfigItemsPanel(char *titleIn); + ~GroupedConfigItemsPanel(); + void AddSchedule(char *label, + wxString &configKey, + wxString &defaultValue, + bool intervalWithBase, + GUITriggerList *triggerList=NULL); + void AddBoolean(char *label, + wxString &configKey, + bool defaultValue, + GUITriggerList *triggerList=NULL); + void Add(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + GUITriggerList *triggerList=NULL); + void AddSelectionFreeForm(char *label, + wxString &configKey, + char *defaultValue, + wxArrayString &codes, + wxArrayString &names, + int charWidth, + GUITriggerList *triggerList=NULL); + void AddSelection(char *label, + wxString &configKey, + char *defaultValue, + wxArrayString &codes, + wxArrayString &names, + GUITriggerList *triggerList=NULL); + FileConfigItemGUI *AddFile(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + DirectoryConfigItemGUI *directoryGUI=NULL, + GUITriggerList *triggerList=NULL); + DirectoryConfigItemGUI *AddDirectory(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + GUITriggerList *triggerList=NULL); + RemoteFileConfigItemGUI *AddRemoteFile(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + wxString &FTPIDIn, + RemoteDirectoryConfigItemGUI *directoryGUI=NULL, + GUITriggerList *triggerList=NULL); + RemoteDirectoryConfigItemGUI *AddRemoteDirectory(char *label, + wxString &configKey, + char *defaultValue, + int charWidth, + wxString &FTPIDIn, + GUITriggerList *triggerList=NULL); + + void OnResize(wxSizeEvent &event); + void OnTextChange(wxCommandEvent &event); + bool UpdateFromTrigger(); + + protected: + + private: + wxString title; + wxStaticBox staticBox; + bool staticBoxAdded; + ArrayOfPointers configItemPanels; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ImagePanel.cpp b/ImagePanel.cpp new file mode 100644 index 0000000..642c2d8 --- /dev/null +++ b/ImagePanel.cpp @@ -0,0 +1,215 @@ +#include +#include +#include "ImagePanel.h" + +BEGIN_EVENT_TABLE(ImagePanel, wxPanel) + EVT_PAINT(ImagePanel::OnPaint) + EVT_SIZE(ImagePanel::OnResize) +END_EVENT_TABLE() + +ImagePanel::ImagePanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name):wxPanel(parent, + id, + pos, + size, + style, + name) +{ + painting=false; + currentScale=1.0; +} +ImagePanel::ImagePanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxImage &imageIn):wxPanel(parent, + id, + pos, + size, + style, + name) +{ + image=imageIn; +} + +void ImagePanel::SetImage(wxImage &imageIn) +{ + image.Destroy(); + image=imageIn.Copy(); + DrawImage(); +} + +void ImagePanel::Maximise() +{ + wxSize panelSize; + int panelWidth; + int panelHeight; + int imageWidth; + int imageHeight; + float xscale; + float yscale; + bool growing; + float smallestScale; + float largestScale; + + panelSize=GetSize(); + panelWidth=panelSize.GetWidth(); + panelHeight=panelSize.GetHeight(); + imageWidth=image.GetWidth(); + imageHeight=image.GetHeight(); + if ((imageWidth==0)||(imageHeight==0)) + { + currentScale=1.0; + } + else + { + if ((imageWidth>panelWidth)||(imageHeight>panelHeight)) + { + growing=false; + } + else + { + growing=true; + } + xscale=(float)panelWidth/(float)imageWidth; + yscale=(float)panelHeight/(float)imageHeight; + + smallestScale=yscale; + largestScale=xscale; + if (xscaleClear(); + dc->DrawBitmap(bitmap,0,0); +} + +void ImagePanel::Clear() +{ + wxClientDC dc(this); + dc.Clear(); +} + +void ImagePanel::Proportion(int maxWidth,int maxHeight) +{ + int imageWidth; + int imageHeight; + float widthRatio; + float heightRatio; + float newRatio; + float smallestScale; + float largestScale; + bool growing; + wxString msg; + + imageWidth=image.GetWidth(); + imageHeight=image.GetHeight(); + + if ((imageWidth==0)||(imageHeight==0)) + { + return; + } + widthRatio =(float)maxWidth/(float)imageWidth; + heightRatio =(float)maxHeight/(float)imageHeight; +// msg.Printf("[%d][%d] [%d][%d] [%.2f][%.2f]",maxWidth,maxHeight,imageWidth,imageHeight,widthRatio,heightRatio);wxMessageBox(msg); + if ((imageWidth>maxWidth)||(imageHeight>maxHeight)) + { + growing=false; + } + else + { + growing=true; + } + + smallestScale =widthRatio; + largestScale =heightRatio; + if (widthRatio>heightRatio) + { + smallestScale =heightRatio; + largestScale =widthRatio; + } + if (growing) + { + newRatio=smallestScale; + } + else + { + newRatio=smallestScale; + } +//msg.Printf("newRatio [%.2f] [%.2f][%.2f]",newRatio, +// (float)imageWidth * newRatio, +// (float)imageHeight * newRatio);wxMessageBox(msg); + Scale(newRatio); + DrawImage(); +} + +void ImagePanel::OnPaint(wxPaintEvent &event) +{ + painting=true; + DrawImage(); + painting=false; +} + +ImagePanel::~ImagePanel() +{ +} + +void ImagePanel::OnResize(wxSizeEvent &event) +{ + //Maximise(); + // + painting=false; + DrawImage(); +} diff --git a/ImagePanel.h b/ImagePanel.h new file mode 100644 index 0000000..747c21c --- /dev/null +++ b/ImagePanel.h @@ -0,0 +1,45 @@ +#ifndef __IMAGEPANEL_H +#define __IMAGEPANEL_H +#include +#include +#include +#include +#include +#include + +class ImagePanel : public wxPanel +{ + public: + ImagePanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + ImagePanel(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + wxImage &imageIn); + void SetImage(wxImage &imageIn); + virtual ~ImagePanel(); + wxString GetValue(); + void OnPaint(wxPaintEvent &event); + void OnResize(wxSizeEvent &event); + void Maximise(); + + void DrawImage(); + void Scale(float scaleFactor); + void Proportion(int maxWidth,int maxHeight); + void Clear(); + private: + wxImage image; + float currentScale; + bool painting; + DECLARE_EVENT_TABLE() + +}; + +#endif diff --git a/ImageTypePanel.cpp b/ImageTypePanel.cpp new file mode 100644 index 0000000..1005a48 --- /dev/null +++ b/ImageTypePanel.cpp @@ -0,0 +1,74 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "ImageTypePanel.h" +#include "Server.h" +#include "GlobalStatistics.h" +#include "WindowIDs.h" + +wxString ImageTypePanel::GetLabel() +{ + wxString label="Stat Type"; + return (label); +} + +wxString ImageTypePanel::AllName() +{ + wxString all="All Stat Types"; + + return (all); +} + +wxString ImageTypePanel::AllCode() +{ + wxString all=""; + + return (all); +} + +wxString ImageTypePanel::FindCodeFromName(wxString &name) +{ + int count; + int index; + wxString foundName; + wxString retVal=""; + + count=IMAGE_TYPE_COUNT; + + for (index=0;index +#include +#include + +// Statsgen Includes +#include "BoxedDropDown.h" + +class ImageTypePanel : public BoxedDropDown +{ + protected: + virtual wxString GetLabel(); + virtual void DropDownEntries(wxArrayString &entries, + wxString &defaultSelection); + virtual wxString AllCode(); + virtual wxString AllName(); + virtual wxString FindCodeFromName(wxString &name); + private: +}; + + +#endif diff --git a/Initiate b/Initiate new file mode 100644 index 0000000..446685f --- /dev/null +++ b/Initiate @@ -0,0 +1,423 @@ +CODBanFile.cpp: status="Reading Ban File"; progress->SetStatus(status); +DropList.cpp: status="Reading Drop List"; progress->SetStatus(status); +DropList.cpp: progress->Initiate(dropCount, +DropList.cpp: progress->Update(dropIndex+1); +ExternalDatabase.cpp: progress->Initiate(rowCount," rows",1," rows",1); +ExternalDatabase.cpp: progress->Update(currentRowCount); +ExternalDatabase.cpp: progress->Update(currentRowCount); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->Update(currentRowCount); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->Update(currentRowCount); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->Update(currentRowCount); +ExternalDatabase.cpp: progress->SetStatus(msg); +ExternalDatabase.cpp: progress->Update(*currentRowCount); +ExternalDatabase.cpp: progress->Update(*currentRowCount); +ExternalDatabase.cpp: progress->LogError(msg,SeverityError); +ExternalDatabase.cpp: progress->LogError(msg,SeverityError); +ExternalDatabase.cpp: progress->LogError(msg,SeverityError); +ExternalDatabase.cpp: progress->LogError(msg,SeverityError); +ExternalDatabase.cpp: progress->LogError(msg,SeverityError); +FTPBrowserPanel.cpp: progress->SetDynamicPanel(NULL); +FTPBrowserPanel.cpp: status="Getting Size";progress->SetStatus(status); +FTPBrowserPanel.cpp: status="Done";progress->SetStatus(status); +FTPBrowserPanel.cpp: status="Getting Directory Listing"; progress->SetStatus(status); +FTPBrowserPanel.cpp: status="Done"; progress->SetStatus(status); +FTPBrowserPanel.cpp: progress->SetDynamicPanel(progressPanel); +FTPBrowserPanel.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DYNAMIC); +FTPBrowserPanel.cpp: progress->UpdateLabel(""); +GlobalStatistics.cpp: progress->Initiate((long)rounds.GetCount(), +GlobalStatistics.cpp: progress->Update((long)(roundIndex+1)); +GlobalStatistics.cpp: status="Reading Aliases"; progress->SetStatus(status); +GlobalStatistics.cpp: progress->Initiate(aliasCount, +GlobalStatistics.cpp: progress->Update(aliasIndex+1); +GlobalStatistics.cpp: progress->DisableTimeToGo(); +GlobalStatistics.cpp: progress->Initiate(topValue, +GlobalStatistics.cpp: progress->Update(1); +GlobalStatistics.cpp: progress->Update(2); +GlobalStatistics.cpp: progress->Update(3); +GlobalStatistics.cpp: progress->Update(4); +GlobalStatistics.cpp: progress->ClearErrors(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_GENERAL); +GlobalStatistics.cpp: progress->LogError(templateFilename); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE); +GlobalStatistics.cpp: progress->DisableTimeToGo(); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); +GlobalStatistics.cpp: progress->DisableTimeToGo(); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->Initiate( +GlobalStatistics.cpp: progress->LogError(msg,SeverityCaution); +GlobalStatistics.cpp: progress->Update((long)roundIndex+1); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES2); +GlobalStatistics.cpp: progress->Initiate( +GlobalStatistics.cpp: progress->Update((long)playerIndex+1); +GlobalStatistics.cpp: status="Read Award Definitions"; progress->SetStatus(status); +GlobalStatistics.cpp: status="Updating Servers"; progress->SetStatus(status); +GlobalStatistics.cpp: status="Read Clan Definitions"; progress->SetStatus(status); +GlobalStatistics.cpp: progress->ClearErrors(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_GENERAL); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_APPLY_ALIASES); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DATABASE_READ_STATIC); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DATABASE_LOCATE_EXISTING_PLAYERS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE); +GlobalStatistics.cpp: progress->DisableTimeToGo(); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); +GlobalStatistics.cpp: progress->DisableTimeToGo(); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE); +GlobalStatistics.cpp: progress->Finalise(); +GlobalStatistics.cpp: progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_WEBSITE); +GlobalStatistics.cpp: progress->Finalise(); +LogFile.cpp: progress->SetStatus(msg); +LogFileReader.cpp: progress->Update(currentFilePosition); +LogFileReader.cpp: progress->LogError(errorMessage,SeverityError); +MessageCentre.cpp: progress->LogError(msg,SeverityCaution); +MessageCentre.cpp: progress->LogError(msg,SeverityCaution); +MessageCentre.cpp: progress->LogError(msg,SeverityCaution); +MessageCentre.cpp: progress->LogError(msg,SeverityCaution); +MessageCentre.cpp: progress->LogError(msg,SeverityCaution); +MessageCentre.cpp: progress->LogError(msg,SeverityError); +MessageCentre.cpp: progress->LogError(msg,SeverityError); +PunkbusterBanFile.cpp: status="Reading Ban File"; progress->SetStatus(status); +QuakeWarsLogFileReader.cpp: progress->Update(currentPosition); +QuakeWarsLogFileReader.cpp: progress->Update(currentPosition); +QuakeWarsLogFileReader.cpp: progress->LogError(errorMessage,SeverityError); +RemoteMachine.cpp: progress->SetStatus(msg); +RemoteMachine.cpp: progress->LogError(msg,SeverityOK); +RemoteMachine.cpp: progress->Update(remoteFileSize); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->Update(bytesRead); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,SeverityCaution); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(errorMessage,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->Update(bytesTransferred); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +RemoteMachine.cpp: progress->LogError(msg,maxErrorSeverity); +Round.cpp: progress->WakeUp(); +Server.cpp: progress->Initiate(totalFileSize, +Server.cpp: progress->Update(0); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->SetStatus(msg); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->Initiate(totalFileSize, +Server.cpp: //progress->SetStatus(msg); +Server.cpp: progress->SetOffset(progress->CurrentValue()); +Server.cpp: progress->SetOffset(progress->CurrentValue()); +Server.cpp: progress->SetOffset(progress->CurrentValue()); +Server.cpp: progress->SetOffset(progress->CurrentValue()); +Server.cpp: progress->LogError(msg,SeverityCaution); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->LogError(msg,SeverityError); +Server.cpp: progress->Initiate( +Server.cpp: currentProgress=progress->CurrentValue(); +Server.cpp: progress->Update(currentProgress); +StatsgenApp.cpp: itemSize=progress->GetSize(); +StatsgenDatabase.cpp: progress->LogError(msg,SeverityError); +StatsgenDatabase.cpp: progress->Initiate(topValue, +StatsgenDatabase.cpp: progress->DisableTimeToGo(); +StatsgenDatabase.cpp: progress->Update(step++); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Changed Players"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Changed Rounds"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Actions"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Ammo"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Weapons"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Maps"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Teams"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Classes"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Gametypes"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Locations"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:XP"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Cheats"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Skill Weights"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Score Weights"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Avatars"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Picture"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Website"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:XFire"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Clan Role"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Real Name"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Misc 1"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Misc 2"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("AKA List"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Maps"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Game Types"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Weapons"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Locations"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Teams"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kill Totals:Classes"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Servers"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Server Variables"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Server Progress"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Clans"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Players"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Rounds"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Round Variables"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Kills"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Team Wins"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Team Losses"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Actions"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Speech"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Players In Rounds"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Award Points"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Total XP Points"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("XP Points"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Streaks"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Award Definitions"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Miscellaneous"); +StatsgenDatabase.cpp:// progress->Update(step++);progress->SetStatus("Indexes"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Views"); +StatsgenDatabase.cpp: progress->LogError(errorString,SeverityError); +StatsgenDatabase.cpp: progress->Initiate(topValue, +StatsgenDatabase.cpp: progress->DisableTimeToGo(); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Starting"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Changed Players"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Changed Rounds"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Actions"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Ammo"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Weapons"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Maps"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Teams"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Classes"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Game Types"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:Locations"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Keys:XP"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Total XP List"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("XP List"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Cheaters List"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("AKA List"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Skill Weights"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Score Weights"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Avatars"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Pictures"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Website"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:XFire"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Clan Roles"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Real Names"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Misc 1"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Player Data:Misc 2"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Maps"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Game Types"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Weapons"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Locations"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Teams"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kill Totals:Classes"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Server Variables"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Servers"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Clans"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Players"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Rounds"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Round Variables"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Kills"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Team Wins"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Team Losses"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Actions"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Speech"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Players In Rounds"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Award Points"); +StatsgenDatabase.cpp: // progress->Update(step++);progress->SetStatus("Streaks"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Award Definition"); +StatsgenDatabase.cpp: progress->Update(step++);progress->SetStatus("Miscellaneous"); +StatsgenDatabase.cpp: progress->SetStatus(totaltype); +StatsgenDatabase.cpp: progress->SetStatus("Create Indexes"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_1"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_2"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_3"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_4"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_5"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_6"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_7"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_8"); +StatsgenDatabase.cpp: progress->SetStatus("xppoints_9"); +StatsgenDatabase.cpp: progress->SetStatus("xptotalpoints_1"); +StatsgenDatabase.cpp: progress->SetStatus("xptotalpoints_2"); +StatsgenDatabase.cpp: progress->SetStatus("xptotalpoints_3"); +StatsgenDatabase.cpp: progress->SetStatus("xptotalpoints_4"); +StatsgenDatabase.cpp: progress->SetStatus("roundvariables_1"); +StatsgenDatabase.cpp: progress->SetStatus("roundvariables_2"); +StatsgenDatabase.cpp: progress->SetStatus("roundvariables_3"); +StatsgenDatabase.cpp: progress->SetStatus("roundvariables_4"); +StatsgenDatabase.cpp: progress->SetStatus("action_1"); +StatsgenDatabase.cpp: progress->SetStatus("action_2"); +StatsgenDatabase.cpp: progress->SetStatus("class_1"); +StatsgenDatabase.cpp: progress->SetStatus("class_2"); +StatsgenDatabase.cpp: progress->SetStatus("gametype_1"); +StatsgenDatabase.cpp: progress->SetStatus("gametype_2"); +StatsgenDatabase.cpp: progress->SetStatus("location_1"); +StatsgenDatabase.cpp: progress->SetStatus("location_2"); +StatsgenDatabase.cpp: progress->SetStatus("map_1"); +StatsgenDatabase.cpp: progress->SetStatus("map_2"); +StatsgenDatabase.cpp: progress->SetStatus("team_1"); +StatsgenDatabase.cpp: progress->SetStatus("team_2"); +StatsgenDatabase.cpp: progress->SetStatus("weapon_1"); +StatsgenDatabase.cpp: progress->SetStatus("weapon_2"); +StatsgenDatabase.cpp: progress->SetStatus("actiondata_1"); +StatsgenDatabase.cpp: progress->SetStatus("actiondata_2"); +StatsgenDatabase.cpp: progress->SetStatus("actiondata_3"); +StatsgenDatabase.cpp: progress->SetStatus("actiondata_4"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_1"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_2"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_3"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_4"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_5"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_6"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_7"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_8"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_9"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_10"); +StatsgenDatabase.cpp: progress->SetStatus("killdata_11"); +StatsgenDatabase.cpp: progress->SetStatus("player_1"); +StatsgenDatabase.cpp: progress->SetStatus("player_2"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_1"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_2"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_3"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_4"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_5"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_6"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_7"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_8"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_9"); +StatsgenDatabase.cpp: progress->SetStatus("playerinround_10"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_1"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_2"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_3"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_4"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_5"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_6"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_7"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_8"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_9"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_10"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_11"); +StatsgenDatabase.cpp: progress->SetStatus("rounds_12"); +StatsgenDatabase.cpp: progress->SetStatus("speechdata_1"); +StatsgenDatabase.cpp: progress->SetStatus("speechdata_2"); +StatsgenDatabase.cpp: progress->SetStatus("speechdata_3"); +StatsgenDatabase.cpp: progress->SetStatus("teamlossdata_1"); +StatsgenDatabase.cpp: progress->SetStatus("teamlossdata_2"); +StatsgenDatabase.cpp: progress->SetStatus("teamlossdata_3"); +StatsgenDatabase.cpp: progress->SetStatus("teamwindata_1"); +StatsgenDatabase.cpp: progress->SetStatus("teamwindata_2"); +StatsgenDatabase.cpp: progress->SetStatus("teamwindata_3"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_1"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_2"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_3"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_4"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_5"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_6"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_7"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_8"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_9"); +StatsgenDatabase.cpp: progress->SetStatus("streakdata_10"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_1"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_2"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_3"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_4"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_5"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_6"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_7"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_8"); +StatsgenDatabase.cpp: progress->SetStatus("awardpoints_9"); +StatsgenDatabase.cpp: progress->SetStatus(msg); +StatsgenDatabase.cpp: progress->Initiate((long)tableCount," tables",1, " tables",1); +StatsgenDatabase.cpp: progress->Update((long)tableIndex); +StatsgenDatabase.cpp: progress->SetStatus(statusText); +StatsgenDatabase.cpp: progress->Finalise(); +StatsgenFrame.cpp: progress->Create(this,-1); +StatsgenFrame.cpp:// progress->CreatePanels(); +StatsgenFrame.cpp: progress->DisableUpdate(); +StatsgenFrame.cpp: progress->DisableUpdate(); +StatsgenFrame.cpp: msg="Before Panel";progress->LogError(msg); +StatsgenFrame.cpp: msg="After Panel";progress->LogError(msg); +StatsgenFrame.cpp: msg="Before GUI";progress->LogError(msg); +StatsgenFrame.cpp: msg="After GUI";progress->LogError(msg); +StatsgenFrame.cpp: msg="Before Create";progress->LogError(msg); +StatsgenFrame.cpp: msg="After Create";progress->LogError(msg); +StatsgenFrame.cpp: msg="Before Addboolean";progress->LogError(msg); +StatsgenFrame.cpp: msg="After Addboolean";progress->LogError(msg); +StatsgenFrame.cpp: progress->DisableUpdate(); +StatsgenLog.cpp: progress->LogError(messageString,newSeverity); +TemplateFile.cpp: progress->Update(templateLines.GetCount()); +TemplateFile.cpp: progress->LogError(errorMessage,SeverityError); +TemplateFile.cpp: progress->LogError(msg,SeverityCaution); +TemplateFile.cpp: progress->LogError(msg,SeverityCaution); +TemplateFile.cpp: progress->Initiate((long)0, +TemplateFile.cpp: progress->LogError(msg,SeverityCaution); +TemplateFile.cpp: progress->LogError(msg,SeverityError); +TemplateFile.cpp: progress->LogError(msg,SeverityCaution); +TemplateFile.cpp: progress->Update(*lineIndex); +TemplateFile.cpp: progress->LogError(msg,SeverityCaution); +TemplateOpenQuery.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityCaution); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->LogError(msg,SeverityError); +TemplateVariable.cpp: progress->SetStatus(token); +Website.cpp: progress->SetStatus(msg); +Website.cpp: progress->Initiate(totalFileSize, +Website.cpp: progress->SetOffset(progress->CurrentValue()); +Website.cpp: progress->SetStatus(filenameonly); +Website.cpp: progress->LogError(msg,SeverityError); diff --git a/KeyedIndex.cpp b/KeyedIndex.cpp new file mode 100644 index 0000000..1d3a228 --- /dev/null +++ b/KeyedIndex.cpp @@ -0,0 +1,11 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "KeyedIndex.h" + +int KeyedIndex::Compare(KeyedIndex *item1,KeyedIndex *item2) +{ + return (item1->key.Cmp(item2->key)); +} diff --git a/KeyedIndex.h b/KeyedIndex.h new file mode 100644 index 0000000..f6fd700 --- /dev/null +++ b/KeyedIndex.h @@ -0,0 +1,22 @@ +#ifndef __KEYEDINDEX +#define __KEYEDINDEX + +// wxWindows includes +#include +#include +#include +#include + +class KeyedIndex; + +WX_DEFINE_SORTED_ARRAY(KeyedIndex *,ArrayOfKeyedIndex); +class ArrayOfKeyedIndex; +class KeyedIndex +{ + public: + static int Compare(KeyedIndex *item1,KeyedIndex *item2); + wxString key; + int index; +}; + +#endif diff --git a/KillData.cpp b/KillData.cpp new file mode 100644 index 0000000..4df6360 --- /dev/null +++ b/KillData.cpp @@ -0,0 +1,153 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "KillData.h" +#include "GlobalStatistics.h" + +KillData::KillData() +{ +} + +KillData::~KillData() +{ +} + +char *KillData::KillTypeText() +{ + char *retVal; + + switch (KillType(gameType,playerIndex)) + { + case KILL_TYPE_KILL: + retVal=KILL_TYPE_STRING_KILL; + break; + case KILL_TYPE_DEATH: + retVal=KILL_TYPE_STRING_DEATH; + break; + case KILL_TYPE_TEAMKILL: + retVal=KILL_TYPE_STRING_TEAMKILL; + break; + case KILL_TYPE_TEAMKILLVICTIM: + retVal=KILL_TYPE_STRING_TEAMKILLVICTIM; + break; + case KILL_TYPE_TEAMSWAP: + retVal=KILL_TYPE_STRING_TEAMSWAP; + break; + case KILL_TYPE_SUICIDE: + retVal=KILL_TYPE_STRING_SUICIDE; + break; + default: + retVal=KILL_TYPE_STRING_UNKNOWN; + break; + } + + return (retVal); +} + +KillTypes KillData::KillType(int gameType,int playerIndexIn) +{ + KillTypes retVal; + + // Make this read from config eventually + + if (playerIndexIn==playerIndex) + { + // This is probably a kill + retVal=KILL_TYPE_KILL; + } + else + { + // This is probably a death + retVal=KILL_TYPE_DEATH; + } + + if (playerIndex==targetIndex) + { + retVal=KILL_TYPE_SUICIDE; + if (globalStatistics.IsTeamSwapWeapon(playerWeapon)) + { + retVal=KILL_TYPE_TEAMSWAP; + } + } + if (playerIndex!=targetIndex) + { + if (playerTeam==targetTeam) + { + if (!globalStatistics.IsDeathmatchGametype(gameType)) + { + if (playerIndex==playerIndexIn) + { + retVal=KILL_TYPE_TEAMKILL; + } + else + { + retVal=KILL_TYPE_TEAMKILLVICTIM; + } + } + } + } + + return (retVal); +} + +wxString KillData::SQLTableName() +{ + wxString tableName="killdata"; + + return (tableName); +} + +wxString KillData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "killidx integer," + "playerindex integer," + "playerclass integer," + "playerteam integer," + "playerweapon integer," + "playerammo integer," + "targetindex integer," + "targetclass integer," + "targetteam integer," + "targetlocation integer," + "%s" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("killtype","killtype",FIELD_WIDTH_KILL_TYPE).GetData() + ); + + return SQL; +} + +bool KillData::WriteToDatabase(int roundIndex,int itemIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + Player target; + + player=globalStatistics.playerList.Item(playerIndex); + target=globalStatistics.playerList.Item(targetIndex); + SQL.Printf("insert into %s" + "(roundindex,killidx,playerindex,playerclass,playerteam," + "playerweapon,playerammo,targetindex,targetclass," + "targetteam,targetlocation,killtype)" + "values" + "('%d','%d','%d','%d','%d'," + "'%d','%d','%d','%d'," + "'%d','%d','%s')", + SQLTableName().GetData(), + roundIndex,itemIndex,player.actualPlayerIndex,playerClass,playerTeam, + playerWeapon,playerAmmo,target.actualPlayerIndex,targetClass, + targetTeam,targetLocation,KillTypeText()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + + return retVal; +} diff --git a/KillData.h b/KillData.h new file mode 100644 index 0000000..c828c24 --- /dev/null +++ b/KillData.h @@ -0,0 +1,61 @@ +#ifndef __KILLDATA +#define __KILLDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class KillData; + +enum KillTypes +{ + KILL_TYPE_KILL=0, + KILL_TYPE_DEATH, + KILL_TYPE_TEAMKILL, + KILL_TYPE_TEAMKILLVICTIM, + KILL_TYPE_TEAMSWAP, + KILL_TYPE_SUICIDE +}; + +#define KILL_TYPE_STRING_UNKNOWN "UNKNOWN" +#define KILL_TYPE_STRING_KILL "KILL" +#define KILL_TYPE_STRING_DEATH "DEATH" +#define KILL_TYPE_STRING_TEAMKILL "TEAMKILL" +#define KILL_TYPE_STRING_TEAMKILLVICTIM "TEAMKILLVICTIM" +#define KILL_TYPE_STRING_SUICIDE "SUICIDE" +#define KILL_TYPE_STRING_TEAMSWAP "TEAMSWAP" + +WX_DECLARE_OBJARRAY(KillData,ArrayOfKillData); +class KillData +{ + public: + KillData(); + virtual ~KillData(); + KillTypes KillType(int gameType,int playerIndex); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int itemIndex); + char *KillTypeText(); + + + wxDateTime killTime; + int gameType; + int mapName; + int playerIndex; + int playerClass; + int playerTeam; + int playerWeapon; + int playerAmmo; + int targetIndex; + int targetClass; + int targetTeam; + int targetDamage; + int targetLocation; + +}; + + +#endif diff --git a/KillTotal.cpp b/KillTotal.cpp new file mode 100644 index 0000000..0fc9aae --- /dev/null +++ b/KillTotal.cpp @@ -0,0 +1,126 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "KillTotal.h" +#include "GlobalStatistics.h" + +KillTotal::KillTotal() +{ + kills=0; + deaths=0; + suicides=0; + teamkills=0; +} + +KillTotal::~KillTotal() +{ +} + +wxString KillTotal::SQLTableName(const char *suffix) +{ + wxString tableName; + + tableName.Printf("killtotal%s",suffix); + + return (tableName); +} + +wxString KillTotal::SQLCreateTable(const char *suffix) +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "itemindex integer," + "playerindex integer," + "kills integer," + "deaths integer," + "suicides integer," + "teamkills integer" + ")", + SQLTableName(suffix).GetData()); + + return SQL; +} + +bool KillTotal::WriteToDatabase(const char *suffix) +{ + wxString SQL; + bool retVal=true; + int actualPlayerIndex; + Player player; + + STATSGEN_DEBUG_FUNCTION_START("KillTotal","WriteToDatabase") + + player=globalStatistics.playerList.Item(playerIndex); + actualPlayerIndex=player.actualPlayerIndex; + + if (actualPlayerIndexitemIndexitemIndex) + { + retVal=-1; + } + else + { + if (total1->itemIndex>total2->itemIndex) + { + retVal=+1; + } + else + { + // check player index + if (total1->playerIndexplayerIndex) + { + retVal=-1; + } + else + { + if (total1->playerIndex>total2->playerIndex) + { + retVal=+1; + } + else + { + retVal=0; + } + } + } + } + + return (retVal); +} + diff --git a/KillTotal.h b/KillTotal.h new file mode 100644 index 0000000..942bd60 --- /dev/null +++ b/KillTotal.h @@ -0,0 +1,34 @@ +#ifndef __KILLTOTAL +#define __KILLTOTAL + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class KillTotal; + +WX_DECLARE_OBJARRAY(KillTotal,ArrayOfKillTotal); +class KillTotal +{ + public: + static int Compare(KillTotal *total1,KillTotal *total2); + KillTotal(); + virtual ~KillTotal(); + + bool WriteToDatabase(const char *suffix); + static wxString SQLTableName(const char *suffix); + static wxString SQLCreateTable(const char *suffix); + int itemIndex; + int playerIndex; + int kills; + int deaths; + int suicides; + int teamkills; + +}; + + +#endif diff --git a/KillTotalLists.cpp b/KillTotalLists.cpp new file mode 100644 index 0000000..c9cc3a8 --- /dev/null +++ b/KillTotalLists.cpp @@ -0,0 +1,191 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "KillTotalLists.h" +#include "KillTotal.h" +#include "KillData.h" +#include "GlobalStatistics.h" + +KillTotalLists::KillTotalLists() +{ +} + +KillTotalLists::~KillTotalLists() +{ +} + +void KillTotalLists::Clear() +{ + maps.Clear(); + gameTypes.Clear(); + weapons.Clear(); + locations.Clear(); + teams.Clear(); + classes.Clear(); +} + +void KillTotalLists::AddKill( + ArrayOfKillTotal &list, + int id, + int killType, + int playerIndex) +{ + KillTotal killTotal; + int killIndex; + int killCount; + bool found; + + killCount=list.GetCount(); + found=false; + for (killIndex=0;killIndex +#include +#include "KillTotal.h" +#include "KillData.h" + +// Statsgen Includes + +class KillTotalLists +{ + public: + ArrayOfKillTotal maps; + ArrayOfKillTotal gameTypes; + ArrayOfKillTotal weapons; + ArrayOfKillTotal locations; + ArrayOfKillTotal teams; + ArrayOfKillTotal classes; + + void WriteToDatabase(); + void WriteToDatabase(ArrayOfKillTotal &list,const char *suffix); + + void Clear(); + void Add( + ArrayOfKillTotal &maps, + ArrayOfKillTotal &gameTypes, + ArrayOfKillTotal &weapons, + ArrayOfKillTotal &locations, + ArrayOfKillTotal &teams, + ArrayOfKillTotal &classes + ); + static void Add(KillData &killData, + int playerIndex, + ArrayOfKillTotal &maps, + ArrayOfKillTotal &gameTypes, + ArrayOfKillTotal &weapons, + ArrayOfKillTotal &locations, + ArrayOfKillTotal &teams, + ArrayOfKillTotal &classes + ); + KillTotalLists(); + ~KillTotalLists(); + void AppendKills( + ArrayOfKillTotal &dest, + ArrayOfKillTotal &source + ); + static void AddKill( + ArrayOfKillTotal &list, + int id, + int killType, + int playerIndex); +}; + + +#endif diff --git a/LogFile.cpp b/LogFile.cpp new file mode 100644 index 0000000..6d3c794 --- /dev/null +++ b/LogFile.cpp @@ -0,0 +1,162 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "LogFile.h" +#include "LogFileReader.h" +#include "COD5LogFileReader.h" +#include "MOHAALogFileReader.h" +#include "ETLogFileReader.h" +#include "GlobalStatistics.h" +#include "Progress.h" +#include "Server.h" + +LogFile::LogFile() +{ + STATSGEN_DEBUG_FUNCTION_START("LogFile","Constructor") + logFileReader=NULL; + serverType=""; + STATSGEN_DEBUG_FUNCTION_END +} + +bool LogFile::Process(Server *server, int serverIndex,long maxLogfileSize) +{ + bool retVal=true; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFile","Process") + if (logFileReader==NULL) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Log file reader is null") + } + else + { + msg="Processing"; + progress->SetStatus(msg); + logFileReader->ProcessLogFile(server,serverIndex,maxLogfileSize); + STATSGEN_DEBUG(DEBUG_ALWAYS,"ran Log file reader") + } + + return (retVal); + STATSGEN_DEBUG_FUNCTION_END +} + +long LogFile::Size() +{ + int fileCount; + int fileIndex; + wxString filename; + long totalFileSize; + + fileCount=filenames.GetCount(); + totalFileSize=0; + for (fileIndex=0;fileIndexFakeTeamIDs(value); + } +} + +bool LogFile::Initiate(wxString &serverTypeIn, wxArrayString &filenameIn) +{ + bool retVal=true; + + if (logFileReader!=NULL) + { + delete(logFileReader); + logFileReader=NULL; + } + serverType=serverTypeIn; + filenames=filenameIn; + + // here we create the LogFileReader appropriate to this logfile + // which is dependent on the serverType + // for now stick with the only one we have which is COD1/2 + if (serverType.Cmp("COD1")==0) + { + logFileReader=new LogFileReader(filenames,serverType); + } + if (serverType.Cmp("COD2")==0) + { + logFileReader=new LogFileReader(filenames,serverType); + } + if (serverType.Cmp("COD4")==0) + { + logFileReader=new LogFileReader(filenames,serverType); + } + if (serverType.Cmp("COD5")==0) + { + logFileReader=new COD5LogFileReader(filenames,serverType); + } + if (serverType.Cmp("MOHAA")==0) + { + logFileReader=new MOHAALogFileReader(filenames,serverType); + } + if (serverType.Cmp("WOLFENSTEIN")==0) + { + logFileReader=new ETLogFileReader(filenames,serverType); + } + + return (retVal); +} + +LogFile::~LogFile() +{ + STATSGEN_DEBUG_FUNCTION_START("LogFile","Destructor") + if (logFileReader!=NULL) + { + delete(logFileReader); + logFileReader=NULL; + } + STATSGEN_DEBUG_FUNCTION_END +} + +void LogFile::StartFromBeginning() +{ + STATSGEN_DEBUG_FUNCTION_START("LogFile","StartFromBeginning") + STATSGEN_DEBUG(DEBUG_ALWAYS,"hello") + if (logFileReader==NULL) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Log file reader is null") + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"About to call StartFromBeginning") + logFileReader->StartFromBeginning(); + STATSGEN_DEBUG(DEBUG_ALWAYS,"Called StartFromBeginning") + } + STATSGEN_DEBUG_FUNCTION_END +} +void LogFile::RetrieveLastRoundPositions(long *lastRoundEndedAt, + long *secondaryLastRoundEndedAt) +{ + *lastRoundEndedAt=0; + *secondaryLastRoundEndedAt=0; + if (logFileReader!=NULL) + { + logFileReader->RetrieveLastRoundPositions(lastRoundEndedAt, + secondaryLastRoundEndedAt); + } +} +void LogFile::SetLastRoundPositions(long lastRoundEndedAt, + long secondaryLastRoundEndedAt) +{ + if (logFileReader!=NULL) + { + logFileReader->SetLastRoundPositions(lastRoundEndedAt, + secondaryLastRoundEndedAt); + } +} diff --git a/LogFile.h b/LogFile.h new file mode 100644 index 0000000..d01e284 --- /dev/null +++ b/LogFile.h @@ -0,0 +1,40 @@ +#ifndef __LOGFILE +#define __LOGFILE + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen includes +#include "LogFileReader.h" + +class LogFile; +class Server; + +WX_DECLARE_OBJARRAY(LogFile,ArrayOfLogFile); +class LogFile +{ + public: + LogFile(); + void FakeTeamIDs(bool value); + bool Process(Server *server,int serverIndex,long maxLogfileSize); + virtual bool Initiate(wxString &serverTypeIn, + wxArrayString &filenamesIn); + virtual long Size(); + virtual ~LogFile(); + void StartFromBeginning(); + void SetLastRoundPositions(long lastRoundEndedAt, + long secondaryLastRoundEndedAt); + void RetrieveLastRoundPositions(long *lastRoundEndedAt, + long *secondaryLastRoundEndedAt); + + protected: + LogFileReader *logFileReader; + wxArrayString filenames; + wxArrayString secondaryFilenames; + wxString serverType; +}; + +#endif diff --git a/LogFileReader.cpp b/LogFileReader.cpp new file mode 100644 index 0000000..ae575b5 --- /dev/null +++ b/LogFileReader.cpp @@ -0,0 +1,956 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "GlobalStatistics.h" +#include "LogFileReader.h" +#include "ErrorData.h" +#include "Round.h" +#include "ConfigData.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "Server.h" +#include "Round.h" +#include "MultiFile.h" + +bool EndsWith(wxString &line,const char *match) +{ + int matchLength; + wxString matchString; + + matchLength=strlen(match); + matchString=line.Right(matchLength); + + return (matchString.Cmp(match)==0); +} + +wxString GetLineToken(wxString &line, + char *sep, + int tokenNumber, + int *tokenCount) +{ + wxStringTokenizer tokens(line,sep); + wxString retVal; + int tokenIndex; + + *tokenCount=tokens.CountTokens(); + + retVal=""; + if (tokenNumber<=*tokenCount) + { + for (tokenIndex=1;tokenIndex<=tokenNumber;tokenIndex++) + { + retVal=tokens.GetNextToken(); + } + } + + return retVal; +} + +LogFileReader::LogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn) +{ + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","Constructor"); + filenames =filenameIn; + serverType =serverTypeIn; + lastRoundEndedAt =0; + fakeTeamIDs =true; + + STATSGEN_DEBUG_FUNCTION_END +} + +void LogFileReader::FakeTeamIDs(bool value) +{ + fakeTeamIDs = value; +} + +wxString LogFileReader::GetServerType() +{ + return (serverType); +} + +bool LogFileReader::DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode) +{ + bool retVal=false; + int tokenCount; + int tokenIndex=0; + wxString name; + wxString id; + wxString roundID; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeTeamLoss"); + + roundID=""; + + if (line.StartsWith("L;")) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Team Loss Found") + decode.Clear(); + decode.teamName=GetLineToken(line,";",2,&tokenCount); + for (tokenIndex=4;tokenIndex<=tokenCount;tokenIndex+=2) + { + id=GetLineToken(line,";",tokenIndex-1,&tokenCount); + name=GetLineToken(line,";",tokenIndex,&tokenCount); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + } + retVal=true; + } + else + { + if (line.StartsWith("RL;")) + { + STATSGEN_DEBUG(DEBUG_RARELY,"COD4 PAM Team Loss Found") + decode.Clear(); + decode.teamName=GetLineToken(line,";",1,&tokenCount); + decode.teamName=""; + for(tokenIndex=3;tokenIndex<=tokenCount;tokenIndex+=2) + { + id=GetLineToken(line,";",tokenIndex-1,&tokenCount); + name=GetLineToken(line,";",tokenIndex,&tokenCount); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + STATSGEN_DEBUG_CODE( + msg.Printf("id[%s] name[%s]",id.GetData(),name.GetData()); + ) + + STATSGEN_DEBUG(DEBUG_RARELY,msg); + } + retVal=true; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool LogFileReader::DecodeTeamWin(wxString &line,DecodedTeamWin &decode) +{ + bool retVal=false; + int tokenCount; + int tokenIndex=0; + wxString name; + wxString id; + wxString roundID; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeTeamWin"); + roundID=""; + + if (line.StartsWith("W;")) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Normal Team Win Found") + decode.Clear(); + decode.teamName=GetLineToken(line,";",2,&tokenCount); + for (tokenIndex=4;tokenIndex<=tokenCount;tokenIndex+=2) + { + id=GetLineToken(line,";",tokenIndex-1,&tokenCount); + name=GetLineToken(line,";",tokenIndex,&tokenCount); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + } + retVal=true; + } + else + { + if (line.StartsWith("RW;")) + { + STATSGEN_DEBUG(DEBUG_RARELY,"COD4 PAM Team Win Found") + decode.Clear(); + decode.teamName=GetLineToken(line,";",1,&tokenCount); + decode.teamName=""; + for(tokenIndex=3;tokenIndex<=tokenCount;tokenIndex+=2) + { + id=GetLineToken(line,";",tokenIndex-1,&tokenCount); + name=GetLineToken(line,";",tokenIndex,&tokenCount); + decode.playerIDs.Add(id); + decode.playerRoundIDs.Add(roundID); + decode.playerNames.Add(name); + STATSGEN_DEBUG_CODE( + msg.Printf("id[%s] name[%s]",id.GetData(),name.GetData()); + ) + + STATSGEN_DEBUG(DEBUG_RARELY,msg); + } + retVal=true; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool LogFileReader::IsWorldPlayer(wxString &id,wxString &team,wxString &name) +{ + bool retVal=false; + + if ((id.Length()==0) && + (name.Length()==0) && + (team.Cmp("world")==0)) + { + retVal=true; + } + + return (retVal); +} + +bool LogFileReader::DecodeKill(wxString &line,DecodedKill &decode) +{ + bool retVal=false; + int tokenCount; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeKill"); + if ((line.StartsWith("D;")) || (line.StartsWith("AD;")) || (line.StartsWith("VD;"))) + { + decode.targetID=GetLineToken(line,";",2,&tokenCount); + decode.targetTeam=GetLineToken(line,";",4,&tokenCount); + decode.playerID=GetLineToken(line,";",6,&tokenCount); + decode.playerTeam=GetLineToken(line,";",8,&tokenCount); + if (fakeTeamIDs) + { + UpdatePlayerRoundInfo2(decode.targetID, + playerIDs, + playerTeamList, + decode.targetTeam); + UpdatePlayerRoundInfo2(decode.playerID, + playerIDs, + playerTeamList, + decode.playerTeam); + } + } + if (line.StartsWith("K;")) + { + decode.targetID=GetLineToken(line,";",2,&tokenCount); + decode.targetRoundID=GetLineToken(line,";",3,&tokenCount); + decode.targetTeam=GetLineToken(line,";",4,&tokenCount); + decode.targetName=GetLineToken(line,";",5,&tokenCount); + decode.targetClass="Soldier"; + decode.playerID=GetLineToken(line,";",6,&tokenCount); + decode.playerRoundID=GetLineToken(line,";",7,&tokenCount); + decode.playerTeam=GetLineToken(line,";",8,&tokenCount); + decode.playerName=GetLineToken(line,";",9,&tokenCount); + decode.playerClass="Soldier"; + decode.playerWeapon=GetLineToken(line,";",10,&tokenCount); + decode.targetDamage=GetLineToken(line,";",11,&tokenCount); + decode.playerAmmo=GetLineToken(line,";",12,&tokenCount); + decode.targetLocation=GetLineToken(line,";",13,&tokenCount); + if ((decode.playerWeapon.Length()==0)|| + (decode.playerWeapon.Cmp("none")==0)) + { + decode.playerWeapon=decode.playerAmmo; + } + if (tokenCount==13) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Kill Found") + retVal=true; + if (decode.targetTeam.Length()==0) + { + decode.targetTeam=FindPlayerRoundInfo2( + decode.targetID, + playerIDs, + playerTeamList, + ""); + } + if (decode.playerTeam.Length()==0) + { + decode.playerTeam=FindPlayerRoundInfo2( + decode.playerID, + playerIDs, + playerTeamList, + ""); + } + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool LogFileReader::DecodeAction(wxString &line,DecodedAction &decode) +{ + bool retVal=false; + int tokenCount; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeAction"); + if (line.StartsWith("A;")) + { + decode.playerID=GetLineToken(line,";",2,&tokenCount); + decode.playerRoundID=GetLineToken(line,";",3,&tokenCount); + decode.playerTeam=GetLineToken(line,";",4,&tokenCount); + decode.playerName=GetLineToken(line,";",5,&tokenCount); + decode.action=GetLineToken(line,";",6,&tokenCount); + if (tokenCount==6) + { + // COD4 Kill Assist is differently organised *sigh* + // Why can't they stick to the rules + // Kill Assist + // playerid;playername;targetid;targetname;action + // playerid = playerid + // playername = playerroundid + // targetid = playerteam + // targetname = playername + // action = action + // if targetid and player id are both hex then this really is + // a cod4 kill assist + if (IsHexString(decode.playerID) && IsHexString(decode.playerTeam)) + { + decode.playerName =decode.playerRoundID; + decode.playerRoundID =""; + decode.playerTeam =""; + STATSGEN_DEBUG(DEBUG_RARELY,"COD4 Kill Assist Action Found") + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Normal Action Found") + } + retVal=true; + } + if (tokenCount==4) + { + STATSGEN_DEBUG(DEBUG_RARELY,"COD4 PAM MOD activity") + decode.action=decode.playerID; + decode.playerID=decode.playerRoundID; + decode.playerName=decode.playerTeam; + + decode.playerRoundID=""; + decode.playerTeam=""; + STATSGEN_DEBUG_CODE( + msg.Printf("id[%s] name[%s] action[%s]", + decode.playerID.GetData(), + decode.playerName.GetData(), + decode.action.GetData()); + ) + retVal=true; + STATSGEN_DEBUG(DEBUG_RARELY,msg) + } + if (tokenCount==5) + { + if ((decode.playerTeam.IsNumber()) && + (decode.playerName.StartsWith("shots_"))) + { + // COD4 PAM MOD + // 4th token a numeric, 5th token shots_fired or shots_hit + // not really a action + retVal=false; + STATSGEN_DEBUG(DEBUG_RARELY,"COD4 PAM MOD Action Found") + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Extreme MOD Action Found") + // This is a (extreme) mod with no team line + decode.action=decode.playerName; + decode.playerName=decode.playerTeam; + decode.playerTeam=""; + retVal=true; + } + } + } + if (line.StartsWith("heal;")) + { + decode.playerID=""; + decode.playerRoundID=GetLineToken(line,";",2,&tokenCount); + decode.playerTeam=""; + decode.playerName=GetLineToken(line,";",3,&tokenCount); + decode.action=GetLineToken(line,";",1,&tokenCount); + if (tokenCount==5) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Admiral Action Found") + retVal=true; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool LogFileReader::DecodeSpeech(wxString &line,DecodedSpeech &decode) +{ + bool retVal=false; + int tokenCount; + Player player; + PlayerInRound playerInRound; + int playerInRoundCount; + int playerInRoundIndex; + wxString decolouredName; + bool found; + wxString tempGUID; + + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","DecodeSpeech"); + + if ((line.StartsWith("say;"))|| + (line.StartsWith("sayteam;"))) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Speech Found") + decode.playerID=GetLineToken(line,";",2,&tokenCount); + decode.playerRoundID=GetLineToken(line,";",3,&tokenCount); + decode.playerName=GetLineToken(line,";",4,&tokenCount); + decode.speech=GetLineToken(line,";",5,&tokenCount); + + tempGUID=serverType+"_"+decode.playerID; + + // Speech does not bother with the colour codes + // Search current round for a decoloured name that matches this one + found = false; + playerInRoundCount=currentRound.playersInRound.GetCount(); + for (playerInRoundIndex=0; + playerInRoundIndexlogfileVariableKeys.Clear(); + round->logfileVariableValues.Clear(); + remainder=line.AfterFirst(' '); + key=GetLineToken(remainder,"\\",1,&tokenCount); + for (tokenIndex=1;tokenIndex<=tokenCount;tokenIndex++) + { + if ((tokenIndex % 2)!=0) + { + // odd numbers are the values + value=GetLineToken(remainder,"\\",tokenIndex,&tokenCount); + // We have decoded a value - the key should represent what + // it means + if (key.CmpNoCase("g_gametype")==0) + { + decode.gameType=value; + gameTypeFound=true; + } + else + if (key.CmpNoCase("mapname")==0) + { + decode.mapName=value; + mapFound=true; + } + else + { + if (tokenIndex>1) + { + thisServer->AddVariable(key,value); + round->AddVariable(key,value); + } + } + + } + else + { + // even numbers are the keys + key=GetLineToken(remainder,"\\",tokenIndex,&tokenCount); + } + } + if (gameTypeFound && mapFound) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Round Start Found") + retVal=true; + } + } + else + { + // Not a Start Round + retVal=false; + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool LogFileReader::IsRoundStart(wxString &line) +{ + bool retVal; + + retVal=false; + if (line.StartsWith("InitGame:")) + { + retVal=true; + } + + return (retVal); +} + +bool LogFileReader::IsRoundEnd(wxString &line) +{ + bool retVal; + + retVal=false; + if ((line.StartsWith("ShutdownGame:"))|| + (line.StartsWith("ExitLevel:"))|| + (line.StartsWith("RestartGame:")) + ) + + { + retVal=true; + } + + return (retVal); +} + +bool LogFileReader::StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime) +{ + bool retVal=false; + wxString timeString; + wxString remainder; + wxString minuteString; + wxString secondString; + int minutes=0; + int seconds=0; + time_t since1970; + + + timeString=lineRead.BeforeFirst(' '); + remainder=lineRead.AfterFirst(' '); + lineRead=remainder; + + timeString.Trim(true); + timeString.Trim(false); + + if (timeString.IsNumber()) + { + since1970=atoi(timeString.GetData()); + lineTime.Set(since1970); + retVal=true; + } + else + { + minuteString=timeString.BeforeFirst(':'); + secondString=timeString.AfterFirst(':'); + if (minuteString.IsNumber() && + secondString.IsNumber()) + { + retVal=true; + minutes=atoi(minuteString.GetData()); + seconds=atoi(secondString.GetData()); + since1970=(60*minutes)+seconds; + lineTime.Set(since1970); + } + else + { + retVal=false; + } + } + return(retVal); +} + +wxString LogFileReader::ReadLine(MultiFile &logfile, + ErrorData &errorData) +{ + unsigned char charRead; + bool endOfLine=false; + wxString lineRead; + + lineRead=""; + while (!endOfLine && !logfile.Eof()) + { + charRead=logfile.GetC(); + if (charRead=='\n') + { + endOfLine=true; + } + else + if (charRead=='\r') + { + endOfLine=true; + } + else + if (charRead>=' ') + { + // Printable character + lineRead+=charRead; + } + else + { + // Corrupted character - don't add to line + } + } + + return(lineRead); +} + +void LogFileReader::ProcessLogFile(Server *server,int serverIndex,long maxLogfileSize) +{ + MultiFile logfile(filenames); + wxString errorMessage; + wxFileOffset logfileSize=0; + bool inRound=false; + wxString lineRead; + bool result; + wxDateTime lineTime; + int roundCount; + int roundIndex; + off_t currentFilePosition; + wxString msg; + ErrorData errorData; + int lineNumber=0; + long maxLogfilePosition=0; + + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","ProcessLogFile") + thisServer=server; + if (logfile.Ok()) + { + // File appears to be open + + logfileSize=logfile.Length(); + if (logfileSize0) + { + maxLogfilePosition=lastRoundEndedAt+(1024*1024*maxLogfileSize); + } + else + { + maxLogfilePosition=0; + } + STATSGEN_DEBUG_CODE(msg.Printf("Last Round Ended At %ld",lastRoundEndedAt);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + while (!logfile.Eof() && errorData.IsOK()) + { + // Read each line in turn + // Stripping leading and trailing spaces + currentFilePosition=logfile.TellI(); + progress->Update(currentFilePosition); + lineRead=ReadLine(logfile,errorData); + lineRead.Trim(true); + lineRead.Trim(false); + lineNumber++; + STATSGEN_DEBUG_CODE(msg.Printf("%9d %s",lineNumber,lineRead.GetData());) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + if (lineRead.Length()>0) + { + // Line contains something + result=StripTimeFromLine(lineRead,lineTime); + if (result) + { + // Line has a valid time field + if (IsRoundStart(lineRead)) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Round Start Encountered") + // Start of round encountered + if (inRound) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Old Round Ended.Starting new round") + // We were already in a round + // Strange situation - new round started + // without old round ending + // Just store current round and start again + currentRound.Process(errorData,serverIndex); + //currentRound.Debug(); + globalStatistics.rounds.Add(currentRound); + currentRound.Initiate(this, + lineTime, + lineRead); + lastRoundEndedAt=currentFilePosition; + } + else + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Starting new round") + // We were not in a previous round + // so we just need to create a new round + currentRound.Initiate(this, + lineTime, + lineRead); + } + inRound=true; + } + else + if (IsRoundEnd(lineRead)) + { + + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Round End encountered") + // Reached end of a round + if (inRound) + { + // Reached end of an active round + currentRound.AddLogLine(lineTime,lineRead); + currentRound.Process(errorData,serverIndex); + //currentRound.Debug(); + globalStatistics.rounds.Add(currentRound); + lastRoundEndedAt=logfile.TellI(); + } + else + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Not In Round:Line Discarded") + // End of an inactive round (start of logfile) + // or Start Of Round got corrupted/not recorded. + // Just throw away this round + } + inRound=false; + } + else + { + // Some other sort of line - just add it + currentRound.AddLogLine(lineTime,lineRead); + } + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Bad Time Field") + // Line does not have a valid time field + // Ignore + } + } + else + { + // Line is zero length - ignore + } + if ((maxLogfilePosition>0) && (lastRoundEndedAt>maxLogfilePosition)) + { + // Reached the limit for this process run + break; + } + } + // End of file processed + // Search through removing all the dropped rounds + roundCount=globalStatistics.rounds.GetCount(); + roundIndex=0; + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Dropping Inactive Rounds") + while (roundIndexLogError(errorMessage,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + } + STATSGEN_DEBUG_FUNCTION_END +} + +LogFileReader::~LogFileReader() +{ +} + +void LogFileReader::StartFromBeginning() +{ + STATSGEN_DEBUG_FUNCTION_START("LogFileReader","StartFromBeginning") + lastRoundEndedAt=0; + STATSGEN_DEBUG_FUNCTION_END +} + +void LogFileReader::RetrieveLastRoundPositions(long *lastRoundEndedAtOut, + long *secondaryLastRoundEndedAtOut) +{ + *lastRoundEndedAtOut=lastRoundEndedAt; + *secondaryLastRoundEndedAtOut=lastRoundEndedAt; +} +void LogFileReader::SetLastRoundPositions(long lastRoundEndedAtIn, + long secondaryLastRoundEndedAtIn) +{ + + lastRoundEndedAt=lastRoundEndedAtIn; + secondaryLastRoundEndedAt=lastRoundEndedAtIn; +} + +wxString LogFileReader::FindPlayerRoundInfo2(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + char *defaultValue) +{ + wxString retVal=defaultValue; + int listCount; + int listIndex; + wxString listname; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","FindPlayerRoundInfo") + listCount=listnames.GetCount(); + + STATSGEN_DEBUG(DEBUG_RARELY,name) + for (listIndex=0;listIndex +#include +#include +#include +#include + +// statsgen includes +#include "ErrorData.h" +#include "Round.h" +#include "MultiFile.h" + +#define WORLD_PLAYER_NAME "STATSGENWORLDPLAYER" +#define WORLD_PLAYER_ID "STATSGENWORLDID" +#define WORLD_PLAYER_TEAM "STATSGENWORLDTEAM" +#define WORLD_PLAYER_CLASS "STATSGENWORLDCLASS" + +void StatsgenDebug(char *message); +void StatsgenDebug(wxString &message); +bool EndsWith(wxString &source,const char *match); +wxString GetLineToken(wxString &line, + char *sep, + int tokenNumber, + int *tokenCount); + +enum LogFileLineTypes +{ + LOG_LINE_TYPE_NOTHING=0, + LOG_LINE_TYPE_START_ROUND, + LOG_LINE_TYPE_END_ROUND, + LOG_LINE_TYPE_JOIN_GAME, + LOG_LINE_TYPE_LEAVE_GAME, + LOG_LINE_TYPE_ACTION, + LOG_LINE_TYPE_KILL, + LOG_LINE_TYPE_DAMAGE, + LOG_LINE_TYPE_SPEECH, + LOG_LINE_TYPE_TEAM_WIN, + LOG_LINE_TYPE_TEAM_LOSS +}; + +class Server; + +class LogFileReader +{ + public: + void FakeTeamIDs(bool value); + virtual bool IsWorldPlayer(wxString &id,wxString &team,wxString &name); + LogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn); + virtual ~LogFileReader(); + virtual void ProcessLogFile(Server *server,int serverIndex,long maxLogfileSize); + virtual bool DecodeRoundStart(wxString &line,DecodedRoundStart &decode,Round *round); + virtual bool DecodePlayerJoin(wxString &line,DecodedPlayerJoin &decode); + virtual bool DecodePlayerQuit(wxString &line,DecodedPlayerQuit &decode); + virtual bool DecodeKill(wxString &line,DecodedKill &decode); + virtual bool DecodeTeamWin(wxString &line,DecodedTeamWin &decode); + virtual bool DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode); + virtual bool DecodeAction(wxString &line,DecodedAction &decode); + virtual bool DecodeSpeech(wxString &line,DecodedSpeech &decode); + wxString GetServerType(); + void StartFromBeginning(); + void SetLastRoundPositions(long lastRoundEndedAt, + long secondaryLastRoundEndedAt); + void RetrieveLastRoundPositions(long *lastRoundEndedAt, + long *secondaryLastRoundEndedAt); + + protected: + wxString FindPlayerRoundInfo2(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + char *defaultValue); + void UpdatePlayerRoundInfo2(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + wxString &id); + wxArrayString playerIDs; + wxArrayString playerTeamList; + bool DecodeInitGame(wxString &line,DecodedRoundStart &decode,Round *round); + virtual bool StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime); + virtual bool IsRoundStart(wxString &line); + virtual bool IsRoundEnd(wxString &line); + + Round currentRound; + + wxString serverType; + Server *thisServer; + bool fakeTeamIDs; + + protected: + wxString ReadLine(MultiFile &logfile, + ErrorData &errorData); + + wxArrayString filenames; + off_t lastRoundEndedAt; + off_t secondaryLastRoundEndedAt; + +}; + +#endif diff --git a/MOHAALogFileReader.cpp b/MOHAALogFileReader.cpp new file mode 100644 index 0000000..919ce2e --- /dev/null +++ b/MOHAALogFileReader.cpp @@ -0,0 +1,784 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "GlobalStatistics.h" +#include "MOHAALogFileReader.h" +#include "ErrorData.h" +#include "Round.h" +#include "ConfigData.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "Server.h" +#include "Round.h" + +void MOHAALogFileReader::NextSubexpression(wxString ®ularExpressionString, + int *charIndex, + wxString &idFound, + wxString &replacementString) +{ + // Need to scan through from charIndex onwards + // looking for either "(.+)", "$$id=replacement$$", "$$id$$" + // as soon as we find any of these we decode them and return + // the values + + wxString stringToCheck; + int terminatorIndex; + + idFound=""; + replacementString=""; + stringToCheck=regularExpressionString.Mid(*charIndex); + while (stringToCheck.Length()>0) + { + stringToCheck=regularExpressionString.Mid(*charIndex); + if (stringToCheck.StartsWith("(.+)")) + { + break; + } + if (stringToCheck.StartsWith("$$")) + { + // Skip past the initial $$ + stringToCheck=stringToCheck.Mid(2); + // find the terminating $$ + terminatorIndex=stringToCheck.Find("$$"); + if (terminatorIndex<0) + { + // no terminating $$ - sod it just go to the end of the line + terminatorIndex=stringToCheck.Length(); + } + // strip off the terminating $$ + stringToCheck=stringToCheck.Left(terminatorIndex); + idFound=stringToCheck.BeforeFirst('='); + replacementString=stringToCheck.AfterFirst('='); + break; + } + (*charIndex)++; + } +} + + +void MOHAALogFileReader::UpdateRegularExpression(char *id, + wxString ®ularExpressionString, + wxArrayString *replacements, + wxArrayInt *subexpressionIndex) +{ + int charIndex; + wxString idFound; + wxString replacementString; + int expressionIndex; + wxString originalString; + bool foundIt; + + expressionIndex=1; + charIndex=0; + // scan through each expression in the regular expression + // until we find the one we are checking for + foundIt=false; + while (charIndex0) + { + originalString.Printf("$$%s=%s$$", + idFound.GetData(), + replacementString.GetData()); + regularExpressionString.Replace(originalString.GetData(),""); + originalString=""; // to make it move on 1 character + } + else + { + originalString.Printf("$$%s$$", + idFound.GetData()); + regularExpressionString.Replace(originalString.GetData(),"(.+)"); + originalString="(.+)"; + } + if (replacements!=NULL) + { + replacements->Add(replacementString); + } + if (replacementString.Length()>0) + { + // this is a replacement line - it is not a match + // so add the -1 to the expression index + subexpressionIndex->Add(-1); + } + else + { + subexpressionIndex->Add(expressionIndex); + } + } + else + { + // Found an expression - but it is not the one we want + if (idFound.Length()==0) + { + // No ID Found so originalString must be a straight subexpression + originalString="(.+)"; + } + else + { + // ID found (not appropriate to this id) - so it needs to be skipped past + if (replacementString.Length()>0) + { + originalString.Printf("$$%s=%s$$", + idFound.GetData(), + replacementString.GetData()); + } + else + { + originalString.Printf("$$%s$$", + idFound.GetData()); + } + } + // move onto next expression + expressionIndex++; + } + // skip past the subexpression in the string + charIndex+=(originalString.Length()); + if (foundIt) + { + break; + } + } + if (!foundIt) + { + subexpressionIndex->Add(-1); + replacementString=""; + if (replacements!=NULL) + { + replacements->Add(replacementString); + } + } +} + +MOHAALogFileReader::MOHAALogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn): LogFileReader(filenameIn,serverTypeIn) +{ + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","Constructor"); + wxString configGroup; + int expressionCount; + int expressionIndex; + wxString regularExpressionString; + wxString msg; + wxString dummy; + int dummyInt; + wxRegEx *regExp; + + configGroup="LINEID"+serverType; + globalStatistics.configData.ReadList(configGroup,regularExpressionLines); + expressionCount=regularExpressionLines.GetCount(); + for (expressionIndex=0;expressionIndex")==0)) + { + retVal=true; + } + + return (retVal); +} + +bool MOHAALogFileReader::MatchingExpression(wxString &line, + char *idCode, + int *expressionIndex) +{ + int expressionCount; + bool retVal=false; + wxRegEx *regExp; + wxString regExpString; + wxString idCodeString; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","MatchingExpression") + + expressionCount=compiledRegularExpressions.GetCount(); + for ((*expressionIndex)=0; + (*expressionIndex)Matches(line.GetData()); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Found matching expression"); + regExpString=regularExpressionLines.Item(*expressionIndex); + idCodeString=regExpString.BeforeFirst(','); + if (idCodeString.Length()>0) + { + *idCode=idCodeString[0]; + } + else + { + *idCode=' '; + } + break; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +wxString MOHAALogFileReader::RetrieveRegularExpMatch( + wxString &line, + int expressionIndex, + wxArrayInt *subexpressions, + wxArrayString *replacements) +{ + wxString retVal=""; + wxRegEx *regExp; + int subexpressionIndex; + wxString replacement; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","RetrieveRegularExpMatch") + if (replacements!=NULL) + { + replacement=replacements->Item(expressionIndex); + } + else + { + replacement=""; + } + subexpressionIndex=subexpressions->Item(expressionIndex); + if (subexpressionIndex<0) + { + // subexpression not appropriate - return the replacement value + retVal=replacement; + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Using subexpression") + // need to retrieve the match + regExp=(wxRegEx *)compiledRegularExpressions.Item(expressionIndex); + retVal=regExp->GetMatch(line,subexpressionIndex); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +wxString MOHAALogFileReader::FindPlayerRoundInfo(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + char *defaultValue) +{ + wxString retVal=defaultValue; + int listCount; + int listIndex; + wxString listname; + + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","FindPlayerRoundInfo") + listCount=listnames.GetCount(); + + STATSGEN_DEBUG(DEBUG_RARELY,name) + for (listIndex=0;listIndex0) + { + destination=source; + } +} + +bool MOHAALogFileReader::DecodeRoundStart(wxString &line, + DecodedRoundStart &decode, + Round *round) +{ + bool retVal=false; + wxString combinedString; + char idCode; + int expressionIndex; + wxString msg; + wxString replacement; + + STATSGEN_DEBUG_FUNCTION_START("MOHAALogFileReader","DecodeRoundStart"); + + if (MatchingExpression(line,&idCode,&expressionIndex)) + { + STATSGEN_DEBUG(DEBUG_RARELY,line) + if (idCode == 'R') + { + STATSGEN_DEBUG_CODE(msg.Printf("Round Start found [%s]",line.GetData());) + STATSGEN_DEBUG(DEBUG_RARELY,msg); + playerTeamListNames.Clear(); + playerTeamList.Clear(); + playerClassListNames.Clear(); + playerClassList.Clear(); + playerIDListNames.Clear(); + playerIDList.Clear(); + round->logfileVariableKeys.Clear(); + round->logfileVariableValues.Clear(); + retVal=true; + // This is a Round Start + UpdateValue(decode.mapName,RetrieveRegularExpMatch(line,expressionIndex,&subexpressionIndexMap,&replacementMap)); + UpdateValue(decode.gameType,RetrieveRegularExpMatch(line,expressionIndex,&subexpressionIndexGameType,&replacementGameType)); + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool MOHAALogFileReader::IsRoundStart(wxString &line) +{ + bool retVal; + char idCode; + int expressionIndex; + retVal=false; + retVal=(line.StartsWith("Server:")); + + if (!retVal) + { + if (MatchingExpression(line,&idCode,&expressionIndex)) + { + if (idCode == 'R') + { + retVal=true; + } + } + } + return (retVal); +} + +bool MOHAALogFileReader::IsRoundEnd(wxString &line) +{ + bool retVal; + + retVal=false; + retVal=(line.StartsWith("==== ShutdownGame ====")); + + return (retVal); +} + +bool MOHAALogFileReader::StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime) +{ + bool retVal=false; + int minutes=0; + int seconds=0; + time_t since1970; + + + retVal=true; + since1970=(60*minutes)+seconds; + lineTime.Set(since1970); + + return(retVal); +} + +MOHAALogFileReader::~MOHAALogFileReader() +{ + // delete the regular expressions + int expressionCount; + int expressionIndex; + wxRegEx *regExp; + + expressionCount=compiledRegularExpressions.GetCount(); + for (expressionIndex=0;expressionIndex +#include +#include +#include +#include + +// statsgen includes +#include "ErrorData.h" +#include "Round.h" +#include "LogFileReader.h" +#include "DynamicArrays.h" + +class MOHAALogFileReader:public LogFileReader +{ + public: + virtual bool IsWorldPlayer(wxString &id,wxString &team,wxString &name); + MOHAALogFileReader(wxArrayString &filenameIn,wxString &serverTypeIn); + virtual ~MOHAALogFileReader(); + virtual bool DecodeRoundStart(wxString &line,DecodedRoundStart &decode,Round *round); + virtual bool DecodePlayerJoin(wxString &line,DecodedPlayerJoin &decode); + virtual bool DecodePlayerQuit(wxString &line,DecodedPlayerQuit &decode); + virtual bool DecodeKill(wxString &line,DecodedKill &decode); + virtual bool DecodeTeamWin(wxString &line,DecodedTeamWin &decode); + virtual bool DecodeTeamLoss(wxString &line,DecodedTeamLoss &decode); + virtual bool DecodeAction(wxString &line,DecodedAction &decode); + virtual bool DecodeSpeech(wxString &line,DecodedSpeech &decode); + + protected: + bool DecodeClientUserinfoChanged(wxString &line, + wxString &inRoundID, + wxString &name, + wxString &teamname, + wxString &classname); + void UpdateValue(wxString &destination,wxString source); + wxString FindPlayerRoundInfo(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + char *defaultValue); + void UpdatePlayerRoundInfo(wxString &name, + wxArrayString &listnames, + wxArrayString &listIDs, + wxString &id); + void UpdateRegularExpression(char *id, + wxString ®ularExpressionString, + wxArrayString *replacements, + wxArrayInt *subexpressionIndex); + void NextSubexpression(wxString ®ularExpressionString, + int *charIndex, + wxString &idFound, + wxString &replacementString); + + virtual bool StripTimeFromLine(wxString &lineRead,wxDateTime &lineTime); + virtual bool IsRoundStart(wxString &line); + virtual bool IsRoundEnd(wxString &line); + + wxArrayString regularExpressionLines; + wxArrayString replacementPlayerWeapon; + wxArrayString replacementPlayerAmmo; + wxArrayString replacementTargetLocation; + wxArrayString replacementAction; + wxArrayString replacementPlayerTeam; + wxArrayString replacementPlayerClass; + wxArrayString replacementTargetTeam; + wxArrayString replacementTargetClass; + wxArrayString replacementMap; + wxArrayString replacementGameType; + + wxArrayString playerTeamListNames; + wxArrayString playerTeamList; + wxArrayString playerClassListNames; + wxArrayString playerClassList; + wxArrayString playerIDListNames; + wxArrayString playerIDList; + + wxArrayInt subexpressionIndexMap; + wxArrayInt subexpressionIndexGameType; + wxArrayInt subexpressionIndexPlayerName; + wxArrayInt subexpressionIndexPlayerGUID; + wxArrayInt subexpressionIndexPlayerInRoundID; + wxArrayInt subexpressionIndexTargetName; + wxArrayInt subexpressionIndexTargetGUID; + wxArrayInt subexpressionIndexPlayerWeapon; + wxArrayInt subexpressionIndexPlayerAmmo; + wxArrayInt subexpressionIndexTargetLocation; + wxArrayInt subexpressionIndexAction; + wxArrayInt subexpressionIndexSpeech; + wxArrayInt subexpressionIndexPlayerClass; + wxArrayInt subexpressionIndexPlayerTeam; + wxArrayInt subexpressionIndexTargetClass; + wxArrayInt subexpressionIndexTargetTeam; + ArrayOfPointers compiledRegularExpressions; + wxString RetrieveRegularExpMatch(wxString &line, + int expressionIndex, + wxArrayInt *subexpressions, + wxArrayString *replacements); + bool MatchingExpression(wxString &line, + char *idCode, + int *expressionIndex); + + + private: +}; + +#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..39d9192 --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +WXWIDGETS_BASE=../../wxWidgets-3.1.1 +WXWIDGETS_BUILD=${WXWIDGETS_BASE}/build +SQLITE_BASE=../../sqlite-autoconf-3260000 +SQLITE_BUILD=${SQLITE_BASE}/build + +DEBUG_FLAG=-DDEBUG + +STATSGEN_WEBSITE_ADDRESS="www.statsgen.co.uk" +STATSGEN_WEBSITE_PORT="80" + +#STATSGEN_WEBSITE_ADDRESS="localhost" +#STATSGEN_WEBSITE_PORT="8000" + +STATSGEN_COMPILER_OPTIONS=${DEBUG_FLAG} -DSTATSGEN_WEBSITE_ADDRESS=\"${STATSGEN_WEBSITE_ADDRESS}\" -DSTATSGEN_WEBSITE_PORT=${STATSGEN_WEBSITE_PORT} -static-libgcc -static-libstdc++ +APP=statsgen2.exe +OBJECTS=AKAListEntry.o ActionData.o AliasCacheEntry.o AliasDialog.o AliasEditorPanel.o AliasListEntry.o AwardDefinition.o AwardEditorPanel.o BaseConfigItemGui.o BooleanConfigItemGUI.o BoxedDropDown.o COD5LogFileReader.o CODBanFile.o Cheater.o Clan.o ClanEditorPanel.o ConfigData.o ConfigEditorGUI.o ConfigItem.o ContentTypes.o DefaultTemplate1.o DefaultTemplate2.o DirectoryConfigItemGUI.o DropList.o DropListDialog.o DropListEditorPanel.o DropListEntry.o DynamicArrays.o ETLogFileReader.o ErrorData.o ErrorPanel.o FTPBrowserPanel.o FTPConnectionPanel.o FileConfigItemGUI.o GUITriggerItem.o GUITriggerList.o GenericConfigGUI.o GenericConfigPanel.o GenericKey.o GenericNumberedConfigGUI.o GenericNumberedConfigPanel.o GenericOKCancelDialog.o GroupedConfigItemsPanel.o ImagePanel.o ImageTypePanel.o KeyedIndex.o KillData.o KillTotal.o KillTotalLists.o LogFile.o LogFileReader.o MOHAALogFileReader.o MessageCentre.o MultiFile.o PerformUpgradeDialog.o Player.o PlayerCacheEntry.o PlayerDataDialog.o PlayerDataEditorPanel.o PlayerDataEntry.o PlayerDataList.o PlayerInRound.o PlayerList.o PriorityPanel.o Progress.o ProgressPanel.o PunkbusterBanFile.o QuakeWarsLogFile.o QuakeWarsLogFileReader.o RemoteDirectoryConfigItemGUI.o RemoteFileConfigItemGUI.o Round.o ScheduleConfigItemGUI.o ScheduleDialog.o ScheduleEditorPanel.o ScheduleItem.o SelectionConfigItemGUI.o SelectionFreeFormConfigItemGUI.o Server.o ServerTypePanel.o SkillTypePanel.o SpeechData.o StaticFunctions.o StatsgenDatabase.o StatsgenFrame.o StatsgenLog.o StatsgenWeb.o StatusPanel.o StreakData.o TeamLossData.o TeamWinData.o TemplateFile.o TemplateOpenFile.o TemplateOpenQuery.o TemplateVariable.o TemplateVariableField.o TextConfigItemGUI.o TextListDialog.o TextListEditorPanel.o WeaponGroupDialog.o WebFile.o WebServer.o WebServerRequestHandler.o Website.o WebsiteConfigGUI.o WeightList.o WeightListEntry.o XPPoints.o XPTotals.o PlayerCachePanel.o GlobalStatistics.o ExternalDatabase.o RemoteMachine.o RestartingFTP.o StatsgenApp.o GUIWizards.o ResizingListCtrl.o +HEADERS=AKAListEntry.h ActionData.h AliasCacheEntry.h AliasDialog.h AliasEditorPanel.h AliasListEntry.h AwardDefinition.h AwardEditorPanel.h BaseConfigItemGUI.h BooleanConfigItemGUI.h BoxedDropDown.h COD5LogFileReader.h CODBanFile.h Cheater.h Clan.h ClanEditorPanel.h ConfigData.h ConfigEditorGUI.h ConfigItem.h ContentTypes.h DirectoryConfigItemGUI.h DropList.h DropListDialog.h DropListEditorPanel.h DropListEntry.h DynamicArrays.h ETLogFileReader.h ErrorData.h ErrorPanel.h FTPBrowserPanel.h FTPConnectionPanel.h FileConfigItemGUI.h GUITriggerItem.h GUITriggerList.h GUIWizards.h GenericConfigGUI.h GenericConfigPanel.h GenericKey.h GenericNumberedConfigGUI.h GenericNumberedConfigPanel.h GenericOKCancelDialog.h GlobalStatistics.h GroupedConfigItemsPanel.h ImagePanel.h ImageTypePanel.h KeyedIndex.h KillData.h KillTotal.h KillTotalLists.h LogFile.h LogFileReader.h MOHAALogFileReader.h MessageCentre.h MultiFile.h PerformUpgradeDialog.h Player.h PlayerCacheEntry.h PlayerCachePanel.h PlayerDataDialog.h PlayerDataEditorPanel.h PlayerDataEntry.h PlayerDataList.h PlayerInRound.h PlayerList.h PriorityPanel.h Progress.h ProgressPanel.h PunkbusterBanFile.h QuakeWarsLogFile.h QuakeWarsLogFileReader.h RemoteDirectoryConfigItemGUI.h RemoteFileConfigItemGUI.h RemoteMachine.h RestartingFTP.h Round.h ScheduleConfigItemGUI.h ScheduleDialog.h ScheduleEditorPanel.h ScheduleItem.h SelectionConfigItemGUI.h SelectionFreeFormConfigItemGUI.h Server.h ServerTypePanel.h SkillTypePanel.h SpeechData.h StaticFunctions.h StatsgenApp.h StatsgenDatabase.h StatsgenFrame.h StatsgenLog.h StatsgenWeb.h StatusPanel.h StreakData.h TeamLossData.h TeamWinData.h TemplateFile.h TemplateOpenFile.h TemplateOpenQuery.h TemplateVariable.h TemplateVariableField.h TextConfigItemGUI.h TextListDialog.h TextListEditorPanel.h Version.h WeaponGroupDialog.h WebFile.h WebServer.h WebServerRequestHandler.h Website.h WebsiteConfigGUI.h WeightList.h WeightListEntry.h WindowIDs.h XPPoints.h XPTotals.h statsgen2_private.h ExternalDatabase.h +RESOURCE_OBJECTS=bitmaps.o + +WXCONFIG=${WXWIDGETS_BUILD}/wx-config +SQLITE_OBJECTS=${SQLITE_BUILD}/sqlite3.o +SQLITE_INCLUDE_DIR=${SQLITE_BASE} +WX_LIBS=`${WXCONFIG} --libs` +WX_INCS=`${WXCONFIG} --cppflags` + +COMPILER=g++ +COMPILER_OPTIONS=${WX_INCS} -I. -g -I${SQLITE_INCLUDE_DIR} ${STATSGEN_COMPILER_OPTIONS} + +LINKER=g++ +LINKER_OPTIONS=${WX_LIBS} + +RESOURCE_COMPILER=windres.exe +RESOURCE_COMPILER_OPTIONS=-O coff +RESOURCE_OBJECTS=bitmaps.o maindetails.o + +.SUFFIXES: .cpp .o +.SUFFIXES: .rc .o +.h.cpp: +all:${APP} + +clean: + @rm ${OBJECTS} + @rm ${APP} + +${APP}:${OBJECTS} ${RESOURCE_OBJECTS} + ${LINKER} -o ${APP} ${OBJECTS} ${SQLITE_OBJECTS} ${RESOURCE_OBJECTS} ${LINKER_OPTIONS} + #cp ${APP} testrun + #cp statsgen2.ini testrun + +.cpp.o: ${HEADERS} + ${COMPILER} ${COMPILER_OPTIONS} -c $< + + +.rc.o: ${RESOURCE_OBJECTS} + ${RESOURCE_COMPILER} ${RESOURCE_COMPILER_OPTIONS} -i $< -o $@ + + diff --git a/MessageCentre.cpp b/MessageCentre.cpp new file mode 100644 index 0000000..c9eea6c --- /dev/null +++ b/MessageCentre.cpp @@ -0,0 +1,497 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "ErrorData.h" +#include "GlobalStatistics.h" +#include "MessageCentre.h" +#include "RemoteMachine.h" +#include "Progress.h" +#include "StaticFunctions.h" + +#define MESSAGE_CENTRE_PREFIX "Statsgen2:^7" +#define MESSAGE_CENTRE_PREFIX_HIDDEN "" +MessageCentre::MessageCentre() +{ + ID=""; + messageIndex=0; + overallEnabled=false; + serverEnabled=false; + usingPunkbuster=false; + messagePrefix=""; +} + +MessageCentre::~MessageCentre() +{ +} + +void MessageCentre::SetID(wxString &IDIn) +{ + ID=IDIn; +} + +void MessageCentre::Initiate() +{ + wxString configBaseKey; + wxString configKey; + wxString configValue; + wxArrayString configKeys; + wxArrayString configValues; + int formatIndex; + int formatCount; + wxString format; + wxString key; + wxString msg; + wxArrayString tokenValues; + wxArrayString customMessages; + wxArrayString workingMessages; + wxString configGroup; + int customMessageInterval; + int customMessageCount; + int customMessageIndex; + int workingMessageCount; + + STATSGEN_DEBUG_FUNCTION_START("MessageCentre","Initiate") + + serverEnabled=false; + if (ID.Length()>0) + { + // Read in the configuration items for this server + configBaseKey="/Server"+ID; + configBaseKey+="/"; + + configKey=configBaseKey+"serverType"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + serverType=configValue; + + configKey=configBaseKey+"gameIP"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + gameIP=configValue; + STATSGEN_DEBUG(DEBUG_ALWAYS,configValue) + + configKey=configBaseKey+"gamePort"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + STATSGEN_DEBUG(DEBUG_ALWAYS,configValue) + gamePort=-1; + if (configValue.Length()>0) + { + gamePort=atoi(configValue.GetData()); + } + + configKey="/RCONSettings/ClientPort"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"8000"); + STATSGEN_DEBUG(DEBUG_ALWAYS,configValue) + localPort=-1; + if (configValue.Length()>0) + { + localPort=atoi(configValue.GetData()); + } + + configKey=configBaseKey+"IPAddress"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + hostname=configValue; + STATSGEN_DEBUG(DEBUG_ALWAYS,configValue) + + configKey=configBaseKey+"RCONPassword"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + password=configValue; + STATSGEN_DEBUG(DEBUG_ALWAYS,configValue) + + configKey=configBaseKey+"MessagingEnabled"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + serverEnabled=(configValue.CmpNoCase("y")==0); + + configKey=configBaseKey+"RCONUsePunkBuster"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + usingPunkbuster=(configValue.CmpNoCase("y")==0); + + remotePunkbusterDirectory=""; + if (usingPunkbuster) + { + configKey=configBaseKey+"PunkBusterPostCommand"; + globalStatistics.configData.ReadTextValue(configKey,&punkbusterPostCommand,""); + + configKey=configBaseKey+"banFile1Type"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + if (configValue.CmpNoCase("PUNKBUSTER")==0) + { + configKey=configBaseKey+"FTPBanFile1Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + remotePunkbusterDirectory=configValue; + } + else + { + configKey=configBaseKey+"banFile2Type"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + if (configValue.CmpNoCase("PUNKBUSTER")==0) + { + configKey=configBaseKey+"ban2Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + remotePunkbusterDirectory=configValue; + } + } + } + } + + configKey="/RCONSettings/Enabled"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + overallEnabled=(configValue.CmpNoCase("y")==0); + + configKey="/RCONSettings/MessagePrefix"; + globalStatistics.configData.ReadTextValue(configKey,&messagePrefix,"^7"); + // Now read the message list + + STATSGEN_DEBUG(DEBUG_ALWAYS,"Reading Message Centre Formats") + globalStatistics.configData.ReadGroup("MessageCentreFormats", + configKeys, + configValues); + formatCount=configKeys.GetCount(); + workingMessages.Clear(); + + for (formatIndex=0;formatIndex0) + { + int tokenValueCount; + int tokenValueIndex; + wxString tokenValue; + wxString substitutionValue; + + // we have a valid format string + // let's replace the tokens with the + // appropriate values + globalStatistics.configData.ReadList("MessageCentreValues", + key,tokenValues); + tokenValueCount=tokenValues.GetCount(); + for (tokenValueIndex=0; + tokenValueIndex0) + { + workingMessages.Add(format); + } + } + } + + // Need to insert the custom messages + globalStatistics.configData.ReadTextValue( + "/RCONSettings/CustomMessageInterval", + &configValue,"5"); + customMessageInterval=atoi(configValue.GetData()); + configGroup="CustomMessages"; + globalStatistics.configData.ReadList(configGroup,customMessages); + customMessageCount=customMessages.GetCount(); + workingMessageCount=workingMessages.GetCount(); + messagesToSend.Clear(); + customMessageIndex=0; + STATSGEN_DEBUG_CODE(msg.Printf("SLJCustom Messages [%d] Interval [%d] Working Messages [%d]", customMessageCount,customMessageInterval,workingMessageCount);) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + for (formatIndex=0; + formatIndex0) && (customMessageInterval>0)) + { + if ((formatIndex % customMessageInterval)==0) + { + format=customMessages.Item(customMessageIndex); + STATSGEN_DEBUG(DEBUG_RARELY,format) + messagesToSend.Add(format); + customMessageIndex++; + if (customMessageIndex>=customMessageCount) + { + customMessageIndex=0; + } + } + } + } + + STATSGEN_DEBUG_CODE(msg.Printf("Messages Calculated - Messages To Send [%d]", messagesToSend.GetCount());) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + // Self check the settings + if (overallEnabled && serverEnabled) + { + STATSGEN_DEBUG_CODE(msg.Printf("Messaging Enabled - Messages To Send [%d]", messagesToSend.GetCount());) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + if (usingPunkbuster) + { + if (remotePunkbusterDirectory.Length()==0) + { + msg.Printf("Server [%s]:Punkbuster Messaging Enabled but no Punkbuster Ban Directory defined, switching to non-PunkBuster operation",ID.GetData()); + progress->LogError(msg,SeverityCaution); + usingPunkbuster=false; + } + } + if ((hostname.Length()==0)&&(gameIP.Length()==0)) + { + msg.Printf("Server [%s]:RCON Messaging Enabled but hostname is blank for server, server messaging disabled",ID.GetData()); + progress->LogError(msg,SeverityCaution); + serverEnabled=false; + } + if (password.Length()==0) + { + msg.Printf("Server [%s]:RCON Messaging Enabled but RCON Password is blank for server, server messaging disabled",ID.GetData()); + progress->LogError(msg,SeverityCaution); + serverEnabled=false; + } + if (gamePort<1) + { + msg.Printf("Server [%s]:RCON Messaging Enabled but game port is invalid, server messaging disabled",ID.GetData()); + progress->LogError(msg,SeverityCaution); + serverEnabled=false; + } + if (localPort<1) + { + msg.Printf("Server [%s]:RCON Messaging Enabled but local port is invalid, server messaging disabled",ID.GetData()); + progress->LogError(msg,SeverityCaution); + serverEnabled=false; + } + } + if (overallEnabled && serverEnabled && usingPunkbuster) + { + STATSGEN_DEBUG_CODE(msg.Printf("Punkbuster Messaging Enabled - Messages To Send [%d]", messagesToSend.GetCount());) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + // We need to construct the punkbuster message file + // and upload it to the game server + UpdatePunkbusterMessages(); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void MessageCentre::SendRCONCommand(wxString &command) +{ + wxIPV4address remoteAddress; + wxIPV4address localAddress; + wxDatagramSocket *connection; + wxString msg; + wxString constructedCommand; + wxSocketError lastError; + + STATSGEN_DEBUG_FUNCTION_START("MessageCentre","SendRCONCommand") + if (gameIP.Length()>0) + { + remoteAddress.Hostname(gameIP); + } + else + { + remoteAddress.Hostname(hostname); + } + remoteAddress.Service(gamePort); + localAddress.AnyAddress(); + localAddress.Service(localPort); + + connection=new wxDatagramSocket(localAddress,wxSOCKET_BLOCK); + if (connection==NULL) + { + msg.Printf("Could not connect to %s:%d for message sending", + hostname.GetData(),gamePort); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + } + else + { + if (serverType.CmpNoCase("QUAKEWARS")==0) + { + constructedCommand.Printf("%c%crcon%c%s%c%s%c", + 255,255,255, + password.GetData(), + 255, + command.GetData(), + 255); + } + else + { + constructedCommand.Printf("%c%c%c%crcon %s %s", + 255,255,255,255, + password.GetData(), + command.GetData()); + } + STATSGEN_DEBUG(DEBUG_SOMETIMES,constructedCommand) + STATSGEN_DEBUG(DEBUG_SOMETIMES,hostname) + connection->SendTo(remoteAddress, + constructedCommand.GetData(), + constructedCommand.Length()); + + if (connection->Error()) + { + lastError=connection->LastError(); + msg.Printf("Error during rcon send %d",lastError); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + } + } + + if (connection!=NULL) + { + delete (connection); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void MessageCentre::SendMessage() +{ + int messageCount; + wxString messageToSend; + wxString command; + wxString configKey; + wxString configValue; + + if (overallEnabled && serverEnabled) + { + messageCount=messagesToSend.GetCount(); + if (messageCount>0) + { + if (messageIndex>=messageCount) + { + messageIndex=0; + } + messageToSend=messagesToSend.Item(messageIndex); + messageIndex++; + + if (!usingPunkbuster) + { + char *mandatoryMessagePrefix; + if (globalStatistics.hiddenFeatures) + { + mandatoryMessagePrefix=MESSAGE_CENTRE_PREFIX_HIDDEN; + } + else + { + mandatoryMessagePrefix=MESSAGE_CENTRE_PREFIX; + } + command.Printf("say \"%s%s%s\"",messagePrefix.GetData(),mandatoryMessagePrefix,messageToSend.GetData()); + SendRCONCommand(command); + } + + // Time to send the message + } + } +} + +void MessageCentre::UpdatePunkbusterMessages() +{ + int messageCount; + wxString messageToSend; + wxString command; + wxString configKey; + wxString configValue; + int currentMessageIndex; + wxFileName messageFileName; + FILE *fp; + int totalMessageTime; + int messageIntervalTimer; + wxString msg; + wxString configGroup; + const char *punkbusterMessageFile="statsgenpbmessages.cfg"; + + STATSGEN_DEBUG_FUNCTION_START("MessageCentre","UpdatePunkbusterMessages") + configKey="/RCONSettings/MessageIntervalTimer"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + messageIntervalTimer=atoi(configValue.GetData()); + + if ((overallEnabled && serverEnabled) && (messageIntervalTimer>0)) + { + messageFileName=BaseDirectoryFileName(punkbusterMessageFile); + STATSGEN_DEBUG(DEBUG_ALWAYS,messageFileName.GetFullPath()) + messageCount=messagesToSend.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("Messages To Send [%d]",messageCount);) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + if (messageCount>0) + { + totalMessageTime=messageIntervalTimer*messageCount; + fp=fopen(messageFileName.GetFullPath().GetData(),"w"); + if (fp!=NULL) + { + fprintf(fp,"pb_sv_taskempty\n"); + if (messageIndex>=messageCount) + { + messageIndex=0; + } + for (currentMessageIndex=messageIndex; + currentMessageIndex0) + { + fprintf(fp,"%s\n",punkbusterPostCommand.GetData()); + } + fclose(fp); + configGroup="Server"+ID; + RemoteMachine server(configGroup); + wxString filename; + + filename=messageFileName.GetFullPath(); + server.PutFile(remotePunkbusterDirectory, filename); + command.Printf("pb_sv_load %s",punkbusterMessageFile); + + SendRCONCommand(command); + } + } + } + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/MessageCentre.h b/MessageCentre.h new file mode 100644 index 0000000..0b533a5 --- /dev/null +++ b/MessageCentre.h @@ -0,0 +1,44 @@ +#ifndef __MESSAGECENTRE +#define __MESSAGECENTRE + +// wxWindows includes +#include +#include + +// Statsgen Includes +#include "LogFile.h" + +class MessageCentre +{ + public: + MessageCentre(); + virtual ~MessageCentre(); + + void SetID(wxString &IDIn); + void SendMessage(); + void Initiate(); + void SendRCONCommand(wxString &command); + void UpdatePunkbusterMessages(); + + + wxArrayString messagesToSend; + int messageIndex; + wxString ID; + + int gamePort; + int localPort; + wxString hostname; + wxString gameIP; + wxString password; + + bool overallEnabled; + bool serverEnabled; + bool usingPunkbuster; + wxString remotePunkbusterDirectory; + wxString serverType; + wxString messagePrefix; + wxString punkbusterPostCommand; +}; + + +#endif diff --git a/MultiFile.cpp b/MultiFile.cpp new file mode 100644 index 0000000..fd9becd --- /dev/null +++ b/MultiFile.cpp @@ -0,0 +1,275 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "MultiFile.h" + +MultiFile::MultiFile(wxArrayString &filenamesIn) +{ + LoadFiles(filenamesIn); + currentFileIndex=0; +} + +MultiFile::~MultiFile() +{ + UnloadFiles(); +} + +wxString MultiFile::Filename() +{ + int fileCount; + int fileIndex; + wxString filename; + wxString retVal; + + fileCount=filenames.GetCount(); + for (fileIndex=0;fileIndex0); + for (fileIndex=0;fileIndexOk()); + } + } + + return (retVal); +} + +void MultiFile::UnloadFiles() +{ + int fileCount; + int fileIndex; + wxFileInputStream *filestream; + wxBufferedInputStream *bufferedstream; + + currentFileIndex=0; + fileCount=filenames.GetCount(); + for (fileIndex=0;fileIndexGetSize(); + } + } + + return (retVal); +} + +long MultiFile::Size() +{ + return (Length()); +} + +long MultiFile::TellI() +{ + int fileIndex; + long retVal; + wxString filename; + wxBufferedInputStream *filestream; + + retVal=0; + for (fileIndex=0;fileIndex<=currentFileIndex;fileIndex++) + { + filestream=(wxBufferedInputStream *)bufferedstreams.Item(fileIndex); + if (filestream!=NULL) + { + if (fileIndex<(currentFileIndex-1)) + { + retVal+=(filestream->GetSize()); + } + else + { + retVal+=(filestream->TellI()); + } + } + } + + return (retVal); +} + +long MultiFile::SeekI(long newPosition) +{ + int fileCount; + int fileIndex; + long currentPosition; + wxString filename; + wxBufferedInputStream *filestream; + long thisFileSize; + + currentPosition=0; + currentFileIndex=0; + fileCount=filenames.GetCount(); + for (fileIndex=0;fileIndexGetSize(); + if (newPosition<=(currentPosition+thisFileSize)) + { + // requested position is in this file + filestream->SeekI(newPosition-currentPosition); + currentPosition=newPosition; + break; + } + else + { + filestream->SeekI(thisFileSize); + currentPosition+=(thisFileSize); + } + } + else + { + } + } + + return (currentPosition); +} + +bool MultiFile::Eof() +{ + wxBufferedInputStream *filestream; + bool retVal=true; + int fileIndex; + int fileCount; + + fileCount=filenames.GetCount(); + for (fileIndex=currentFileIndex;fileIndexEof(); + if (!retVal) + { + break; + } + } + currentFileIndex++; + } + return (retVal); +} + +unsigned char MultiFile::GetC() +{ + wxBufferedInputStream *filestream; + unsigned char retVal=0; + int fileIndex; + int fileCount; + + fileCount=filenames.GetCount(); + + for (fileIndex=currentFileIndex; + fileIndexEof()) + { + retVal=filestream->GetC(); + break; + } + else + { + // eof + if (fileIndex!=(fileCount-1)) + { + // we are "between" files + // we need to fake an end of line + currentFileIndex=(fileIndex+1); + retVal=0xa; + break; + } + } + } + currentFileIndex=fileIndex; + } + return (retVal); +} + diff --git a/MultiFile.h b/MultiFile.h new file mode 100644 index 0000000..7282065 --- /dev/null +++ b/MultiFile.h @@ -0,0 +1,36 @@ +#ifndef __MULTIFILE +#define __MULTIFILE + +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "DynamicArrays.h" + +class MultiFile +{ + public: + MultiFile(wxArrayString &filenamesIn); + ~MultiFile(); + wxString Filename(); + bool Eof(); + unsigned char GetC(); + bool Ok(); + long Length(); + long SeekI(long position); + long TellI(); + long Size(); + + private: + void LoadFiles(wxArrayString &filenames); + void UnloadFiles(); + public: + wxArrayString filenames; + ArrayOfPointers filestreams; + ArrayOfPointers bufferedstreams; + long currentFileIndex; +}; + +#endif diff --git a/PerformUpgradeDialog.cpp b/PerformUpgradeDialog.cpp new file mode 100644 index 0000000..f1a86a8 --- /dev/null +++ b/PerformUpgradeDialog.cpp @@ -0,0 +1,284 @@ +// Statsgen Includes +#include +#include +#include "PerformUpgradeDialog.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" +#include "Progress.h" + +BEGIN_EVENT_TABLE(PerformUpgradeDialog, wxDialog) + EVT_SIZE(PerformUpgradeDialog::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,PerformUpgradeDialog::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,PerformUpgradeDialog::OnQuit) +END_EVENT_TABLE() + +PerformUpgradeDialog::PerformUpgradeDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ + upgradeList=NULL; +} + +void PerformUpgradeDialog::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void PerformUpgradeDialog::OnSave(wxCommandEvent& event) +{ + long selectedItem; + int upgradeIndex; + wxString upgradeFilename; + wxString description; + wxString upgradeType; + wxString message; + wxString caption="Are You Sure?"; + + selectedItem=-1; + selectedItem=upgradeList->GetNextItem(selectedItem,wxLIST_NEXT_ALL,wxLIST_STATE_SELECTED); + if (selectedItem!=-1) + { + ConfigData upgradeFile; + upgradeIndex=(int)upgradeList->GetItemData(selectedItem); + upgradeFilename=upgradeFiles.Item(upgradeIndex); + wxFileName upgradeFileName(upgradeFilename); + upgradeFile.Initiate(upgradeFileName); + upgradeFile.UpgradeDetails(description,upgradeType); + if (upgradeType.CmpNoCase(UPGRADE_TYPE_UNKNOWN)!=0) + { + message.Printf("Are you sure you want to upgrade the %s using the upgrade file [%s], [%s]", + upgradeType.GetData(), + upgradeFilename.GetData(), + description.GetData()); + if (wxMessageBox(message,caption,wxYES_NO)==wxYES) + { + if (upgradeType.CmpNoCase(UPGRADE_TYPE_CONFIG)==0) + { + UpgradeConfigFile(upgradeFilename); + } + if (upgradeType.CmpNoCase(UPGRADE_TYPE_DATABASE)==0) + { + TemplateFile templateFile; + templateFile.ReadTemplate(upgradeFilename); + templateFile.Process(); + } + progress->Finalise(); + } + } + } +} + +PerformUpgradeDialog::~PerformUpgradeDialog() +{ + progress->SetDynamicPanel(NULL); +} + +void PerformUpgradeDialog::CreateDialog() +{ + wxString label="Generic Configuration"; + wxString defaultValue=""; + wxString configKey; + wxSizeEvent event; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + STATSGEN_DEBUG_FUNCTION_START("PerformUpgradeDialog","CreateDialog") + + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T("Peform Upgrade"), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + + + upgradeList=new wxListCtrl(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT); + progressPanel=new ProgressPanel(); + progressPanel->DynamicSizing(); + progressPanel->DisableTimeToGo(); + progressPanel->DisableCounter(); + progressPanel->Create(this, + WINDOW_ID_PROGRESS_PANEL_DYNAMIC, + wxDefaultPosition, + wxDefaultSize, + wxRAISED_BORDER); + progress->SetDynamicPanel(progressPanel); + progress->ChoosePanel(WINDOW_ID_PROGRESS_PANEL_DYNAMIC); + progress->UpdateLabel("Status"); + STATSGEN_DEBUG(DEBUG_RARELY,"items created") + // populate the list with upgrade files + wxFileName baseDirectory; + wxString fileSpec="*.ini"; + int flags=wxDIR_FILES; + int fileCount; + int fileIndex; + wxString filename; + wxString description; + wxString upgradeType; + int rowNumber=0; + wxListItem listColumn; + long listIndex; + bool rowAdded; + + baseDirectory=BaseDirectoryFileName("statsgen2.ini"); + wxDir::GetAllFiles( + baseDirectory.GetPath(), + &upgradeFiles, + fileSpec, + flags); + STATSGEN_DEBUG(DEBUG_RARELY,"got file list") + listColumn.SetText("Type"); + upgradeList->InsertColumn(0,listColumn); + listColumn.SetText("Description"); + upgradeList->InsertColumn(1,listColumn); + listColumn.SetText("Filename"); + upgradeList->InsertColumn(2,listColumn); + + STATSGEN_DEBUG(DEBUG_RARELY,"created columns") + fileCount=upgradeFiles.GetCount(); + rowNumber=0; + for (fileIndex=0;fileIndexInsertItem(rowNumber,upgradeType); + upgradeList->SetItemData(listIndex,fileIndex); + upgradeList->SetItem(rowNumber,1,description); + upgradeList->SetItem(rowNumber,2,upgradeFileName.GetFullName()); + rowNumber++; + } + } + upgradeList->SetColumnWidth(0,wxLIST_AUTOSIZE); + upgradeList->SetColumnWidth(1,wxLIST_AUTOSIZE); + upgradeList->SetColumnWidth(2,wxLIST_AUTOSIZE); + STATSGEN_DEBUG(DEBUG_RARELY,"populated columns") + OnResize(event); + STATSGEN_DEBUG_FUNCTION_END +} + +bool PerformUpgradeDialog::DisplayDialog() +{ + int dialogRetVal; + bool retVal; + + // Called when we want to pop the dialog box + // into existance for the first time + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + retVal=true; + break; + case WINDOW_ID_BUTTON_QUIT: + default: + retVal=false; + break; + } + + return (retVal); +} + +void PerformUpgradeDialog::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + int panelWidth; + int panelHeight; + wxSize itemSize; + wxPoint itemPosition; + int yPosition; + int progressWidth; + int progressHeight; + + STATSGEN_DEBUG_FUNCTION_START("PerformUpgradeDialog","OnResize") + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + itemSize=progressPanel->GetSize(); + progressHeight=itemSize.GetHeight(); + progressWidth=itemSize.GetWidth(); + panelHeight=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE-progressHeight; + panelWidth=dialogWidth; + if (progressWidth>panelWidth) + { + panelWidth=progressWidth; + } + else + { + progressWidth=panelWidth; + } + + // upgradeList + yPosition=0; + upgradeList->SetSize(0,yPosition,panelWidth,panelHeight); + + // progress panel + yPosition=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE-progressHeight; + progressPanel->SetSize(0,yPosition,progressWidth,progressHeight); + + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x=saveWidth+BUTTON_WIDTH_GAP+BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/PerformUpgradeDialog.h b/PerformUpgradeDialog.h new file mode 100644 index 0000000..7fa6b6e --- /dev/null +++ b/PerformUpgradeDialog.h @@ -0,0 +1,42 @@ +#ifndef __PERFORMUPGRADEDIALOG +#define __PERFORMUPGRADEDIALOG + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "ProgressPanel.h" + +class PerformUpgradeDialog : public wxDialog +{ + public: + PerformUpgradeDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~PerformUpgradeDialog(); + + void OnQuit(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + void OnResize(wxSizeEvent& event); + void CreateDialog(); + + bool DisplayDialog(); + + protected: + + wxButton quitButton; + wxButton saveButton; + ProgressPanel *progressPanel; + wxListCtrl *upgradeList; + wxArrayString upgradeFiles; + private: + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/Player.cpp b/Player.cpp new file mode 100644 index 0000000..6cb2ef5 --- /dev/null +++ b/Player.cpp @@ -0,0 +1,308 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "Player.h" +#include "GlobalStatistics.h" + +Player::Player() +{ + name=""; + ID=""; + score=0.0; + skill=0.0; + scoreWeighted=0.0; + skillWeighted=0.0; + kills=0; + deaths=0; + teamKills=0; + teamWins=0; + teamLosses=0; + longestKillStreak=0; + longestTeamKillStreak=0; + longestDeathStreak=0; + suicides=0; + rounds=0; + accumulatedDuration=0; + dropped=false; + lastActiveRound=0; + clanIndex=-1; + lastRoundPlayed=0; + firstRoundPlayed=-1; + actualPlayerIndex=-1; +} + +Player::~Player() +{ +} +wxString Player::SQLTableName() +{ + wxString retVal="player"; + + return (retVal); +} + +wxString Player::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "playerindex integer," + "%s," + "%s," + "score float," + "skill float," + "scoreweighted float," + "skillweighted float," + "kills integer," + "deaths integer," + "teamkills integer," + "teamwins integer," + "teamlosses integer," + "longestkillstreak integer," + "longestteamkillstreak integer," + "longestdeathstreak integer," + "suicides integer," + "rounds integer," + "duration integer," + "lastactiveround integer," + "clanindex integer," + "dropped varchar(1)" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("name","playername",FIELD_WIDTH_PLAYER_NAME).GetData(), + StatsgenDatabase::StringFieldDefinition("id","playerguid",FIELD_WIDTH_PLAYER_GUID).GetData() + ); + + return SQL; +} + +bool Player::WriteToDatabase(int itemIndex) +{ + bool updateExisting; + + updateExisting=(itemIndexlongestKillStreak) + { + longestKillStreak=secondary.longestKillStreak; + } + if (secondary.longestTeamKillStreak>longestTeamKillStreak) + { + longestTeamKillStreak=secondary.longestTeamKillStreak; + } + if (secondary.longestDeathStreak>longestDeathStreak) + { + longestDeathStreak=secondary.longestDeathStreak; + } + if (secondary.lastActiveRound>lastActiveRound) + { + lastActiveRound=secondary.lastActiveRound; + } + if (secondary.lastRoundPlayed>lastRoundPlayed) + { + lastRoundPlayed=secondary.lastRoundPlayed; + } + if (secondary.firstRoundPlayed +#include +#include +#include + +class Player; + +WX_DECLARE_OBJARRAY(Player,ArrayOfPlayers); +class Player +{ + public: + Player(); + virtual ~Player(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int itemIndex); + bool WriteToDatabaseUpdate(int itemIndex,bool update); + bool UpdateFromDatabase(int newPlayerIndex); + void Add(Player &secondary); + void ZeroScore(); + + wxString name; + wxString ID; + float score; + float skill; + float scoreWeighted; + float skillWeighted; + int kills; + int deaths; + int teamKills; + int suicides; + int teamWins; + int teamLosses; + int longestKillStreak; + int longestTeamKillStreak; + int longestDeathStreak; + int rounds; + wxTimeSpan accumulatedDuration; + bool dropped; + int lastActiveRound; + int clanIndex; + int lastRoundPlayed; + int firstRoundPlayed; + int actualPlayerIndex; +}; + +#endif diff --git a/PlayerCacheEntry.cpp b/PlayerCacheEntry.cpp new file mode 100644 index 0000000..eddf3f1 --- /dev/null +++ b/PlayerCacheEntry.cpp @@ -0,0 +1,24 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "PlayerCacheEntry.h" +#include "GlobalStatistics.h" + +PlayerCacheEntry::PlayerCacheEntry() +{ +} + +PlayerCacheEntry::~PlayerCacheEntry() +{ +} + +int PlayerCacheEntry::GUIDCompare( + PlayerCacheEntry **item1, + PlayerCacheEntry **item2 + ) +{ + return ((*item1)->guid.Cmp((*item2)->guid)); +} diff --git a/PlayerCacheEntry.h b/PlayerCacheEntry.h new file mode 100644 index 0000000..8a35478 --- /dev/null +++ b/PlayerCacheEntry.h @@ -0,0 +1,27 @@ +#ifndef __PLAYERCACHEENTRY +#define __PLAYERCACHEENTRY + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class PlayerCacheEntry; + +WX_DECLARE_OBJARRAY(PlayerCacheEntry,ArrayOfPlayerCacheEntry); +class PlayerCacheEntry +{ + public: + PlayerCacheEntry(); + ~PlayerCacheEntry(); + wxString guid; + wxString name; + static int GUIDCompare( + PlayerCacheEntry **item1, + PlayerCacheEntry **item2); +}; + + +#endif diff --git a/PlayerCachePanel.cpp b/PlayerCachePanel.cpp new file mode 100644 index 0000000..f8ddf67 --- /dev/null +++ b/PlayerCachePanel.cpp @@ -0,0 +1,289 @@ +// wx includes +#include +#include + +// Statsgen Includes +#include "PlayerCachePanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(PlayerCachePanel, wxPanel) + EVT_SIZE(PlayerCachePanel::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,PlayerCachePanel::OnFilterChanged) + EVT_LIST_COL_CLICK(WINDOW_ID_LISTBOX_CONFIGITEMS,PlayerCachePanel::OnColumnClick) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_LISTBOX_CONFIGITEMS, + PlayerCachePanel::OnRightClick) +END_EVENT_TABLE() + +PlayerCachePanel::PlayerCachePanel(wxString &configKeyIn,wxString &labelTextIn) +{ + cacheDisplay=NULL; + filter=NULL; + configKey=configKeyIn; + labelText=labelTextIn; + SetFilterType(FILTER_TYPE_NO_CASE); + filterNameCallBack=(bool (*)(wxString &name))NULL; + +} + +void PlayerCachePanel::UpdateCacheList() +{ + wxListItem listColumn; + int cacheIndex; + int cacheCount; + PlayerCacheEntry cacheEntry; + long listIndex; + wxString decolouredName; + wxString filterString; + int rowNumber; + bool addRow; + wxString matchString; + wxRegEx regExp; + + globalStatistics.configData.ReadTextValue(configKey,&filterString); + + switch (filterType) + { + case FILTER_TYPE_NO_CASE: + filterString.MakeLower(); + break; + case FILTER_TYPE_CASE: + break; + case FILTER_TYPE_REGEXP: + if (regExp.Compile(filterString)) + { + } + else + { + } + break; + } + cacheDisplay->Hide(); + cacheDisplay->DeleteAllColumns(); + cacheDisplay->DeleteAllItems(); + listColumn.SetText("GUID"); + cacheDisplay->InsertColumn(0,listColumn); + listColumn.SetText("Name"); + cacheDisplay->InsertColumn(1,listColumn); + listColumn.SetText("Decoloured Name"); + cacheDisplay->InsertColumn(2,listColumn); + cacheCount=globalStatistics.playerCache.GetCount(); + rowNumber=0; + for (cacheIndex=0;cacheIndex0) + { + // how to match the filter depends on the filter type + addRow=false; + matchString=decolouredName; + switch (filterType) + { + case FILTER_TYPE_NO_CASE: + matchString.MakeLower(); + addRow=matchString.Contains(filterString); + break; + case FILTER_TYPE_CASE: + addRow=matchString.Contains(filterString); + break; + case FILTER_TYPE_REGEXP: + addRow=regExp.Matches(matchString.GetData()); + break; + } + } + if (filterNameCallBack!=NULL) + { + addRow=(addRow && (!filterNameCallBack(cacheEntry.name))); + } + if (addRow) + { + listIndex=cacheDisplay->InsertItem(rowNumber,cacheEntry.guid); + cacheDisplay->SetItemData(listIndex,cacheIndex); + cacheDisplay->SetItem(rowNumber,1,cacheEntry.name); + cacheDisplay->SetItem(rowNumber,2,decolouredName); + rowNumber++; + } + } + cacheDisplay->SetColumnWidth(0,wxLIST_AUTOSIZE); + cacheDisplay->SetColumnWidth(1,wxLIST_AUTOSIZE); + cacheDisplay->SetColumnWidth(2,wxLIST_AUTOSIZE); + cacheDisplay->Show(); +} + +void PlayerCachePanel::CreateScreen() +{ + wxString defaultValue=""; + wxSizeEvent event; + + if (cacheDisplay==NULL) + { + globalStatistics.ReadPlayerCache(); + cacheDisplay=new wxListCtrl(this, + WINDOW_ID_LISTBOX_CONFIGITEMS, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT); + filter=new TextConfigItemGUI(); + filter->Create(this,WINDOW_ID_TEXTCTRL_CONFIGVALUE); + filter->Set(configKey,labelText,defaultValue,-1); + filter->OnResize(event); +// filter=new TextConfigItemGUI(this, +// WINDOW_ID_TEXTCTRL_CONFIGVALUE); + UpdateCacheList(); + + } + else + { + // Screen is already created + } +} + +void PlayerCachePanel::OnRightClick(wxListEvent &event) +{ + if (GetParent()!=NULL) + { + // Pop the event up to the next level + event.SetId(this->GetId()); + GetParent()->AddPendingEvent(event); + } +} + +void PlayerCachePanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int filterWidth; + int filterHeight; + int panelWidth; + int panelHeight; + int listHeight; + int listWidth; + wxString msg; + + // Make sure the screen has been created + CreateScreen(); + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + itemSize=filter->GetSize(); + filterWidth=itemSize.GetWidth(); + filterHeight=itemSize.GetHeight(); + + listWidth=panelWidth-10; + listHeight=panelHeight-filterHeight; + if (listHeight<0) + { + listHeight=0; + } + + filterWidth=panelWidth-10; + cacheDisplay->SetSize(0,0,listWidth,listHeight); + + filter->SetSize(0,listHeight,filterWidth,filterHeight); +} + +void PlayerCachePanel::OnColumnClick(wxListEvent &event) +{ + columnToSort=event.GetColumn(); + cacheDisplay->SortItems(PlayerCachePanel::CompareItems,(long)columnToSort); +} + +int wxCALLBACK PlayerCachePanel::CompareItems(long item1, long item2, long columnToSort) +{ + wxString field1; + wxString field2; + PlayerCacheEntry cacheEntry1; + PlayerCacheEntry cacheEntry2; + int retVal; + + cacheEntry1=globalStatistics.playerCache.Item(item1); + cacheEntry2=globalStatistics.playerCache.Item(item2); + switch (columnToSort) + { + case 0: // GUID + field1=cacheEntry1.guid; + field2=cacheEntry2.guid; + break; + case 1: // Coloured Name + field1=cacheEntry1.name; + field2=cacheEntry2.name; + break; + case 2: // Decoloured Name + default: + field1=DecolouriseName(cacheEntry1.name); + field2=DecolouriseName(cacheEntry2.name); + break; + } + + retVal=field1.Cmp(field2); + + return (retVal); +} + +void PlayerCachePanel::OnFilterChanged(wxCommandEvent &event) +{ + ApplyFilter(); +} + +void PlayerCachePanel::ApplyFilter() +{ + UpdateCacheList(); +} + +void PlayerCachePanel::SetFilterType(FilterTypes filterTypeIn) +{ + filterType=filterTypeIn; +} + +void PlayerCachePanel::GetSelectedPlayers(wxArrayInt &selectedPlayers) +{ + long selectedItem; + int playerIndex; + wxString msg; + + selectedItem=-1; + selectedItem=cacheDisplay->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + while (selectedItem!=-1) + { + playerIndex=(int)cacheDisplay->GetItemData(selectedItem); + selectedPlayers.Add(playerIndex); + selectedItem=cacheDisplay->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + } +} + +void PlayerCachePanel::GetShownPlayers(wxArrayInt &shownPlayers) +{ + int shownPlayersCount; + int shownPlayersIndex; + wxListItem listItem; + int playerCacheIndex; + wxString msg; + + shownPlayers.Clear(); + shownPlayersCount=cacheDisplay->GetItemCount(); + for (shownPlayersIndex=0; + shownPlayersIndexGetItemData(shownPlayersIndex); + shownPlayers.Add(playerCacheIndex); + } +} + +void PlayerCachePanel::SetFilter(wxString &filterString) +{ + globalStatistics.configData.WriteTextValue(configKey,filterString); + filter->SetConfigKey(configKey); +} + +void PlayerCachePanel::SetFilterCallBack(bool (*filterNameCallBackIn)(wxString &name)) + +{ + filterNameCallBack = filterNameCallBackIn; +} diff --git a/PlayerCachePanel.h b/PlayerCachePanel.h new file mode 100644 index 0000000..1573e7f --- /dev/null +++ b/PlayerCachePanel.h @@ -0,0 +1,54 @@ +#ifndef __PLAYERCACHEPANEL +#define __PLAYERCACHEPANEL + +#include +#include + +// Statsgen Includes +#include "TextConfigItemGUI.h" +#include "WindowIDs.h" + +class PlayerCachePanel : public wxPanel +{ + public: + enum FilterTypes + { + FILTER_TYPE_NO_CASE=0, + FILTER_TYPE_CASE, + FILTER_TYPE_REGEXP + }; + PlayerCachePanel(wxString &configKeyIn, + wxString &labelTextIn); + void CreateScreen(); + void OnRightClick(wxListEvent &event); + void OnResize(wxSizeEvent &event); + void OnColumnClick(wxListEvent &event); + void ApplyFilter(); + void UpdateCacheList(); + void GetShownPlayers(wxArrayInt &players); + void GetSelectedPlayers(wxArrayInt &players); + void OnFilterChanged(wxCommandEvent &event); + void SetFilterType(FilterTypes filterTypeIn); + void SetFilter(wxString &filterData); + void SetFilterCallBack(bool (*filterNameCallBack)(wxString &name)); + static int wxCALLBACK CompareItems( + long item1, + long item2, + long columntosort); + + + protected: + wxListCtrl *cacheDisplay; + TextConfigItemGUI *filter; + FilterTypes filterType; + bool (*filterNameCallBack)(wxString &name); + + + private: + int columnToSort; + wxString configKey; + wxString labelText; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/PlayerDataDialog.cpp b/PlayerDataDialog.cpp new file mode 100644 index 0000000..f1e79c0 --- /dev/null +++ b/PlayerDataDialog.cpp @@ -0,0 +1,56 @@ +// Statsgen Includes +#include "PlayerDataDialog.h" +#include "PlayerDataList.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +PlayerDataDialog::PlayerDataDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + PlayerDataList *playerDataListIn, + wxString &defaultPlayerData, + wxString &playerDataTitle) : GenericOKCancelDialog + (parent, + id, + title, + pos, + size, + style, + name) +{ + playerDataList=playerDataListIn; + panel=new PlayerDataEditorPanel(playerDataList, + defaultPlayerData, + playerDataTitle); + panel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); +} + +bool PlayerDataDialog::DisplayDialog() +{ + return (GenericOKCancelDialog::DisplayDialog((wxPanel *)panel)); +} + +PlayerDataDialog::~PlayerDataDialog() +{ +} + +void PlayerDataDialog::OnSave(wxCommandEvent &event) +{ + playerDataList->WriteToFile(); + globalStatistics.configData.CommitChanges(); + GenericOKCancelDialog::OnSave(event); +} + +void PlayerDataDialog::OnQuit(wxCommandEvent &event) +{ + globalStatistics.configData.RollbackChanges(); + GenericOKCancelDialog::OnQuit(event); +} + diff --git a/PlayerDataDialog.h b/PlayerDataDialog.h new file mode 100644 index 0000000..dc5813f --- /dev/null +++ b/PlayerDataDialog.h @@ -0,0 +1,40 @@ +#ifndef __PLAYERDATADIALOG +#define __PLAYERDATADIALOG + +#include +#include + +// Statsgen Includes +#include "GenericOKCancelDialog.h" +#include "PlayerDataEditorPanel.h" +#include "PlayerDataList.h" +#include "WindowIDs.h" + +class PlayerDataDialog : public GenericOKCancelDialog +{ + public: + PlayerDataDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + PlayerDataList *playerDataList, + wxString &defaultPlayerData, + wxString &playerDataTitle); + + virtual ~PlayerDataDialog(); + + virtual void OnSave(wxCommandEvent& event); + virtual void OnQuit(wxCommandEvent& event); + virtual bool DisplayDialog(); + + protected: + + private: + PlayerDataEditorPanel *panel; + PlayerDataList *playerDataList; +}; + +#endif diff --git a/PlayerDataEditorPanel.cpp b/PlayerDataEditorPanel.cpp new file mode 100644 index 0000000..d21d37f --- /dev/null +++ b/PlayerDataEditorPanel.cpp @@ -0,0 +1,309 @@ +// wx includes +#include +#include +#include +#include + +// Statsgen Includes +#include "PlayerDataEditorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(PlayerDataEditorPanel, wxPanel) + EVT_SIZE(PlayerDataEditorPanel::OnResize) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_DROPLIST, + PlayerDataEditorPanel::OnPlayerDataListRightClick) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_PLAYERCACHE, + PlayerDataEditorPanel::OnPlayerRightClick) + EVT_MENU(PLAYER_DATA_ADD,PlayerDataEditorPanel::OnPopupMenu) + EVT_MENU(PLAYER_DATA_DELETE,PlayerDataEditorPanel::OnPopupMenu) + EVT_LIST_END_LABEL_EDIT(WINDOW_ID_DROPLIST,PlayerDataEditorPanel::OnLabelEdit) +END_EVENT_TABLE() + +PlayerDataEditorPanel::PlayerDataEditorPanel(PlayerDataList *playerDataListIn, + wxString &defaultPlayerDataIn, + wxString &playerDataTitleIn) +{ + playerCache=NULL; + playerDataListCtrl=NULL; + playerDataList=playerDataListIn; + defaultPlayerData=defaultPlayerDataIn; + playerDataTitle=playerDataTitleIn; + + // Lets load up the current DropList List into + // the global statistics - we can transfer + // it across into the tree during creation + globalStatistics.ReadAliasList(); + playerDataList->ReadFromFile(); +} + +bool PlayerDataEditorPanel::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + wxString dummyConfigKey="/tmp/tmp"; + wxString labelText="Player Filter"; + wxString configKey; + + wxPanel::Create( parent, id, + pos, + size, + style, + name); + + playerCache=new PlayerCachePanel(dummyConfigKey,labelText); + playerCache->SetFilterType(PlayerCachePanel::FILTER_TYPE_NO_CASE); + playerCache->Create(this, + WINDOW_ID_PLAYERCACHE, + wxDefaultPosition, + wxDefaultSize); + playerDataListCtrl=new wxListCtrl(this, + WINDOW_ID_DROPLIST, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT| + wxLC_EDIT_LABELS); + RefreshPlayerDataListTree(); + + configItems=new GroupedConfigItemsPanel("Configuration File"); + configItems->Create(this,-1,wxDefaultPosition,wxDefaultSize); + configItems->AddFile("Configuration File", + playerDataList->filenameConfigKey, + (char *)playerDataList->defaultFilename.GetData(), + -1, + NULL); + + wxSizeEvent dummyEvent; + OnResize(dummyEvent); + return (true); +} + +void PlayerDataEditorPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int playerCacheWidth; + int playerCacheHeight; + int panelWidth; + int panelHeight; + int playerListWidth; + int playerListHeight; + wxString msg; + int configHeight; + int configWidth; + + + if (playerDataListCtrl!=NULL) + { + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + configItems->SetSize(0,0,1,1); + itemSize=configItems->GetSize(); + configWidth=panelWidth; + configHeight=itemSize.GetHeight(); + + panelHeight-=configHeight; + + playerCacheWidth=panelWidth; + playerCacheHeight=panelHeight/2; + playerListWidth=panelWidth; + playerListHeight=panelHeight/2; + + configItems->SetSize(0,0,configWidth,configHeight); + playerDataListCtrl->SetSize(0,configHeight,playerListWidth,playerListHeight); + playerCache->SetSize(0,playerListHeight+configHeight,playerCacheWidth,playerCacheHeight); + } + +} + +void PlayerDataEditorPanel::AddPlayerDataEntry(int index, + PlayerDataEntry &listEntry) +{ + long itemIndex; + long listIndex; + long rowNumber; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("PlayerDataEditorPanel","AddPlayerDataEntry") + rowNumber=index; + itemIndex=index; +// itemIndex++; + + listIndex=playerDataListCtrl->InsertItem(rowNumber,listEntry.playerData); + STATSGEN_DEBUG_CODE(msg.Printf("row [%ld] listIndex=[%ld] itemIndex [%ld]" + "[%s] [%s] [%s]", + rowNumber,listIndex,itemIndex, + listEntry.playerGUID.GetData(), + listEntry.playerName.GetData(), + listEntry.playerData.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + + playerDataListCtrl->SetItemData(listIndex,itemIndex); + playerDataListCtrl->SetItem(rowNumber,1,listEntry.playerGUID); + playerDataListCtrl->SetItem(rowNumber,2,DecolouriseName(listEntry.playerName)); + playerDataListCtrl->SetItem(rowNumber,3,listEntry.playerName); + STATSGEN_DEBUG_FUNCTION_END +} + +void PlayerDataEditorPanel::RefreshPlayerDataListTree() +{ + PlayerDataEntry listEntry; + wxListItem listColumn; + int listCount; + int listIndex; + + playerDataListCtrl->Hide(); + + playerDataListCtrl->DeleteAllColumns(); + playerDataListCtrl->DeleteAllItems(); + listColumn.SetText(playerDataTitle); + playerDataListCtrl->InsertColumn(0,listColumn); + listColumn.SetText("GUID"); + playerDataListCtrl->InsertColumn(1,listColumn); + listColumn.SetText("Name (Uncoloured)"); + playerDataListCtrl->InsertColumn(2,listColumn); + listColumn.SetText("Name (Coloured)"); + playerDataListCtrl->InsertColumn(3,listColumn); + + listCount=playerDataList->playerDataList.GetCount(); + for (listIndex=0;listIndexplayerDataList.Item(listIndex); + AddPlayerDataEntry(listIndex,listEntry); + } + + playerDataListCtrl->SetColumnWidth(0,wxLIST_AUTOSIZE); + playerDataListCtrl->SetColumnWidth(1,wxLIST_AUTOSIZE); + playerDataListCtrl->SetColumnWidth(2,wxLIST_AUTOSIZE); + playerDataListCtrl->SetColumnWidth(3,wxLIST_AUTOSIZE); + playerDataListCtrl->Show(); +} + +void PlayerDataEditorPanel::OnPlayerDataListRightClick(wxListEvent &event) +{ + wxString msg; + wxMenu popupMenu(_T("")); + wxString menuItem; + + // What have we right clicked on - parent or child? + menuItem="Delete Entry"; popupMenu.Append(PLAYER_DATA_DELETE,menuItem); + popupMenu.AppendSeparator(); + + popupMenu.Append(PLAYER_DATA_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void PlayerDataEditorPanel::OnPlayerRightClick(wxListEvent &event) +{ + wxString msg; + wxString menuItem; + wxMenu popupMenu(_T("")); + + // Right clicked on an item in the Player Cache + menuItem="New Avatar Entry"; + popupMenu.Append(PLAYER_DATA_ADD,menuItem); + popupMenu.AppendSeparator(); + popupMenu.Append(PLAYER_DATA_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void PlayerDataEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + wxString msg; + wxArrayInt selectedPlayers; + int selectedCount; + int cacheIndex; + PlayerCacheEntry cacheEntry; + int playerIndex; + int playerCount; + long selectedItem=-1; + int listIndex; + int id; + wxArrayInt selectedPlayerData; + PlayerDataEntry listEntry; + + STATSGEN_DEBUG_FUNCTION_START("PlayerDataEditorPanel","OnPopupMenu") + wxString data=defaultPlayerData; + + selectedPlayerData.Clear(); + selectedItem=-1; + selectedItem=playerDataListCtrl->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + while (selectedItem!=-1) + { + listIndex=playerDataListCtrl->GetItemData(selectedItem); + selectedPlayerData.Add(listIndex); + selectedItem=playerDataListCtrl->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + } + id=event.GetId(); + switch (id) + { + case PLAYER_DATA_ADD: + playerCache->GetSelectedPlayers(selectedPlayers); + selectedCount=selectedPlayers.GetCount(); + for (cacheIndex=0;cacheIndexAddPlayer(cacheEntry.guid,cacheEntry.name,data); + } + RefreshPlayerDataListTree(); + break; + case PLAYER_DATA_DELETE: + selectedCount=selectedPlayerData.GetCount(); + if (selectedCount>0) + { + listIndex=selectedPlayerData.Item(0); + listEntry=playerDataList->playerDataList.Item(listIndex); + playerDataList->DeletePlayer(listEntry.playerGUID, + listEntry.playerName); + } + RefreshPlayerDataListTree(); + break; + } + STATSGEN_DEBUG_FUNCTION_END +} + +void PlayerDataEditorPanel::OnLabelEdit(wxListEvent &event) +{ + wxMenu popupMenu(_T("")); + long index; + long listIndex; + PlayerDataEntry listEntry; + int listCount; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("PlayerDataEditorPanel","OnLabelEdit") + index=event.GetIndex(); + + listIndex=playerDataListCtrl->GetItemData(index); + listCount=playerDataList->playerDataList.GetCount(); + + STATSGEN_DEBUG_CODE(msg.Printf("Index=[%d] of [%d]",listIndex,listCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (listIndexplayerDataList.Item(listIndex); + listEntry.playerData=event.GetText(); + STATSGEN_DEBUG_CODE(msg.Printf("Adding [%s] [%s] with data [%s]", + listEntry.playerGUID.GetData(), + listEntry.playerName.GetData(), + listEntry.playerData.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + playerDataList->AddPlayer(listEntry.playerGUID, + listEntry.playerName, + listEntry.playerData); + } + RefreshPlayerDataListTree(); + event.StopPropagation(); + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/PlayerDataEditorPanel.h b/PlayerDataEditorPanel.h new file mode 100644 index 0000000..364d876 --- /dev/null +++ b/PlayerDataEditorPanel.h @@ -0,0 +1,55 @@ +#ifndef __PLAYERDATAEDITORPANEL +#define __PLAYERDATAEDITORPANEL + +#include +#include + +// Statsgen Includes +#include "PlayerCachePanel.h" +#include "PlayerCacheEntry.h" +#include "PlayerDataEntry.h" +#include "PlayerDataList.h" +#include "GroupedConfigItemsPanel.h" +#include "WindowIDs.h" + +class PlayerDataEditorPanel : public wxPanel +{ + public: + PlayerDataEditorPanel(PlayerDataList *playerDataListIn, + wxString &defaultPlayerDataIn, + wxString &playerDataTitleIn); + virtual bool Create(wxWindow *parent, + wxWindowID id=-1, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + void OnResize(wxSizeEvent &event); + void OnPlayerDataListRightClick(wxListEvent &event); + void OnLabelEdit(wxListEvent &event); + void OnPlayerRightClick(wxListEvent &event); + void OnPopupMenu(wxCommandEvent &event); + void RefreshPlayerDataListTree(); + + protected: + + + private: + void AddPlayerDataEntry(int index,PlayerDataEntry &listEntry); + enum + { + PLAYER_DATA_CANCEL=1000, + PLAYER_DATA_ADD, + PLAYER_DATA_DELETE + }; + + PlayerCachePanel *playerCache; + wxListCtrl *playerDataListCtrl; + PlayerDataList *playerDataList; + wxString defaultPlayerData; + wxString playerDataTitle; + GroupedConfigItemsPanel *configItems; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/PlayerDataEntry.cpp b/PlayerDataEntry.cpp new file mode 100644 index 0000000..8dce55f --- /dev/null +++ b/PlayerDataEntry.cpp @@ -0,0 +1,135 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "PlayerDataEntry.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +PlayerDataEntry::PlayerDataEntry() +{ + playerIndex=-1; + playerGUID=""; + playerName=""; + playerData=""; +} + +PlayerDataEntry::~PlayerDataEntry() +{ +} + +void PlayerDataEntry::ReadFromFile(wxTextFile *fp,int index) +{ + wxString lineRead; + wxString tempString; + wxString msg; + Player existingPlayer; + + + STATSGEN_DEBUG_FUNCTION_START("PlayerDataEntry","ReadFromFile") + lineRead=fp->GetLine(index); + + + tempString=lineRead; + playerData=tempString.BeforeFirst(','); + playerGUID=tempString.AfterFirst(','); + + playerName=playerGUID.AfterFirst(','); + playerGUID=playerGUID.BeforeFirst(','); + STATSGEN_DEBUG_CODE( + msg.Printf("name read [%s] [%s]", + playerGUID.GetData(), + playerName.GetData()); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + + // Update with any current aliases + AliasListEntry alias; + + alias.aliasGUID=playerGUID; + alias.aliasName=playerName; + if (globalStatistics.FindAlias(alias)) + { + playerGUID=alias.primaryGUID; + playerName=alias.primaryName; + STATSGEN_DEBUG_CODE( + msg.Printf("Re-aliased to [%s] [%s]", + playerGUID.GetData(), + playerName.GetData()); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + } + + playerIndex=globalStatistics.FindPlayerIndex(playerName); + STATSGEN_DEBUG_CODE( + msg.Printf("playerIndex found %d",playerIndex); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + if (playerIndex==-1) + { + // Not in current player list - means it is still in db + int dummyPlayerIndex; + Player player; + player.name=playerName; + if (player.UpdateFromDatabase(dummyPlayerIndex)) + { + playerIndex=player.actualPlayerIndex; + } + else + { + playerIndex=-1; + } + STATSGEN_DEBUG_CODE( + msg.Printf("playerIndex in db found %d",playerIndex); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + } + else + { + existingPlayer=globalStatistics.playerList.Item(playerIndex); + if (existingPlayer.actualPlayerIndex >= 0) + { + playerIndex=existingPlayer.actualPlayerIndex; + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void PlayerDataEntry::WriteToFile(FILE *fp) +{ + STATSGEN_DEBUG_FUNCTION_START("PlayerDataEntry","WriteToFile") + fprintf(fp,"%s,%s,%s\n", + playerData.GetData(), + playerGUID.GetData(), + playerName.GetData()); + STATSGEN_DEBUG_FUNCTION_END +} + +bool PlayerDataEntry::WriteToDatabase(const char *tableName) +{ + wxString SQL; + bool retVal=true; + + SQL.Printf("delete from %s where playerindex=%d", + tableName, + playerIndex); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + if (playerIndex>=0) + { + SQL.Printf("insert into %s" + "(playerindex,playerdata)" + "values" + "('%d','%s')", + tableName, + playerIndex, + StatsgenDatabase::SafeForInsert(playerData).GetData() + ); + + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + } + + return (retVal); +} + diff --git a/PlayerDataEntry.h b/PlayerDataEntry.h new file mode 100644 index 0000000..d3921bf --- /dev/null +++ b/PlayerDataEntry.h @@ -0,0 +1,31 @@ +#ifndef __PLAYERDATAENTRY +#define __PLAYERDATAENTRY + +// wxWindows includes +#include +#include +#include +#include +#include + +// Statsgen Includes + +class PlayerDataEntry; + +WX_DECLARE_OBJARRAY(PlayerDataEntry,ArrayOfPlayerDataEntry); +class PlayerDataEntry +{ + public: + PlayerDataEntry(); + ~PlayerDataEntry(); + int playerIndex; + wxString playerName; + wxString playerGUID; + wxString playerData; + void ReadFromFile(wxTextFile *fp,int index); + void WriteToFile(FILE *fp); + bool WriteToDatabase(const char *tableName); +}; + + +#endif diff --git a/PlayerDataList.cpp b/PlayerDataList.cpp new file mode 100644 index 0000000..de6ec90 --- /dev/null +++ b/PlayerDataList.cpp @@ -0,0 +1,186 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "PlayerDataList.h" +#include "PlayerDataEntry.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +PlayerDataList::PlayerDataList(const char *filenameConfigKeyIn, + const char *databaseTableNameIn, + const char *defaultFilenameIn) +{ + playerDataList.Clear(); + filenameConfigKey=filenameConfigKeyIn; + databaseTableName=databaseTableNameIn; + defaultFilename=defaultFilenameIn; +} + +PlayerDataList::~PlayerDataList() +{ +} + +void PlayerDataList::ReadFromFile() +{ + wxString filename; + wxTextFile fp; + int lineIndex; + + filename=""; + + globalStatistics.configData.ReadTextValue(filenameConfigKey, + &filename, + (char *)defaultFilename.GetData()); + playerDataList.Clear(); + if (wxFileExists(filename)) + { + if (fp.Open(filename)) + { + for (lineIndex=0;lineIndex +#include +#include +#include + +// Statsgen Includes +#include "PlayerDataEntry.h" + +class PlayerDataList +{ + public: + PlayerDataList(const char *filenameConfigKeyIn, + const char *databaseTableNameIn, + const char *defaultFilename); + ~PlayerDataList(); + + void ReadFromFile(); + void WriteToFile(); + void AddPlayer(wxString &guid,wxString &name,wxString &data); + int DeletePlayer(wxString &guid,wxString &name); + wxString SQLTableName(); + wxString SQLCreateTable(); + bool CreateDatabaseTable(); + bool WriteToDatabase(); + + ArrayOfPlayerDataEntry playerDataList; + wxString filenameConfigKey; + wxString databaseTableName; + wxString defaultFilename; + +}; + + +#endif diff --git a/PlayerInRound.cpp b/PlayerInRound.cpp new file mode 100644 index 0000000..013b986 --- /dev/null +++ b/PlayerInRound.cpp @@ -0,0 +1,543 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "PlayerInRound.h" +#include "GlobalStatistics.h" +#include "Player.h" +#include "ErrorData.h" + +PlayerInRound::PlayerInRound() +{ + timeLogged=false; + teamKills=0; + teamWins=0; + teamLosses=0; + suicides=0; + kills=0; + deaths=0; + score=0.0; + skill=0.0; +} + +PlayerInRound::~PlayerInRound() +{ +} + +void PlayerInRound::LogTime(wxDateTime &timeStamp,bool resetTime) +{ + wxTimeSpan activityDuration; + + if (!timeLogged || resetTime) + { + lastActivityTime=timeStamp; + } + + activityDuration=timeStamp.Subtract(lastActivityTime); + if (activityDuration<0) + { + // logfile has logged a negative time + activityDuration=0; + } + if (activityDuration>3600) + { + // something wrong here - too long between activities + activityDuration=0; + } + accumulatedDuration+=activityDuration; + lastActivityTime=timeStamp; + timeLogged=true; +} + +void PlayerInRound::CalculateStreaks(ArrayOfKillData *kills, + int gameType) +{ + KillData kill; + int killIndex; + int killCount; + StreakData streak; + KillTypes lastKillType=KILL_TYPE_KILL; + KillTypes thisKillType=KILL_TYPE_KILL; + bool killDataFound=false; + + killCount=kills->GetCount(); + + streak.streakSize=0; + streak.streakEndedPlayerIndex=-1; + for (killIndex=0;killIndexItem(killIndex); + if ((kill.playerIndex==playerIndex) || + (kill.targetIndex==playerIndex)) + { + // This kill/death belongs to this player + thisKillType=kill.KillType(gameType,playerIndex); + if ((!killDataFound)||(thisKillType!=lastKillType)) + { + // This is a new streak type + if (killDataFound) + { + // and it is not the first + if (streak.streakSize>1) + { + // this is a significant streak + // what sort is it, who ended it? + switch (lastKillType) + { + case KILL_TYPE_KILL: + // killer ended the kill streak + streak.streakEndedPlayerIndex=kill.playerIndex; + killStreak.Add(streak); + break; + case KILL_TYPE_DEATH: + // target ended the death streak + streak.streakEndedPlayerIndex=kill.targetIndex; + deathStreak.Add(streak); + break; + case KILL_TYPE_TEAMKILL: + // target ended the teamkill streak + streak.streakEndedPlayerIndex=kill.targetIndex; + teamKillStreak.Add(streak); + break; + default: + // not interested in other streak types + break; + } + } + else + { + // This streak is insignificant + } + + // Lets initiate the current streak + streak.streakSize=1; + streak.streakEndedPlayerIndex=-1; + + + } + else + { + // This is the first item of the streak + streak.streakSize=1; + // Currently nobody has ended the streak + streak.streakEndedPlayerIndex=-1; + } + } + else + { + // This is the same as the last streak type (or the first one) + if (killDataFound) + { + // This is a continuation of the current streak + streak.streakSize++; + // Currently nobody has ended the streak + streak.streakEndedPlayerIndex=-1; + + } + } + lastKillType=thisKillType; + killDataFound=true; + } + else + { + // This kill data has nothing to do with this player + } + } + + // If the current streak has >0 entries then the round ended with a + // streak active - need to see if it is worth adding. + if (streak.streakSize>1) + { + // this is a significant streak + // what sort is it, who ended it? + // nobody ended this streak + streak.streakEndedPlayerIndex=-1; + switch (lastKillType) + { + case KILL_TYPE_KILL: + // killer ended the kill streak + killStreak.Add(streak); + break; + case KILL_TYPE_DEATH: + // target ended the death streak + deathStreak.Add(streak); + break; + case KILL_TYPE_TEAMKILL: + // target ended the teamkill streak + teamKillStreak.Add(streak); + break; + default: + // not interested in other streak types + break; + } + } + +} + +void PlayerInRound::Debug() +{ + wxString durationString; + wxString errorMessage; + Player player; + StreakData streak; + int streakIndex; + int streakCount; + STATSGEN_DEBUG_FUNCTION_START("PlayerInRound","Debug") + + player=globalStatistics.GetPlayer(playerIndex); + durationString=accumulatedDuration.Format("%H:%M:%S"); + STATSGEN_DEBUG_CODE(errorMessage.Printf( + "PLIDX[%05d]DUR[%s]K[%06d]D[%06d]TK[%06d]SU[%06d]SC[%0.2f]SK[%0.2f][%s]", + playerIndex, + durationString.GetData(), + kills, + deaths, + teamKills, + suicides, + score, + skill, + player.name.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + streakCount=killStreak.GetCount(); + if (streakCount>0) + { + STATSGEN_DEBUG_CODE(errorMessage.Printf("Kill Streaks %d",streakCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + } + for (streakIndex=0;streakIndex0) + { + STATSGEN_DEBUG_CODE(errorMessage.Printf("Death Streaks %d",streakCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + } + for (streakIndex=0;streakIndex0) + { + STATSGEN_DEBUG_CODE(errorMessage.Printf("Team Kill Streaks %d",streakCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + } + for (streakIndex=0;streakIndex +#include +#include +#include +#include + +// statsgen includes +#include "StreakData.h" +#include "KillData.h" +#define PLAYERINROUND_AWARD_ZERO -999999 + +class PlayerInRound; +WX_DECLARE_OBJARRAY(PlayerInRound,ArrayOfPlayersInRound); +class PlayerInRound +{ + public: + PlayerInRound(); + virtual ~PlayerInRound(); + void LogTime(wxDateTime &timeStamp,bool resetTime); + void CalculateStreaks(ArrayOfKillData *kills, + int gameType); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + static wxString SQLCreateTableAward(); + static wxString SQLTableNameAward(); + bool WriteToDatabase(int roundIndex,int itemIndex); + void UpdateActionAwardPoints(wxString &actionCode); + void UpdateWeaponAwardPoints(wxString &code,bool kill,bool teamkill); + void UpdateLocationAwardPoints(wxString &code,bool kill,bool teamkill); + void UpdateMiscAwardPoints(char *code,int count); + void UpdateXPAwardPoints(wxString &code,float points); + + void Debug(); + void ZeroAwardPoints(); + + int playerIndex; + + wxTimeSpan accumulatedDuration; + float score; + float skill; + int kills; + int deaths; + int teamKills; + int teamWins; + int teamLosses; + int suicides; + ArrayOfStreakData teamKillStreak; + ArrayOfStreakData killStreak; + ArrayOfStreakData deathStreak; + wxArrayInt awardPoints; + + + wxDateTime lastActivityTime; + bool timeLogged; +}; + +#endif diff --git a/PlayerList.cpp b/PlayerList.cpp new file mode 100644 index 0000000..83166b8 --- /dev/null +++ b/PlayerList.cpp @@ -0,0 +1,372 @@ +// Statsgen Includes +#include "PlayerList.h" +#include "ErrorData.h" +#include "AliasListEntry.h" +#include "GlobalStatistics.h" + + +PlayerList::PlayerList() +{ + cacheEnabled=false; + Clear(); + nameCache=NULL; + nameCache=new ArrayOfKeyedIndex(KeyedIndex::Compare); + guidCache=NULL; + guidCache=new ArrayOfKeyedIndex(KeyedIndex::Compare); +} + +PlayerList::~PlayerList() +{ + Clear(); + if (nameCache!=NULL) + { + delete nameCache; + } + if (guidCache!=NULL) + { + delete guidCache; + } +} + +void PlayerList::Clear() +{ + players.Clear(); + if (nameCache!=NULL) + { + int cacheCount; + int cacheIndex; + KeyedIndex *cacheEntry; + + cacheCount=nameCache->GetCount(); + for (cacheIndex=0;cacheIndexItem(cacheIndex); + delete cacheEntry; + } + nameCache->Clear(); + } + if (guidCache!=NULL) + { + int cacheCount; + int cacheIndex; + KeyedIndex *cacheEntry; + + cacheCount=guidCache->GetCount(); + for (cacheIndex=0;cacheIndexItem(cacheIndex); + delete cacheEntry; + } + guidCache->Clear(); + } +} + +void PlayerList::EnableCache() +{ + cacheEnabled=true; +} + +void PlayerList::DisableCache() +{ + cacheEnabled=false; +} + +Player &PlayerList::GetPlayer(int index) +{ + return (players.Item(index)); +} +int PlayerList::FindPlayerIndex(wxString &name) +{ + int playerCount; + int playerIndex; + Player player; + int foundIndex=-1; + int searchIndex; + wxString msg; + + if (cacheEnabled) + { + KeyedIndex searchKey; + searchKey.key=name; + searchIndex=nameCache->Index(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + foundIndex=-1; + } + else + { + KeyedIndex *foundKey; + foundKey=nameCache->Item(searchIndex); + foundIndex=foundKey->index; + } + } + else + { + playerCount=players.GetCount(); + for (playerIndex=0;playerIndexkey=name; + nameCacheEntry->index=playerIndex; + nameCache->Add(nameCacheEntry); + + KeyedIndex searchKey; + searchKey.key=id; + searchIndex=guidCache->Index(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + // this guid not in cache + KeyedIndex *guidCacheEntry; + guidCacheEntry=new KeyedIndex; + guidCacheEntry->key=id; + guidCacheEntry->index=playerIndex; + guidCache->Add(guidCacheEntry); + } + else + { + // it's already in the cache + } + } + } + + if (AKAFound) + { + globalStatistics.AddAKA(playerIndex,AKAName); + } + + return(playerIndex); + +} + +void PlayerList::WriteToDatabase() +{ + Player player; + int playerCount; + int playerIndex; + + playerCount=players.GetCount(); + for (playerIndex=0;playerIndexIndex(&searchKey); + if (searchIndex==wxNOT_FOUND) + { + foundIndex=-1; + } + else + { + KeyedIndex *foundKey; + foundKey=guidCache->Item(searchIndex); + foundIndex=foundKey->index; + } + } + else + { + playerCount=players.GetCount(); + for (playerIndex=0;playerIndex + +// Statsgen Includes +#include "Player.h" +#include "DynamicArrays.h" +#include "KeyedIndex.h" + +class PlayerList +{ + public: + PlayerList(); + ~PlayerList(); + Player &GetPlayer(int index); + int FindPlayerIndex(wxString &name); + int AddPlayer(wxString &name,wxString &id); + int FindGUIDIndex(wxString &guid); + int GetCount(); + void Clear(); + Player &Item(int index); + Player *Detach(int index); + void Add(Player *player); + void Add(Player &player); + void RemoveAt(int index); + void Insert(Player &player,int playerIndex); + void WriteToDatabase(); + void EnableCache(); + void DisableCache(); + + protected: + + private: + ArrayOfPlayers players; + bool cacheEnabled; + ArrayOfKeyedIndex *nameCache; + ArrayOfKeyedIndex *guidCache; + +}; + +#endif diff --git a/PriorityPanel.cpp b/PriorityPanel.cpp new file mode 100644 index 0000000..7777d8a --- /dev/null +++ b/PriorityPanel.cpp @@ -0,0 +1,92 @@ +// wx includes +#include +#include +#include + +// Statsgen Includes +#include "PriorityPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" + +BEGIN_EVENT_TABLE(PriorityPanel, wxPanel) + EVT_SIZE(PriorityPanel::OnResize) + EVT_SCROLL(PriorityPanel::OnSliderChange) +END_EVENT_TABLE() + +PriorityPanel::PriorityPanel() +{ + fullRunPriority=NULL; +} + +void PriorityPanel::CreateScreen() +{ + wxString defaultValue=""; + wxSizeEvent event; + long style=wxSL_HORIZONTAL| + wxSL_LABELS | + wxSL_BOTTOM; + + if (fullRunPriority==NULL) + { + fullLabel.Create((wxWindow *)this,-1,_T("Priority")); + fullRunPriority=new wxSlider((wxWindow *)this, + WINDOW_ID_CONFIG_FULL_PRIORITY, + globalStatistics.ReadPriority(true), + 0, + 100, + wxDefaultPosition, + wxDefaultSize, + style); + } + else + { + // Screen is already created + } +} + +void PriorityPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int panelWidth; + int panelHeight; + wxString msg; + int fullX; + int fullY; + int sliderWidth; + int sliderHeight; + int labelWidth=60; + int labelHeight=10; + int labelOffset=0; + + // Make sure the screen has been created + CreateScreen(); + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + sliderWidth=panelWidth; + sliderHeight=panelHeight/2; + fullX=labelWidth; + fullY=0; + sliderWidth-=labelWidth; + sliderWidth-=10; + labelOffset=(sliderHeight-labelHeight)/2; + labelOffset=20; + fullRunPriority->SetSize(fullX,fullY,sliderWidth,sliderHeight); + fullLabel.SetPosition(wxPoint(0,fullY+labelOffset)); +} + +void PriorityPanel::OnSliderChange(wxScrollEvent &event) +{ + int priority; + wxString priorityString; + + switch (event.GetId()) + { + case WINDOW_ID_CONFIG_FULL_PRIORITY: + priority=fullRunPriority->GetValue(); + globalStatistics.WritePriority(true,priority); + break; + } +} + diff --git a/PriorityPanel.h b/PriorityPanel.h new file mode 100644 index 0000000..a8d11ea --- /dev/null +++ b/PriorityPanel.h @@ -0,0 +1,29 @@ +#ifndef __PRIORITYPANEL +#define __PRIORITYPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" + +class PriorityPanel : public wxPanel +{ + public: + PriorityPanel(); + void CreateScreen(); + void OnSliderChange(wxScrollEvent &event); + void OnResize(wxSizeEvent &event); + protected: + wxSlider *fullRunPriority; + + private: + int columnToSort; + wxString configKey; + wxString labelText; + wxStaticText fullLabel; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/Progress.cpp b/Progress.cpp new file mode 100644 index 0000000..276e0e0 --- /dev/null +++ b/Progress.cpp @@ -0,0 +1,4 @@ +// Statsgen Includes +#include "Progress.h" + +StatusPanel *progress; diff --git a/Progress.h b/Progress.h new file mode 100644 index 0000000..b41cc08 --- /dev/null +++ b/Progress.h @@ -0,0 +1,9 @@ +#ifndef __PROGRESS +#define __PROGRESS + + +// Statsgen Includes +#include "StatusPanel.h" + +extern StatusPanel *progress; +#endif diff --git a/ProgressPanel.cpp b/ProgressPanel.cpp new file mode 100644 index 0000000..c46ffeb --- /dev/null +++ b/ProgressPanel.cpp @@ -0,0 +1,1026 @@ +// wx includes +#include "wx/artprov.h" +// Statsgen Includes +#include "ProgressPanel.h" +#include "ErrorPanel.h" +#include "ErrorData.h" +#include "Progress.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(ProgressPanel, wxPanel) + EVT_SIZE(ProgressPanel::OnResize) + EVT_BUTTON(WINDOW_ID_ERROR_BUTTON,ProgressPanel::OnButtonPressed) +END_EVENT_TABLE() + +ProgressPanel::ProgressPanel() +{ + + timeRemaining =NULL; + timeSpent =NULL; + counter =NULL; + description =NULL; + status =NULL; + maxValue =-1; + scale =1; + currentValue =0; + offset =0; + desiredLabelWidth =0; + previousTime =0; + dynamicSizing =false; + EnableTimeToGo(); + counterEnabled =true; + timeStepsCreated =0; + storingError =false; + statusIndex =0; + + EventUpdating(true); + +} + +void ProgressPanel::Reset() +{ + startTime=time(&startTime); + currentValue=0; + offset=0; + timeStepsCreated=0; + statusIndex=0; +} + +void ProgressPanel::CreateScreen() +{ + wxString label=""; + wxSize buttonSize(16,16); + + if (timeRemaining==NULL) + { + timeRemaining=new wxStaticText(this,-1,label); + timeSpent=new wxStaticText(this,-1,label); + counter=new wxStaticText(this,-1,label); + description=new wxStaticText(this,-1,label); + rate=new wxStaticText(this,-1,label); + status=new wxStaticText(this,GetId(),label); + resultButton=new wxBitmapButton(this,WINDOW_ID_ERROR_BUTTON,wxArtProvider::GetIcon(wxART_ERROR,wxART_OTHER,buttonSize)); + ClearErrors(); + + } +} + +ProgressPanel::~ProgressPanel() +{ +} + +void ProgressPanel::Initiate( + long maxIn, + const char *unitsIn, + long scaleIn, + const char *rateUnitsIn, + long rateScaleIn + ) +{ + + CreateScreen(); + + Reset(); + unitText=unitsIn; + maxValue=maxIn; + scale=scaleIn; + rateScale=rateScaleIn; + rateUnits=rateUnitsIn; + + +} + +int ProgressPanel::LabelWidth() +{ + wxSize itemSize; + + itemSize=description->GetSize(); + return (itemSize.GetWidth()); +} + +void ProgressPanel::SetLabelWidth(int labelWidth) +{ + desiredLabelWidth=labelWidth; + + wxSizeEvent dummyEvent; + + OnResize(dummyEvent); +} + +void ProgressPanel::SetLabel(const char *label) +{ + CreateScreen(); + description->SetLabel(label); +} + +void ProgressPanel::SetOffset(long value) +{ + offset=value; +} + +void ProgressPanel::WakeUp() +{ + Update(currentValue-offset); +} + +void ProgressPanel::UpdateColouredBar() +{ + if (timeToGoEnabled) + { + wxClientDC dc(this); + wxPen currentPen; + wxBrush currentBrush; + wxColour green(0,175,0); + wxColour red(175,0,0); + wxColour amber(175,0,175); + wxPen greenPen(green); + wxBrush greenBrush(green); + wxPen redPen(red); + wxBrush redBrush(red); + wxPen amberPen(amber); + wxBrush amberBrush(amber); + wxBrush chosenBrush; + wxPen chosenPen; + + wxSize size; + int maxWidth; + int width; + int height; + + float pixelsPerUnit; + + switch (OverallSeverity()) + { + case SeverityOK: + chosenBrush=greenBrush; + chosenPen=greenPen; + break; + case SeverityCaution: + chosenBrush=amberBrush; + chosenPen=amberPen; + break; + case SeverityError: + chosenBrush=redBrush; + chosenPen=redPen; + break; + default: + chosenBrush=greenBrush; + chosenPen=greenPen; + break; + } + currentPen =dc.GetPen(); + currentBrush =dc.GetBrush(); + + size=description->GetSize(); + maxWidth=size.GetWidth(); + size=GetSize(); + height=size.GetHeight(); + if (maxValue<=0) + { + pixelsPerUnit=(float)maxWidth; + } + else + { + pixelsPerUnit=(float)maxWidth/(float)maxValue; + } + width=(int)(pixelsPerUnit * (float)currentValue); + + dc.SetPen(chosenPen); + dc.SetBrush(chosenBrush); + dc.DrawRectangle(0,1,width,height-3); + dc.SetPen(chosenPen); + dc.SetBrush(currentBrush); + dc.DrawRectangle(width,1,maxWidth-width,height-3); + } + +} + +void ProgressPanel::Update(long value) +{ + wxString timeRemainingString; + wxString timeSpentString; + wxString progressString; + wxString rateString; + wxString msg; + long progressToGo; + time_t currentTime; + time_t elapsedTime; + time_t timeToGo; + long minutes; + long seconds; + float rateValue; + + currentTime=time(¤tTime); + elapsedTime=currentTime-startTime; + currentValue=value+offset; + if ((elapsedTime!=previousTime)/*||(previousTime==0)*/) + { + // Add the current time and value to the history list + // first shuffle the current values down one + historyTimes[0]=historyTimes[1]; + historyValues[0]=historyValues[1]; + historyTimes[1]=historyTimes[2]; + historyValues[1]=historyValues[2]; + if (timeStepsCreated==0) + { + historyTimes[0]=currentTime; + historyValues[0]=currentValue; + historyTimes[1]=currentTime; + historyValues[1]=currentValue; + historyTimes[2]=currentTime; + historyValues[2]=currentValue; + } + historyTimes[2]=currentTime; + historyValues[2]=currentValue; + previousTime=elapsedTime; + timeRemainingString="???"; + rateString="???"; + progressString="???"; + progressToGo=maxValue-currentValue; + if (progressToGo<0) + { + progressToGo=0; + } + if ((elapsedTime>0)&&(timeStepsCreated>0)) + { + if (timeToGoEnabled) + { + time_t rateElapsedTime; + long rateElapsedValue; + + rateElapsedTime=historyTimes[2]-historyTimes[0]; + rateElapsedValue=historyValues[2]-historyValues[0]; + //rateValue=((float)currentValue)/((float)elapsedTime); + + if ((rateElapsedTime>0)&&(rateElapsedValue>0)) + { + rateValue=((float)rateElapsedValue)/((float)rateElapsedTime); + timeToGo=(long)(((float)progressToGo)/rateValue); + rateValue/=((float)rateScale); + rateString.Printf("%0.1f%s / sec",rateValue,rateUnits.GetData()); + minutes=timeToGo/60; + seconds=timeToGo % 60; + timeRemainingString.Printf("%ld:%02ld",minutes,seconds); + /* + if (timeRemainingString.StartsWith("-")) + { + wxString outputMsg; + + outputMsg.Printf("rateElapsedTime [%ld] rateElapsedValue [%ld] rateValue [%f] timeToGo [%ld] rateValue [%f] minutes [%ld] seconds [%ld]", + rateElapsedTime,rateElapsedValue,rateValue, + timeToGo,rateValue,minutes,seconds); + wxMessageBox(outputMsg); + exit(0); + } + */ + } + else + { + timeRemainingString="???"; + rateString.Printf("???%s / sec",rateUnits.GetData()); + } + } + } + if (timeStepsCreated<2) + { + timeStepsCreated++; + } + if (timeToGoEnabled) + { + progressToGo/=scale; + progressString.Printf("%ld%s",progressToGo,unitText.GetData()); + } + else + { + progressString.Printf("%ld%s",currentValue/scale,unitText.GetData()); + } + minutes=elapsedTime / 60; + seconds=elapsedTime % 60; + timeSpentString.Printf("%ld:%02ld",minutes,seconds); + + if (timeToGoEnabled) + { + //timeRemaining->SetLabel(timeRemainingString); + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(timeRemaining); + event.SetString(timeRemainingString); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + timeRemaining->SetLabel(timeRemainingString); + wxSafeYield(); + } + event.SetClientData(rate); + event.SetString(rateString); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + rate->SetLabel(rateString); + wxSafeYield(); + } + } + if (counterEnabled) + { + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,EVENT_ID_PROGRESS_STATUS_TEXT); + //counter->SetLabel(progressString); + event.SetClientData(counter); + event.SetString(progressString); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + counter->SetLabel(progressString); + wxSafeYield(); + } + event.SetClientData(timeSpent); + event.SetString(timeSpentString); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + timeSpent->SetLabel(timeSpentString); + wxSafeYield(); + } + if (eventUpdating) + { + UpdateColouredBar(); + } + } + } + +} + +void ProgressPanel::Finalise() +{ + wxString errorText="done"; + + previousTime=0; + Update(currentValue-offset); + LogError(errorText,SeverityOK); + SetStatus(errorText); +} + +void ProgressPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int width; + int height; + int timeRemainingWidth; + int timeSpentWidth; + int counterWidth; + int descriptionWidth; + int rateWidth; + int statusWidth; + int buttonWidth; + int buttonHeight; + int gap=10; + int yBorder=11; + + CreateScreen(); + + itemSize=counter->GetSize(); + height=itemSize.GetHeight(); + + itemSize=resultButton->GetSize(); + buttonHeight=itemSize.GetHeight(); + buttonWidth=itemSize.GetWidth(); + + counterWidth =120; + timeSpentWidth =50; + statusWidth =250; + + timeRemainingWidth =50; + rateWidth =120; + + + if ((!counterEnabled) && + (dynamicSizing)) + { + counterWidth=0; + timeSpentWidth=0; + } + + if ((!timeToGoEnabled) && + (dynamicSizing)) + { + timeRemainingWidth=0; + rateWidth=0; + } + itemSize=description->GetSize(); + descriptionWidth=itemSize.GetWidth(); + if (desiredLabelWidth>0) + { + descriptionWidth=desiredLabelWidth; + } + + itemSize=GetSize(); + width=itemSize.GetWidth(); + if (dynamicSizing) + { + + statusWidth=width-(timeRemainingWidth+gap+ + timeSpentWidth+gap+ + counterWidth+gap+ + descriptionWidth+gap+ + gap+ + buttonWidth+gap+ + rateWidth+gap); + if (statusWidth<0) + { + statusWidth=0; + } + } + description->SetSize(0, + yBorder/2, + descriptionWidth,height); + + counter->SetSize(descriptionWidth+gap, + yBorder/2, + counterWidth,height); + + timeSpent->SetSize(descriptionWidth+gap+ + counterWidth+gap, + yBorder/2, + timeSpentWidth,height); + + timeRemaining->SetSize(descriptionWidth+gap+ + counterWidth+gap+ + timeSpentWidth+gap, + yBorder/2, + timeRemainingWidth,height); + + rate->SetSize(descriptionWidth+gap+ + counterWidth+gap+ + timeSpentWidth+gap+ + timeRemainingWidth+gap, + yBorder/2, + rateWidth,height); + status->SetSize(descriptionWidth+gap+ + counterWidth+gap+ + timeSpentWidth+gap+ + rateWidth+gap+ + timeRemainingWidth+gap, + yBorder/2, + statusWidth,height); + resultButton->SetSize(descriptionWidth+gap+ + counterWidth+gap+ + timeSpentWidth+gap+ + rateWidth+gap+ + timeRemainingWidth+gap+ + statusWidth+gap, + 0, + buttonWidth,buttonHeight); + + width=timeRemainingWidth+gap+ + timeSpentWidth+gap+ + counterWidth+gap+ + descriptionWidth+gap+ + statusWidth+gap+ + buttonWidth+gap+ + rateWidth+gap; + SetSize(width,height+yBorder+5); +} + +long ProgressPanel::CurrentValue() +{ + return (currentValue); +} + +bool ProgressPanel::GetEventUpdating() +{ + return (eventUpdating); +} + +void ProgressPanel::DisableCounter() +{ + counterEnabled=false; +} +void ProgressPanel::DisableTimeToGo() +{ + timeToGoEnabled=false; +} + +void ProgressPanel::EnableTimeToGo() +{ + timeToGoEnabled=true; +} + +void ProgressPanel::SetStatus(wxString &statusText) +{ + wxString errorText=""; + int severity=-1; + //status->SetLabel(statusText); + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(status); + event.SetString(statusText); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + status->SetLabel(statusText); + wxSafeYield(); + } + LogToDatabase(severity,errorText,statusText); +} + +wxBitmap ProgressPanel::SeverityImage(int severity) +{ + wxBitmap bitmap; + wxSize buttonSize(16,16); + switch (severity) + { + default: + case SeverityNotRun: + bitmap=wxArtProvider::GetIcon(wxART_NORMAL_FILE,wxART_OTHER,buttonSize); + break; + case SeverityOK: + bitmap=wxArtProvider::GetIcon(wxART_TICK_MARK,wxART_OTHER,buttonSize); + break; + case SeverityCaution: + bitmap=wxArtProvider::GetIcon(wxART_INFORMATION,wxART_OTHER,buttonSize); + break; + case SeverityError: + bitmap=wxArtProvider::GetIcon(wxART_ERROR,wxART_OTHER,buttonSize); + break; + } + + return (bitmap); +} + +void ProgressPanel::SetResultSeverity(int severity) +{ + //wxBitmap bitmap; + + //bitmap=SeverityImage(severity); + //resultButton->SetBitmapLabel(bitmap); + + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,EVENT_ID_PROGRESS_BUTTON); + event.SetClientData(resultButton); + event.SetInt(severity); + wxPostEvent(globalStatistics.mainEventHandler,event); +} + +void ProgressPanel::ClearErrors() +{ + wxString label=""; + wxString SQL; + + errorSeverities.Clear(); + errors.Clear(); + SetSeverityIcon(); + timeRemaining->SetLabel(label); + timeSpent->SetLabel(label); + counter->SetLabel(label); + rate->SetLabel(label); + status->SetLabel(label); + statusIndex=0; + if (!storingError) + { + if (description!=NULL) + { + storingError=true; + SQL.Printf("delete from %s where stage='%s'", + TableName().GetData(), + description->GetLabel().GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + storingError=false; + } + } +} + +int ProgressPanel::OverallSeverity() +{ + int severity=SeverityNotRun; + int severityCount; + int thisSeverity; + int severityIndex; + + severityCount=errorSeverities.GetCount(); + for (severityIndex=0;severityIndexseverity) + { + severity=thisSeverity; + } + } + + return (severity); +} + +void ProgressPanel::SetSeverityIcon() +{ + SetResultSeverity(OverallSeverity()); +} + +void ProgressPanel::LogError(wxString &errorTextIn,int severity) +{ + wxString status=""; + wxString errorText; + wxString panelDescription; + if (!storingError) + { + panelDescription=GetDescription(); + panelDescription=panelDescription+" "; + panelDescription=panelDescription.Left(25); + errorText.Printf("%s: %s",panelDescription.GetData(),errorTextIn.GetData()); + errorSeverities.Add(severity); + errors.Add(errorText); + SetSeverityIcon(); + LogToDatabase(severity,errorText,status); + } +} + +void ProgressPanel::OnButtonPressed(wxCommandEvent &event) +{ + wxString title="Errors"; + wxString name=""; + ErrorPanel *errorPanel; + bool save; + + GenericOKCancelDialog dialog(this,-1,title,wxDefaultPosition,wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + ""); + + errorPanel=new ErrorPanel(errors,errorSeverities); + errorPanel->Create(&dialog,-1, + wxDefaultPosition,wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + errorPanel->CreateScreen(); + dialog.SetPanel(errorPanel); + dialog.CreateDialog(); + save=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + if (save) + { + wxString filename; + + filename=wxFileSelector("Choose a save location for error file"); + if (filename.Length()>0) + { + FILE *fp; + + fp=fopen(filename.GetData(),"w"); + if (fp!=NULL) + { + int errorCount; + int errorIndex; + wxString errorText; + wxString errorSeverity; + int severity; + + errorCount=errors.GetCount(); + for (errorIndex=0;errorIndexGetLabel(); + storingError=true; + SQL.Printf("insert into %s " + "(stage,statusindex,logtime,status,severity,error)" + "values" + "('%s',%d,%d,'%s','%s','%s')", + TableName().GetData(), + stage.GetData(), + statusIndex, + logTime, + statusText.GetData(), + severityString.GetData(), + globalStatistics.statsgenDatabase.SafeForInsert(errorText).GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + statusIndex++; + storingError=false; + } +} + +wxString ProgressPanel::GetTimeRemaining() +{ + return (timeRemaining->GetLabel()); +} + +wxString ProgressPanel::GetTimeSpent() +{ + return (timeSpent->GetLabel()); +} + +wxString ProgressPanel::GetDescription() +{ + return (description->GetLabel()); +} + +wxString ProgressPanel::GetRate() +{ + return (rate->GetLabel()); +} + +wxString ProgressPanel::GetCounter() +{ + return (counter->GetLabel()); +} + +wxString ProgressPanel::GetStatusPanel() +{ + return (status->GetLabel()); +} + +int ProgressPanel::GetErrorCount() +{ + return (errorSeverities.GetCount()); +} + +void ProgressPanel::SetTimeRemaining(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(timeRemaining); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + timeRemaining->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetTimeSpent(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(timeSpent); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + timeSpent->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetDescription(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(description); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + description->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetRate(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(rate); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + rate->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetCounter(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(counter); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + counter->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetStatusPanel(wxString &value) +{ + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, + EVENT_ID_PROGRESS_STATUS_TEXT); + event.SetClientData(status); + event.SetString(value); + if (eventUpdating) + { + wxPostEvent(globalStatistics.mainEventHandler,event); + } + else + { + status->SetLabel(value); + wxSafeYield(); + } +} + +void ProgressPanel::SetErrors(wxArrayInt &severitiesIn,wxArrayString &errorsIn) +{ + WX_APPEND_ARRAY(errorSeverities,severitiesIn); + WX_APPEND_ARRAY(errors,errorsIn); + SetSeverityIcon(); +} + +bool ProgressPanel::UpdateClone(ProgressPanel *destinationPanel) +{ + wxString sourceTimeRemaining; + wxString sourceTimeSpent; + wxString sourceDescription; + wxString sourceRate; + wxString sourceStatus; + wxString sourceCounter; + int sourceErrorCount; + + wxString destinationTimeRemaining; + wxString destinationTimeSpent; + wxString destinationDescription; + wxString destinationRate; + wxString destinationStatus; + wxString destinationCounter; + int destinationErrorCount; + + bool panelUpdated = false; + if (destinationPanel==NULL) + { + return false; + } + sourceTimeRemaining =GetTimeRemaining(); + sourceTimeSpent =GetTimeSpent(); + sourceDescription =GetDescription(); + sourceRate =GetRate(); + sourceStatus =GetStatusPanel(); + sourceErrorCount =GetErrorCount(); + sourceCounter =GetCounter(); + + destinationTimeRemaining =destinationPanel->GetTimeRemaining(); + destinationTimeSpent =destinationPanel->GetTimeSpent(); + destinationDescription =destinationPanel->GetDescription(); + destinationRate =destinationPanel->GetRate(); + destinationStatus =destinationPanel->GetStatusPanel(); + destinationErrorCount =destinationPanel->GetErrorCount(); + destinationCounter =destinationPanel->GetCounter(); + + + destinationPanel->counterEnabled=counterEnabled; + if (sourceTimeRemaining.Cmp(destinationTimeRemaining)!=0) + { + panelUpdated = true; + destinationPanel->SetTimeRemaining(sourceTimeRemaining); + } + if (sourceTimeSpent.Cmp(destinationTimeSpent)!=0) + { + panelUpdated = true; + destinationPanel->SetTimeSpent(sourceTimeSpent); + } + if (sourceDescription.Cmp(destinationDescription)!=0) + { + panelUpdated = true; + destinationPanel->SetDescription(sourceDescription); + } + if (sourceRate.Cmp(destinationRate)!=0) + { + panelUpdated = true; + destinationPanel->SetRate(sourceRate); + } + if (sourceStatus.Cmp(destinationStatus)!=0) + { + panelUpdated = true; + destinationPanel->SetStatus(sourceStatus); + } + if (sourceCounter.Cmp(destinationCounter)!=0) + { + panelUpdated = true; + destinationPanel->SetCounter(sourceCounter); + } + if (sourceErrorCount != destinationErrorCount) + { + // Need to add to errors here actually + destinationPanel->SetErrors(errorSeverities,errors); + } + + if (panelUpdated) + { + wxSizeEvent event; + destinationPanel->OnResize(event); + wxSafeYield(); + } + return (panelUpdated); +} + +void ProgressPanel::EventUpdating(bool value) +{ + eventUpdating=value; +} diff --git a/ProgressPanel.h b/ProgressPanel.h new file mode 100644 index 0000000..65e8da1 --- /dev/null +++ b/ProgressPanel.h @@ -0,0 +1,123 @@ +#ifndef __PROGRESSPANEL +#define __PROGRESSPANEL + +#include +#include +#include + +#define MAX_TIME_STEPS 3 + +// Statsgen Includes +#include "WindowIDs.h" + + enum { + SeverityNotRun=0, + SeverityOK, + SeverityCaution, + SeverityError, + SeverityMax}; + +class ProgressPanel : public wxPanel +{ + public: + ProgressPanel(); + ~ProgressPanel(); + void EventUpdating(bool value); + + void WakeUp(); + void SetLabel(const char *label); + int LabelWidth(); + void SetLabelWidth(int width); + void Initiate( + long top, + const char *units, + long scale=1, + const char *rateUnits="", + long rateScale=1 + ); + void Update(long value); + + void OnResize(wxSizeEvent &event); + void OnButtonPressed(wxCommandEvent &event); + void SetOffset(long offsetIn); + void Finalise(); + long CurrentValue(); + void EnableTimeToGo(); + void DisableTimeToGo(); + void DisableCounter(); + void SetStatus(wxString &statusText); + void Reset(); + void SetSeverityIcon(); + void ClearErrors(); + void LogError(wxString &errorText,int severity); + static wxBitmap SeverityImage(int severity); + static wxString SeverityString(int severity); + void DynamicSizing(); + static wxString TableName(); + static wxString CreateTableSQL(); + void LogToDatabase(int severity,wxString &errorText,wxString &statusText); + + wxString GetTimeRemaining(); + wxString GetTimeSpent(); + wxString GetDescription(); + wxString GetRate(); + wxString GetCounter(); + wxString GetStatusPanel(); + int GetErrorCount(); + void SetTimeRemaining(wxString &value); + void SetTimeSpent(wxString &value); + void SetDescription(wxString &value); + void SetRate(wxString &value); + void SetCounter(wxString &value); + void SetStatusPanel(wxString &value); + void SetErrors(wxArrayInt &severitiesIn,wxArrayString &errorsIn); + bool UpdateClone(ProgressPanel *clonePanel); + bool GetEventUpdating(); + void UpdateColouredBar(); + int OverallSeverity(); + + protected: + + public: + time_t previousTime; + time_t startTime; + bool counterEnabled; + private: + void CreateScreen(); + void SetResultSeverity(int severity); + bool dynamicSizing; + + wxStaticText *timeRemaining; + wxStaticText *timeSpent; + wxStaticText *counter; + wxStaticText *description; + wxStaticText *rate; + wxStaticText *status; + wxBitmapButton *resultButton; + + wxString unitText; + int desiredLabelWidth; + + long maxValue; + long currentValue; + long scale; + long offset; + long rateScale; + wxString rateUnits; + + bool timeToGoEnabled; + + wxArrayInt errorSeverities; + wxArrayString errors; + time_t historyTimes[MAX_TIME_STEPS]; + long historyValues[MAX_TIME_STEPS]; + int timeStepsCreated; + bool storingError; + int statusIndex; + + bool eventUpdating; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/PunkbusterBanFile.cpp b/PunkbusterBanFile.cpp new file mode 100644 index 0000000..0aa9498 --- /dev/null +++ b/PunkbusterBanFile.cpp @@ -0,0 +1,83 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "GlobalStatistics.h" +#include "Progress.h" +#include "PunkbusterBanFile.h" + +PunkbusterBanFile::PunkbusterBanFile(wxFileName &filenameIn) +{ + filename=filenameIn; + LoadFile(); +} + +PunkbusterBanFile::~PunkbusterBanFile() +{ +} + +void PunkbusterBanFile::LoadFile() +{ + int banCount; + int banIndex; + wxTextFile fp; + bool retVal; + wxString status; + wxString line; + wxString beforeName; + wxString afterName; + wxString name; + wxString reason; + + status="Reading Ban File"; progress->SetStatus(status); + retVal=fp.Open(filename.GetFullPath()); + + names.Clear(); + reasons.Clear(); + + if (retVal) + { + banCount=fp.GetLineCount(); + for (banIndex=0;banIndex0) + { + beforeName=line.BeforeFirst('"'); + afterName=line.AfterLast('"'); + name=line.AfterFirst('"'); + name=name.BeforeLast('"'); + // name is currently set to "name and ip" + name=name.BeforeLast('"'); + name=name.BeforeLast('"'); + + reason=beforeName+" "+afterName; + reasons.Add(reason); + names.Add(name); + } + } + } +} + +void PunkbusterBanFile::AddToDropList() +{ + int banCount; + int banIndex; + wxString name; + + banCount=names.GetCount(); + for (banIndex=0;banIndex +#include +#include + +// Statsgen Includes + +class PunkbusterBanFile +{ + public: + PunkbusterBanFile(wxFileName &filenameIn); + virtual ~PunkbusterBanFile(); + void AddToDropList(); + + private: + void LoadFile(); + wxFileName filename; + + wxArrayString names; + wxArrayString reasons; + +}; + + +#endif diff --git a/QuakeWarsLogFile.cpp b/QuakeWarsLogFile.cpp new file mode 100644 index 0000000..c9e5370 --- /dev/null +++ b/QuakeWarsLogFile.cpp @@ -0,0 +1,76 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "QuakeWarsLogFile.h" +#include "QuakeWarsLogFileReader.h" +#include "GlobalStatistics.h" +#include "Progress.h" +#include "Server.h" + +QuakeWarsLogFile::QuakeWarsLogFile() : LogFile() +{ + STATSGEN_DEBUG_FUNCTION_START("QuakeWarsLogFile","Constructor") +// logFileReader=NULL; +// serverType=""; + STATSGEN_DEBUG_FUNCTION_END +} + +long QuakeWarsLogFile::Size() +{ + int fileCount; + int fileIndex; + wxString filename; + long totalFileSize; + + totalFileSize=0; + fileCount=filenames.GetCount(); + for (fileIndex=0;fileIndex +#include +#include +#include + +// Statsgen includes +#include "LogFileReader.h" +#include "LogFile.h" + +class LogFile; +class Server; + +class QuakeWarsLogFile : public LogFile +{ + public: + QuakeWarsLogFile(); + virtual bool Initiate(wxString &serverTypeIn, + wxArrayString &filenameIn, + wxArrayString &secondaryFilenameIn); + virtual long Size(); + virtual ~QuakeWarsLogFile(); + +}; + +#endif diff --git a/QuakeWarsLogFileReader.cpp b/QuakeWarsLogFileReader.cpp new file mode 100644 index 0000000..67ecaf3 --- /dev/null +++ b/QuakeWarsLogFileReader.cpp @@ -0,0 +1,880 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "GlobalStatistics.h" +#include "QuakeWarsLogFileReader.h" +#include "ErrorData.h" +#include "Round.h" +#include "ConfigData.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "Server.h" +#include "Round.h" +#include "MultiFile.h" + + +QuakeWarsLogFileReader::QuakeWarsLogFileReader(wxArrayString &filenameIn,wxArrayString &secondaryFilenameIn,wxString &serverTypeIn): LogFileReader(filenameIn,serverTypeIn) +{ + STATSGEN_DEBUG_FUNCTION_START("QuakeWarsLogFileReader","Constructor"); + secondaryFilenames =secondaryFilenameIn; + secondaryLastRoundEndedAt =0; + + STATSGEN_DEBUG_FUNCTION_END +} + +time_t QuakeWarsLogFileReader::StripTimeFromLine(wxString &lineRead) +{ + time_t lineTime; + wxString lineTimeString; + + lineTimeString=lineRead.Left(19); + lineTime=DecodeTime(lineTimeString); + if (lineTime>0) + { + lineRead=lineRead.Mid(22); + } + + return (lineTime); +} + +time_t QuakeWarsLogFileReader::DecodeTime(wxString &timeString) +{ + wxDateTime decodedTime; + wxChar *parseResult; + time_t retVal; + char *dateFormat="%Y-%m-%d %H:%M:%S"; + char *timeStringChar; + + timeStringChar=(char *)timeString.GetData(); + if (timeString.Length()!=19) + { + retVal=0; + } + else + { + parseResult=(wxChar *)decodedTime.ParseFormat(timeStringChar,dateFormat); + if (parseResult=NULL) + { + retVal=0; + } + else + { + retVal=decodedTime.GetTicks(); + } + } + + return (retVal); +} + +time_t QuakeWarsLogFileReader::DecodeMapStartTime(wxString &lineRead, + const char *prefix) +{ + wxString timeLine; + time_t timeExtracted; + + timeLine=lineRead.Mid(strlen(prefix)); + timeLine=timeLine.Left(19); + timeExtracted=DecodeTime(timeLine); + + return (timeExtracted); +} + +void QuakeWarsLogFileReader::TrimQuotes(wxString &line) +{ + int lineLength; + + if (line[0]=='\'') + { + line=line.Mid(1); + } + lineLength=line.Length(); + if (lineLength>0) + { + if (line[lineLength-1]=='\'') + { + line=line.Left(lineLength-1); + } + } +} + +void QuakeWarsLogFileReader::SortPlayersByLength( + wxArrayString &playerNames, + wxArrayString &playerTeams, + wxArrayString &playerClasses) +{ + wxString playerName; + wxString playerTeam; + wxString playerClass; + wxArrayString outplayerNames; + wxArrayString outplayerTeams; + wxArrayString outplayerClasses; + int nameCount; + int nameIndex; + int longestNameIndex; + int longestNameLength; + int nameLength; + + // Need the longest filename first + nameCount=playerNames.GetCount(); + while (nameCount>0) + { + longestNameLength=0; + for (nameIndex=0;nameIndex=longestNameLength) + { + longestNameLength=nameLength; + longestNameIndex=nameIndex; + } + } + playerName=playerNames.Item(longestNameIndex); + playerClass=playerClasses.Item(longestNameIndex); + playerTeam=playerTeams.Item(longestNameIndex); + + playerNames.RemoveAt(longestNameIndex); + playerClasses.RemoveAt(longestNameIndex); + playerTeams.RemoveAt(longestNameIndex); + + outplayerNames.Add(playerName); + outplayerClasses.Add(playerClass); + outplayerTeams.Add(playerTeam); + nameCount=playerNames.GetCount(); + } + + playerNames=outplayerNames; + playerClasses=outplayerClasses; + playerTeams=outplayerTeams; +} + +wxString QuakeWarsLogFileReader::SubstitutePlayerNamesInLine( + wxString &lineRead,wxArrayString &playerNames) +{ + int playerCount; + int playerIndex; + wxString playerName; + wxString updatedLine; + + updatedLine=lineRead; + playerCount=playerNames.GetCount(); + for (playerIndex=0;playerIndexUpdate(currentPosition); + lineRead=ReadLine(secondaryLogfileBuffer,errorData); + STATSGEN_DEBUG(DEBUG_RARELY,lineRead) + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_PLAYER_XP)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"XP Found") + xpLine=lineRead+" "; + xpLine+=lastPlayerName; + xpIndex=xpLines.Index(xpLine); + if (xpIndex!=wxNOT_FOUND) + { + xpLines.RemoveAt(xpIndex); + } + xpLines.Add(xpLine); + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_MAPSTARTED)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Round Start Found") + xpLines.Clear(); + roundStarted=true; + mapStartTime=DecodeMapStartTime(lineRead, + QUAKEWARS_LOGLINEPREFIX_MAPSTARTED); + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_SERVER)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Server Found") + serverName=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_SERVER)); + STATSGEN_DEBUG(DEBUG_RARELY,serverName) + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_MAP)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Map Found") + mapName=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_MAP)); + TrimQuotes(mapName); + mapName=mapName.AfterLast('/'); + mapName=mapName.BeforeFirst('.'); + mapName=mapName.Lower(); + STATSGEN_DEBUG(DEBUG_RARELY,mapName) + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_RULESET)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"gametype Found") + gameType=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_RULESET)); + gameType=gameType.Lower(); + STATSGEN_DEBUG(DEBUG_RARELY,gameType) + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_TEAM)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"team Found") + currentTeam=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_TEAM)); + currentTeam=currentTeam.Lower(); + STATSGEN_DEBUG(DEBUG_RARELY,currentTeam) + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_PLAYER)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"player Found") + playerLine=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_PLAYER)); + // Player Line contains + // 'playername' Class 'class' + TrimQuotes(playerLine); + // Player Line contains + // playername' Class 'class + playerClass=playerLine.AfterLast('\''); + playerLine=playerLine.BeforeLast(' '); + // Player Line contains + // playername' Class + playerLine=playerLine.BeforeLast(' '); + // Player Line contains + // playername' + playerName=playerLine.BeforeLast('\''); + // At this point we have + // player Name + // Player Class + // and hopefully the current player team + playerIndex=playerNames.Index(playerName); + if (playerIndex!=wxNOT_FOUND) + { + // Existing player - update its values + // just remove it and we will add it at end + playerNames.RemoveAt(playerIndex); + playerTeams.RemoveAt(playerIndex); + playerClasses.RemoveAt(playerIndex); + } + playerNames.Add(playerName); + playerClasses.Add(playerClass); + playerTeams.Add(currentTeam); + lastPlayerName=playerName; + wxString msg; + msg.Printf("name [%s] class=[%s] team=[%s]", + playerName.GetData(), + playerClass.GetData(), + currentTeam.GetData()); + STATSGEN_DEBUG(DEBUG_RARELY,msg) + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_MAPFINISHED)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"map finished Found") + mapEndTime=DecodeMapStartTime(lineRead, + QUAKEWARS_LOGLINEPREFIX_MAPFINISHED); + } else + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_WINNINGTEAM)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"team win Found") + winningTeam=lineRead.Mid(strlen(QUAKEWARS_LOGLINEPREFIX_WINNINGTEAM)); + winningTeam=winningTeam.Lower(); + roundNearlyFinished=true; + STATSGEN_DEBUG(DEBUG_RARELY,winningTeam) + } else + { + // Dropped through + if (roundNearlyFinished) + { + roundFinished=true; + } + } + } + STATSGEN_DEBUG(DEBUG_ALWAYS,"Finished Decoding Objective File") + if ((roundFinished) && + (gameType.Length()>0) && + (mapName.Length()>0) && + (mapStartTime!=0) && + (mapEndTime!=0) && + (playerNames.GetCount()!=0) + ) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Decoding Kill File") + Round currentRound; + + + // Located round details - time to search for kills + // in the primary logfile + // First lets sort the player names into length order + SortPlayersByLength(playerNames,playerTeams,playerClasses); + roundFinished=false; + roundStarted=false; + inRound=false; + wxDateTime roundStartTime(mapStartTime); + // set up the current round values + currentRound.Initiate(this,roundStartTime,lineRead); + currentRound.SetStartingCondition(serverIndex, + mapName, + mapEndTime-mapStartTime, + gameType); + while (!logfileBuffer.Eof() && (!roundFinished)) + { + currentPosition=secondaryLogfileBuffer.TellI(); + currentPosition+=logfileBuffer.TellI(); + progress->Update(currentPosition); + lastRoundEndedAt=logfileBuffer.TellI(); + lineRead=ReadLine(logfileBuffer,errorData); + STATSGEN_DEBUG(DEBUG_RARELY,lineRead) + lineTime=StripTimeFromLine(lineRead); + if (lineRead.StartsWith(QUAKEWARS_LOGLINEPREFIX_PLAYER_PBGUID)) + { + wxString workingLine; + wxString pbGUID; + wxString playerName; + int playerIndex; + workingLine=lineRead.AfterFirst('['); + pbGUID=workingLine.BeforeFirst(']'); + workingLine=workingLine.AfterFirst(']'); + playerName=workingLine.AfterFirst('"'); + playerName=playerName.BeforeLast('"'); + playerIndex=pbNames.Index(playerName); + if (playerIndex!=wxNOT_FOUND) + { + pbGUIDs.RemoveAt(playerIndex); + pbNames.RemoveAt(playerIndex); + } + pbGUIDs.Add(pbGUID); + pbNames.Add(playerName); + } + else if (lineRead.StartsWith("si_version")) + { + wxString variable; + wxString value; + + variable=lineRead.BeforeFirst(':'); + value=lineRead.AfterFirst(' '); + + serverVariables.Add(variable); + serverValues.Add(value); + } + else if (lineRead.StartsWith("g_version")) + { + variable=lineRead.BeforeFirst(':'); + value=lineRead.AfterFirst(' '); + + serverVariables.Add(variable); + serverValues.Add(value); + } + + useThisLine=true; + // At this point i should have a line and it's time + if (lineTime>0) + { + STATSGEN_DEBUG(DEBUG_RARELY,"line time found") + // we have decoded a line time + // we can use this to identify if this kill + // is within a round or not + if ((lineTime>=mapStartTime) && (lineTime<=mapEndTime)) + { + STATSGEN_DEBUG(DEBUG_RARELY,"line time within range") + inRound=true; + } + if (lineTime>mapEndTime) + { + STATSGEN_DEBUG(DEBUG_RARELY,"line time greater than range") + // After end of round + inRound=false; + roundFinished=true; + // This line is actually part of next round so rewind + logfileBuffer.SeekI(lastRoundEndedAt); + } + if (lineTime=0) + { + if (weaponIndex>0) + { + playerName=lineRead.Left(weaponIndex-1); + } + else + { + // No player name + playerName=""; + } + targetName=lineRead.Mid(weaponIndex+weaponString.Length()); + // At this point we have a weapon, player name, + // and target name + playerIndex=playerNames.Index(playerName); + targetIndex=playerNames.Index(targetName); + if (playerName.Length()==0) + { + playerName=""; + playerTeam=""; + playerClass=""; + playerIndex=0; + } + else + { + if (playerIndex!=wxNOT_FOUND) + { + playerTeam=playerTeams.Item(playerIndex); + playerClass=playerClasses.Item(playerIndex); + } + } + if (targetIndex!=wxNOT_FOUND) + { + targetTeam=playerTeams.Item(targetIndex); + targetClass=playerClasses.Item(targetIndex); + } + if ((targetIndex!=wxNOT_FOUND) && + ((playerIndex!=wxNOT_FOUND) || (playerName.Length()==0)) + ) + { + DecodedKill decodedKill; + wxString msg; + msg.Printf("player [%s] class [%s] team [%s] " + "weapon [%s] " + "target [%s] class [%s] team [%s]", + playerName.GetData(), + playerClass.GetData(), + playerTeam.GetData(), + weapon.GetData(), + targetName.GetData(), + targetClass.GetData(), + targetTeam.GetData() + ); + STATSGEN_DEBUG(DEBUG_RARELY,msg) + + // we have a valid + // player name + // target name + // weapon + // This does appear to be a kill + if (playerName.Length()==0) + { + playerName=WORLD_PLAYER_NAME; + playerTeam=WORLD_PLAYER_TEAM; + playerGUID=WORLD_PLAYER_ID; + playerClass=WORLD_PLAYER_CLASS; + } + else + { + playerGUID=PlayerGUID(playerName,pbGUIDs,pbNames); + } + targetGUID=PlayerGUID(targetName,pbGUIDs,pbNames); + targetLocation=targetTeam; + playerAmmo="none"; + decodedKill.playerName=playerName; + decodedKill.playerTeam=playerTeam; + decodedKill.playerClass=playerClass; + decodedKill.playerID=playerGUID; + decodedKill.playerAmmo=playerAmmo; + decodedKill.playerWeapon=weapon; + + decodedKill.targetName=targetName; + decodedKill.targetTeam=targetTeam; + decodedKill.targetClass=targetClass; + decodedKill.targetID=targetGUID; + decodedKill.targetLocation=targetLocation; + currentRound.AddKill(decodedKill); + } + } + } + } + } + } + // Need to add in the team wins / losses; + for (variableIndex=0;variableIndexAddVariable(variable,value); + } + variable="hostname"; + currentRound.AddVariable(variable,serverName); + thisServer->AddVariable(variable,serverName); + playerCount=playerNames.GetCount(); + for (playerIndex=0;playerIndex 0.000000001) + { + // Only add if we actually have points + playerIndex=playerNames.Index(playerName); + if (playerIndex!=wxNOT_FOUND) + { + playerGUID=PlayerGUID(playerName,pbGUIDs,pbNames); + // ok - got enough info + // can work out + currentRound.AddXPPoints(playerName, + playerGUID, + xpKey, + xpPoints); + } + } + } + + currentRound.roundDuration=wxTimeSpan::Seconds(mapEndTime-mapStartTime); + currentRound.serverIndex=serverIndex; + + if (!currentRound.IsDropped()) + { + globalStatistics.rounds.Add(currentRound); + int xpIndex; + int xpCount; + XPPoints xp; + + xpCount=currentRound.xpPoints.GetCount(); + for (xpIndex=0;xpIndexLogError(errorMessage,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + } + STATSGEN_DEBUG_FUNCTION_END +} + +QuakeWarsLogFileReader::~QuakeWarsLogFileReader() +{ +} + +void QuakeWarsLogFileReader::StartFromBeginning() +{ + STATSGEN_DEBUG_FUNCTION_START("QuakeWarsLogFileReader","StartFromBeginning") + secondaryLastRoundEndedAt=0; + LogFileReader::StartFromBeginning(); + STATSGEN_DEBUG_FUNCTION_END +} + +bool QuakeWarsLogFileReader::IsWorldPlayer(wxString &guid,wxString &playerTeam,wxString &playerName) +{ + return ((guid.Length()==0) && (playerName.Length()==0)); +} + diff --git a/QuakeWarsLogFileReader.h b/QuakeWarsLogFileReader.h new file mode 100644 index 0000000..80ae0d9 --- /dev/null +++ b/QuakeWarsLogFileReader.h @@ -0,0 +1,75 @@ +#ifndef __QUAKEWARSLOGFILEREADER +#define __QUAKEWARSLOGFILEREADER + +#define QUAKEWARS_LOGLINEPREFIX_MAPSTARTED "Map Started: Real Time: " +#define QUAKEWARS_LOGLINEPREFIX_SERVER "Server: " +#define QUAKEWARS_LOGLINEPREFIX_MAP "Map: " +#define QUAKEWARS_LOGLINEPREFIX_TIMELIMIT "Timelimit: " +#define QUAKEWARS_LOGLINEPREFIX_RULESET "Ruleset: " +#define QUAKEWARS_LOGLINEPREFIX_TEAM "Team: " +#define QUAKEWARS_LOGLINEPREFIX_PLAYER "Player: " +#define QUAKEWARS_LOGLINEPREFIX_MAPFINISHED "Map Finished: Real Time: " +#define QUAKEWARS_LOGLINEPREFIX_WINNINGTEAM "Winning Team: " +#define QUAKEWARS_LOGLINEPREFIX_ALLSTATSCLEARED "All Stats Cleared" +#define QUAKEWARS_LOGLINE_PLAYER_SUBSTITUTE "PLAYER" +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_JOIN "PLAYER joined the " +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_JOIN2 " joined the " +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_SPEECH "PLAYER: " +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_KILL "PLAYER [" +#define QUAKEWARS_LOGLINESUFFIX_PLAYER_KILL "] PLAYER" +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_PBGUID "PunkBuster Server: New Connection (slot #" +#define QUAKEWARS_LOGLINEPREFIX_PLAYER_XP "XP: " +// wxWindows includes +#include +#include +#include +#include +#include + +// statsgen includes +#include "ErrorData.h" +#include "LogFileReader.h" +#include "Round.h" +#include "MultiFile.h" + +class Server; + +class QuakeWarsLogFileReader : public LogFileReader +{ + public: + QuakeWarsLogFileReader(wxArrayString &filenameIn, + wxArrayString &secondaryFilenameIn, + wxString &serverTypeIn); + virtual ~QuakeWarsLogFileReader(); + virtual void ProcessLogFile(Server *server,int serverIndex); + virtual void StartFromBeginning(); + virtual bool IsWorldPlayer(wxString &guid,wxString &team,wxString &playerName); + + protected: + wxString PlayerGUID(wxString &playerName,wxArrayString &pbGUIDs,wxArrayString &pbNames); + bool DecodeRound(MultiFile &logfileBuffer, + MultiFile &secondaryLogfileBuffer, + int serverIndex, + wxArrayString &pbGUIDs, + wxArrayString &pbNames); + time_t DecodeMapStartTime(wxString &lineRead, + const char *prefix); + time_t DecodeTime(wxString &timeString); + + time_t StripTimeFromLine(wxString &lineRead); + void TrimQuotes(wxString &line); + void SortPlayersByLength( + wxArrayString &playerNames, + wxArrayString &playerTeams, + wxArrayString &playerClasses); + wxString SubstitutePlayerNamesInLine( + wxString &lineRead, + wxArrayString &playerNames); + + + private: + wxArrayString secondaryFilenames; + +}; + +#endif diff --git a/README.md b/README.md index c75269b..ec1d037 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,388 @@ -# statsgen -A Statistics Generator for COD 1/2/4/5, MOHAA, Spearhead, Wolfenstein/Enemy Territory and Quake Wars. +# Statsgen 2 +Statsgen 2 is a Statistics Generator for Call Of Duty 1/2/4/5, MOHAA, Spearhead, Wolfenstein/Enemy Territory and Quake Wars. Statsgen automatically downloads the server logfiles, processes them using a flexible template system, and then transmits the resultant webpages to the webserver. Templating allows the pages produced to be very flexible to fit in with the style of your clan website. + +# Building Statsgen 2 + +## Build environment +- MinGW 0.6.3 +- Msys 1.0.11 + +### Installing MinGW on Windows +1. Download the MinGW Installer: https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe/ +1. Install MinGW to C:\MinGW +1. After installation, open the MinGW Installation Manager. +1. In the left tab, click 'Basic Setup' and mark the mingw32-gcc-g++ and mingw32-base packages for installation. +1. In the top left corner, click Installation > Apply Changes + +### Installing MSYS on Windows +1. Download MSYS: http://downloads.sourceforge.net/mingw/MSYS-1.0.11.exe +1. The Default Destination of C:\msys\1.0 is fine, so click Next > +1. The default folder of MinGW is fine, so click Next > Install +1. A cmd shell will pop-up asking if you want to continue with the post install, enter y enter +1. Answer y you do have MinGW Installed. +1. Enter `c:/mingw` as the path where MinGW is installed. **NOTE the FORWARD slash (!)** +1. It should confirm that you have make.exe installed, press any key to continue. +1. Click Finish you are done the installation. + +## Required third party components +- wxWidgets 3.1.1 +- sqllite 3.26.0 +**Note:** The versions listed above are the latest versions as tested by Shaun Jackson. Newer versions might work as well. + +### WxWidgets +1. Download the source: https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.zip +1. Extract the source to a folder +1. Start MSys and navigate to the `build` folder inside the folder you just created +1. Run the following commands: +``` +../configure --disable-shared --enable-monolithic +make +``` +This builds the wxWidgets library how it is expected to be built + +### SQLLite +1. Download the autoconf source code: https://www.sqlite.org/2018/sqlite-autoconf-3260000.tar.gz +1. Extract the source to a folder +1. Start MSys and navigate to the `build` folder inside the folder you just created +1. Type `make` + +## Statsgen 2 +1. Clone this repository +2. Edit the makefile. Change the paths pointing to wxWidgets and sqlite folders accordingly. +3. The other 2 configurable variables inside the makefile are: +- DEBUG_FLAG=-DDEBUG +Setting this allows you to switch on debugging dynamically during runtime +comment this out if you want all debug to be disabled +- The final two state where statsgen tries to connect to in order to get it's +image packs +STATSGEN_WEBSITE_ADDRESS="www.statsgen.co.uk" +STATSGEN_WEBSITE_PORT=80 +These should not be changed unless you intend to host your own imagepacks. +Note: As of April 2020, the imagepacks are back online on statsgen.co.uk. +4. Start MSys and navigate to the repository's folder +5. Type `make` +6. Once finished, the compiled .exe file will reside inside the repository's folder + +# Installation / Usage Instructions +Download the latest release and unzip it's contents. The contents should include the following: +- statsgen2.exe +- help.zip +- libmySQL.dll - This is a library used to connect to MySQL databases +- statsgen2.ini +- readme.txt +- upgrade.ini - If prompted to upgrade - this is the file it is after + +statsgen2.exe can now be run - various files / directories will be created including the default templates. + +Perform the Run / First Time Configuration - DO NOT CANCEL THIS OR INSTALLATION WILL NOT COMPLETE + +After a stats run is complete you can click on the buttons (tick, cross) to see what errors have been generated with each stage. A tick indicates all ok. Anything else is error / warning. You may get some initial X symbols in the General progress bar indicating alias / droplist files not available - this is not a problem and will go away once you have edited any of these items. + +Image Packs (new statsgen 2 awards are there) see www.statsgen.co.uk - These can be uploaded automatically using the upload template pack functionality within statsgen mandatory menu. + +To remove the statsgen banner at the top of each stats page and the link to the statsgen homepage. +Edit the Template Config (homepage stuff) (Mandatory Configuration). You can set it to your home page details or set them blank to remove altogether. + +# License +The Statsgen 2 source code is distributed with permission from the original author © Shaun Jackson a.k.a. Nazarine + +Unless otherwise specified, all code is released under the GNU Affero General Public License v3.0. See the repository's LICENSE file for details. + +## Licenses for third party components +- wxWidgets: [wxWindows Library Licence](https://www.wxwidgets.org/about/licence/) +- sqlite: [Public Domain](https://www.sqlite.org/copyright.html/) + +# Version History +Below is the original version history of Statsgen 2, as written by Shaun Jackson. + +### 1.9.3 23rd November 2009 +- Upgraded the MOHAA identification to properly identify maps and gametypes as well as location kills with some mods + +### 1.9.2 10th September 2009 +- Fixed an issue where MySQL database was not created correctly + +### 1.9.0 22nd April 2009 +- Updated default configurations to include 3 new COD5 maps. +- Updated default templates to give map and gametype individual pages. +- Imagepack uploading can now store the contents locally in your html folder. If imagepacks are stored locally you can now see the pictures in the image editor menu option (under display menu). + +**Weapon Groups** + +Weapon Grouping is now possible - weapon grouping allows you to logically group weapons together so that you can assign them to awards and as one item rather than lots of individual items. You can also assign images and skill settings to weapon groups as a whole. +I have updated the default awards to use the weapon groups (apart from that they are effectively the same as before). +Using weapon groups makes it easier to add a new weapon to an existing configuration so that you don't have to go into individual awards to edit them. +I have included some weapon groups in the default configuration (and the upgrade.ini file). +WARNING!!! - Do not make recursive weapon groups - I have not yet put protection in to stop this (I will do soon). If you create Weapon Group A that has Weapon Group B in it and Weapon Group B has Weapon Group A in it then statsgen will enter into an infinite loop as it tries to parse the weapon group. +The Enemy Territory Logfile decoder can now cope with time codes in the HH:MM:SS format +A few other minor changes that i am sure I have forgotten about. + +### 1.8.8 12th March 2009 +- Added ability to read COD5 1.3 Activities (bomb plants) +- Added ability to read COD5 1.3 Team Wins and Team Losses +- Corrected a slight mistake in the default template in regards to activity display on rounds + +Made it so database field widths can be fixed width - this is governed by contents of +statsgen2.ini file - you will see it if you look because i have not written gui edit +screen for this yet. If you completely delete the database (statsgen2.db) i.e. completely delete the file the next time statsgen re-creates it it will be using fixed +width fields. +Advantages - smaller database - faster processing (30% or 40% faster) +Disadvantages - some data may not fit into the fixed width fields (but i think i have made em all big enough) + +### 1.8.7 5th March 2009 +- Updated to cope with new format of COD5 time stamps +- To come ... adding ability to capture COD5 activities (bomb plants etc) + +### 1.8.6 2nd February 2009 +Upgraded config file with some more cod5 weapons and maps +FTP Downloads can now restart where they left off (default is to do this - can be switched off in the advanced server editor window) +FTP Downloads now take account of Max Log File Usage and only download the required amount +A silly green progress bar on various Processing Steps Lines - I know it looks a bit cack and i will tidy it up but i only coded it 3 hours ago because i wanted to watch a film and see from a distance how far statsgen was progressing + +Too Many COD5 Team Kills - If you run a cracked server then GUID's for cod5 will often be the same as each other - this causes the team name guessing to go astray and assign everybody the same team (and therefore lots of teamkills) - there is an option on the server editor (advanced) screen to be able to switch this behaviour off - you will not be able to identify teams but no more teamkills will be generated. The default behaviour is to have the team guessing switched ON + +Upload Template Facility - Updated to allow for the usage of a configuration file as well - this means i can host Omega's rather stunning COD5 template + +### 1.8.5 22nd November 2008 +- Upgraded config file with some more cod5 weapons and maps + +### 1.8.4 12th November 2008 +- Upgraded config file with some more cod5 weapons and maps +- Added ability to get new templates from statsgen website + +### 1.8.3 2nd November 2008 +- Upgraded default template again to do awards properly so that it does not include dropped players (oops) +- Added a skill and score weighting possibility dependent on the gametype +- Added a new award for ww2 assault guns (not sure how i forgot that one) +- Added a few more cod5 weapons as well as all the cod5 gametypes and maps i have been able to decode from the beta fastfiles (10 maps in total for mp i think) + +### 1.8.2 30th October 2008 +- Added COD5 World At War capability + +### 1.8.1 28th October 2008 +- Fixed a screw up + +### 1.8 28th October 2008 +- Updated template processing routing, error checking is better and it is a little faster +- Updated bug regarding teamkills +- Updated so COD4 has a good stab at working out teamkills +- Updated GUIS to allow for Configuration Wizards or standard guis for several sections +- Updated Initial installation to use First Time Configuration Wizard - should make life easier on installation +- Updated default template to be like the Omega template slightly modified to be more statsgen friendly +- Provided a Image Pack configuration gui - this gives you a suggested choice of imagepacks on the statsgen site and uploads them automatically to your website +- Probably a few more issues that i can't remember + +### 1.7.8 Beta 27th Jan 2008 +- Fixed the last of the alias issues. NOTE: Please delete the aliaslist.dat file as it is likely that aliases have been corrupted +- Fixed issue with server messaging where it would stop after a statsgen run + +### 1.7.7 Beta +- Fixed lots of issues with aliases +- Player Data (avatar, real name, mugshot) - this should now work properly + +### 1.7.6 Beta Release 21st January 2008 +- Player Data (avatar, real name, mugshot) - this should now work properly +- Cheaters list should keep updating rather than keep deleting the old values (oops) +- Award Names can contain ' symbols now. +- Some other stuff i can't remember + +### 1.7.5 Beta Release 6th January 2008 +**Changes / Fixes** +- COD4 PAM MOD support - PAM MOD was most annoying in that is logged things in completely the wrong format, logged some things twice, logs players with only partial guid's - the list goes on - but anyway, I've adapted statsgen to cope with PAM mod now (hopefully) +- Upgrading re-worked - I can now supply database upgrade configuration files - if ever i need to supply a "database contents" patch. + +### 1.7 Full Release 3rd December 2007 +**Changes / Fixes** +- BIG change - backup your old statsgen2.exe and templates folder in case of problems +- Quick Template ability removed (redundant with persistant db) +- Persistant Database: +Statsgen now uses a persistant database. What this means is that it will continue from where it left off +each time it runs - This massively speeds up Logfile Processing, Database Writing, Score Calculation and Template Processing. +If you are upgrading it will remove your old db and switch it to a file based version if necessary +Memory usage is drastically reduced +On a first run through you will not notice any speed ups as it has to run through the template processing +at least once fully - from then on it will be a lot faster - only updating players that have changed. +Alias Editing - once a player has been combined together you cannot unjoin them in the existing db (only +for new rounds will the separation start) +Existing rounds - if you change the minimum players / round to register then existing rounds in the db will +not be changed (this may come later if i work out how to do it efficiently) + +### 1.6 Full Release 11th November 2007 +**Changes / Fixes** +- Addition of COD4 Processing + +**Coming soon(ish)** +- statsgen acting as a web server - allow you to configure it using web pages +- statsgen console only - no need for gui - can configure using web server capability +- statsgen linux - soon as I get the above stuff working + +### 1.5 Full Release 10th September 2007 +**Changes / Fixes** +- Addition of Quake Wars Processing (see later for how to configure for Quake Wars) +- Better handling of Archive / Active files +- Updated default template to cope with Quake Wars +- Handled "xxxx already exists" database errors (i.e. I've ignored em - they don't matter - just scare people) +- Dropped Indexes prior to database writing (should speed things up on larger databases) +- Re-created indexes after database writing +- Added extra xp tables (used with Quake Wars) +- Added ability to have XP as part of an award +- Added ability to have Team Kills as part of Awards +- GUI's hide / disable options that are not appropriate (e.g. remote directories hidden if ftp is disabled) + +**Quake Wars** + +Firstly - Quakewars logfiles are a complete t**t. The kill files contain hardly any info, they don't log activities +such as bomb plants, kill locations (head shots), bridge building etc. Player names are logged without the colour +codes. If a player has their clan tag set then the kill logs don't include the tag. +But .... worst of all ... the logs are split into multiple files - kills are logged in an optional kill file, +but map, game type details and xp points are logged in an objective file. +You need to configure your quakewars server to store the kill file with the following config entries +logfile "1" +logtimestamps "1" +logfilename "kills.log" +The actual kill file (on windows - i have no idea for linux servers) will be stored in your + "My Documents\Id Software\Enemy Territory - QUAKE Wars Beta\base\kills.log" file on your server +This file needs to be selected for your Remote Active Logfile on your server editor screen +The objective file is stored in your + "Quake Wars Server installation folder\base\objective.log" +This file needs to be selected for your Secondary Active Logfile on your server editor screen +You must configure both logfiles within statsgen for Quake Wars kills to be processed properly in Statsgen + +### 1.4.4 Unreleased Full Release 7th July 2007 +**Changes / Fixes** +- Fix in default template + +### 1.4.3 Unreleased Full Release 7th July 2007 +**Changes / Fixes** +- Fix in default template: Recognises no team loglines for cod 2 + +### 1.4.2 Unreleased Full Release 29th June 2007 +**Changes / Fixes** +- Speed ups - Lots of optimizations - upto 70% faster logfile processing +- Auto Aliasing - now ignores WOLFENSTEIN and MOHAA automatically cheaters database table - all players found in the logfile who are marked as cheaters are added to the cheaters table (new table) +- Default Template - updated to show list of found cheaters + +### 1.4.1 Unreleased +**Changes / Fixes** +- Crash when round was empty in an unusual way + +### 1.4.0 Full Release 9th June 2007 +**Changes / Fixes** +- Sometimes ban files would not download properly. I don't know why they were failing but i have put some code in to work around it. +- Some more tidying up of the "Time To Go" text +- Added ability to Automatically Alias players during logfile processing. Basically it uses the GUID to work out which players are really the same person, adding them to the alias list - any existing aliases are kept as is. +- You can now add the command line argument `-runonce` e.g. `statsgen2.exe -runonce`. This will cause statsgen to start, perform a stats run, then exit. This is designed to be used by people who want to run statsgen on the Windows Scheduler system. + +### 1.3.3 Full Release 9th April 2007 +**Changes / Fixes** +- Message Center - Punkbuster Messaging now works, I made a several mistakes in this area :-p. +- Editor Screens - Image/Score/Skill editor screens now show the original code key as part of their display +- Thread Safe - The program is now (I hope) thread safe +- Screen Updates - The screen udpates properly now during processing +- Screen Updates - Fixed some issues where negative "Time To Go" info could be displayed +- Screen Updates - Fixed some issues when multiple logfiles caused "Time To Go" to be miscalculated +- Speed Ups - Massively sped up processing if large drop lists were used (e.g. if you used punkbuster bans) +- Speed Ups - Added a few more indexes to speed up the BF2 template +- Logfile Processing - Extreme MOD activities (ctfb_capture) now decoded + +### 1.3.2 Full Release 15th March 2007 +**Changes / Fixes** +oops - I made a mistake and managed to disable website transfer in the last release, and, to cap it off, I managed to include a bad default database config. + +### 1.3.1 Full Release 10th March 2007 +**Changes / Fixes** +- File menu renamed to Run. + +You now have the ability to change the Run Priority of the quick and full templates. This should help +anybody who is running the program on a dedi box and is experiencing lag on the server as statsgen +steals the cpu. The lower priority setting the less statsgen will steal cpu. + +### 1.3 Full Release 3rd March 2007 +**Changes / Fixes** +- Fixed some issues with the MySQL uploading +- Added speech time to the speech log +- Added some more database indexes to speed up some of the templates + +### 1.2 Full Release 13th February 2007 +**Changes / Fixes** +- Changed the default config to be the No Rounds version - This is a much leaner template which takes less processing time +- Awards can now be "weighted" in conjunction with the template +- Skill can now optionally have the negative component caused by deaths switched off +- Default template now has score, skill and award details information page +- MySQL support. Statsgen can now optionally upload it's internal database to a remote (webserver) MySQL database: I will be developing dynamic versions of the current templates which make use of this feature. When in place this MASSIVELY speeds up processing as transfer loads and template processing will be significantly reduced. +- Some extra awards added to use some Admiral Mod features and the associated images also added to the image pack. Thanks again to Omega for doing these - awesome job mate. + +### 1.1.2 Full Release 4th February 2007 +**Changes / Fixes** +- Fixed an issue where award components could not be deleted in the config file + +### 1.1.1 Full Release 3rd February 2007 +**Changes / Fixes** +- Made a slight mistake in the automatic installation detection. Upgraders from 1.1.0 only need replace the executable. + +### 1.1.0 Full Release 28th January 2007 +**Changes / Fixes** +- Extended character sets (Cyrillics etc) now read properly from the logfile +- Skill Calculation - Can now be configured to not allow negative skill (no loss from death) +- Added Free For All as MOHAA Deathmatch Mode to INI File +- Upgrade File & Procedure now supplied +- Database Structure Updated: Rounds / View Rounds (updated with server index round created in), Award Definition (Award ID added). This affects the Message Centre Key used- during stats production (no longer changes when name changes) +- Default Templates - Various Updates / Fixes +- File Downloading Multiple Files - Better handling of weird servers that don't give me a wild card directory listing +- Admiral Mod - Healing activity now detected +- COD1/COD2 Banfile - These are now read and used +- Speech File Output - You can now configure statsgen to write out all the speech in the logs in the Mandatory/Output Config +- Error Boxes - The Save Button is now hooked up so you can save descriptions of errors - this is useful to me if you get problems - you can send me the error details instead- of posting images on the forum + +### 1.0.2 Full Release 18th January 2007 +**Fixes** +- Some FTP Servers dont seem to like getting a directory listing with a wildcard and this prevented download of log files. I have made it so that if it encounters this problem it tries to blunder past it anyway - you will see a caution symbol on the download logs entry to warn you this is happening. + +### 1.0.1 Full Release 6th January 2007 +**Fixes** +- I chumped up the initial release. The "Quick Template" extracted upon install was and invalid testing one. + +### 1.0 Full Release 1st January 2007 +**Fixes** +- Server Updates did not get reflected until statsgen restarted +- Website Updates did not get reflected until statsgen restarted +- Message Center Updates did not get reflected until statsgen restarted +- Better "file not found" handling +- HTML Safe if template codes passed through ColouredText2HTML() function + +**Additions** +- Schedule Editor +- Better transfer failure error logging +- Negative durations on round corruption fixed +- Banned Speech Editor +- MOHAA Support +- Enemy Territory Support +- Omega's Updated Templates +- Help Files + +### 0.2 Alpha 17th November 2006 +**Fixes** +- Remote File Browser fixed (doh!) +- Negative durations on round corruption fixed +- Team Swap Suicides (team balance) now separate from normal suicides +- Various bugfixes to default templates +- Message Centre GUI tidied up + +**Additions** +- Punkbuster Messaging Added +- Default Templates: More configurable options for Colours, Homepage, Homepage banner, Avatars, Player Profiles (mugshots, clan position, xfire address etc) +Ratio's of Kill / Deaths. +- Player Data: Player Data are personalised player options including Avatars, Player Real Name, Clan Position (War Arranger etc), Personal Picture (mugshot), Xfire address, Personal Homepage + +**Things still to do** +- Help Pages +- Schedule Config +- MOHAA support + +### 0.1 Alpha 1st November 2006 +- Default Templates not 100% perfect. +- No help files yet. +- No Avatars yet. +- No Speech Filter yet. +- Speedups possible. +- More award images necessary. +- Only COD1 and COD2 supported. \ No newline at end of file diff --git a/RemoteDirectoryConfigItemGUI.cpp b/RemoteDirectoryConfigItemGUI.cpp new file mode 100644 index 0000000..5510200 --- /dev/null +++ b/RemoteDirectoryConfigItemGUI.cpp @@ -0,0 +1,261 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "RemoteDirectoryConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "FTPBrowserPanel.h" +#include "GenericOKCancelDialog.h" + +BEGIN_EVENT_TABLE(RemoteDirectoryConfigItemGUI, wxPanel) + EVT_SIZE(RemoteDirectoryConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,RemoteDirectoryConfigItemGUI::OnTextChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,RemoteDirectoryConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +RemoteDirectoryConfigItemGUI::RemoteDirectoryConfigItemGUI() +{ + maxCharacters=-1; +} + +void RemoteDirectoryConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +RemoteDirectoryConfigItemGUI::~RemoteDirectoryConfigItemGUI() +{ +} + +void RemoteDirectoryConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void RemoteDirectoryConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + int maxCharactersIn, + wxString &FTPIDIn) +{ + wxSizeEvent event; + wxSize buttonSize(16,16); + + configKey=configKeyIn; + labelText=labelTextIn; + defaultValue=defaultValueIn; + maxCharacters=maxCharactersIn; + FTPID=FTPIDIn; + + + //SetConfigKey(configKey); + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + + SetConfigKey(configKey); + button.Create(this, + WINDOW_ID_CONFIG_BUTTON, + wxArtProvider::GetIcon(wxART_FOLDER, + wxART_OTHER, + buttonSize)); + + OnResize(event); +} + +wxString RemoteDirectoryConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int RemoteDirectoryConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void RemoteDirectoryConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void RemoteDirectoryConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + int buttonWidth; + int buttonHeight; + int widthForTextEdit; + int fixedWidth; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=button.GetSize(); + buttonWidth=itemSize.GetWidth(); + buttonHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-buttonWidth; + fixedWidth=(maxCharacters * FONT_CHAR_WIDTH)+FONT_TEXT_CTRL_GAP; + if (maxCharacters>0) + { + // We have an overriding field width + if (fixedWidthCreate(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + browserPanel->CreateScreen(); + + dialog.SetPanel(browserPanel); + dialog.CreateDialog(); + result=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + if (result) + { + newFilename=browserPanel->GetCurrentSelection(); + selectedSize=browserPanel->selectedSize; + if (selectedSize>=0) + { + // Selected a file - get directory part + textEdit.SetValue(browserPanel->CurrentPath()); + } + else + { + // Selected directory - just use selection + textEdit.SetValue(newFilename); + } + } + else + { + } + + + /* + newDirectory=wxDirSelector(message,value); + if (newDirectory.Length()>0) + { + textEdit.SetValue(newDirectory); + } + */ + +} + +void RemoteDirectoryConfigItemGUI::SetValue(wxString &value) +{ + textEdit.SetValue(value); +} + diff --git a/RemoteDirectoryConfigItemGUI.h b/RemoteDirectoryConfigItemGUI.h new file mode 100644 index 0000000..d1c3fbf --- /dev/null +++ b/RemoteDirectoryConfigItemGUI.h @@ -0,0 +1,47 @@ +#ifndef __REMOTEDIRECTORYCONFIGITEMGUI +#define __REMOTEDIRECTORYCONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class RemoteDirectoryConfigItemGUI : public BaseConfigItemGUI +{ + public: + RemoteDirectoryConfigItemGUI(); + virtual ~RemoteDirectoryConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + int maxCharactersIn, + wxString &FTPIDIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + void SetValue(wxString &value); + protected: + + private: + wxTextCtrl textEdit; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + wxString FTPID; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/RemoteFileConfigItemGUI.cpp b/RemoteFileConfigItemGUI.cpp new file mode 100644 index 0000000..4323e67 --- /dev/null +++ b/RemoteFileConfigItemGUI.cpp @@ -0,0 +1,258 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "RemoteFileConfigItemGUI.h" +#include "RemoteDirectoryConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "GenericOKCancelDialog.h" +#include "FTPBrowserPanel.h" + +BEGIN_EVENT_TABLE(RemoteFileConfigItemGUI, wxPanel) + EVT_SIZE(RemoteFileConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,RemoteFileConfigItemGUI::OnTextChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,RemoteFileConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +RemoteFileConfigItemGUI::RemoteFileConfigItemGUI() +{ + maxCharacters=-1; + directoryConfig=NULL; +} + +void RemoteFileConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +RemoteFileConfigItemGUI::~RemoteFileConfigItemGUI() +{ +} + +void RemoteFileConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void RemoteFileConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + int maxCharactersIn, + wxString &FTPIDIn, + RemoteDirectoryConfigItemGUI *directoryConfigIn) +{ + wxSizeEvent event; + wxSize buttonSize(16,16); + + configKey=configKeyIn; + labelText=labelTextIn; + defaultValue=defaultValueIn; + maxCharacters=maxCharactersIn; + FTPID=FTPIDIn; + directoryConfig=directoryConfigIn; + + //SetConfigKey(configKey); + + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + SetConfigKey(configKey); + button.Create(this, + WINDOW_ID_CONFIG_BUTTON, + wxArtProvider::GetIcon(wxART_FILE_OPEN, + wxART_OTHER, + buttonSize)); + + OnResize(event); +} + +wxString RemoteFileConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int RemoteFileConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void RemoteFileConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void RemoteFileConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + int buttonWidth; + int buttonHeight; + int widthForTextEdit; + int fixedWidth; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=button.GetSize(); + buttonWidth=itemSize.GetWidth(); + buttonHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-buttonWidth; + fixedWidth=(maxCharacters * FONT_CHAR_WIDTH)+FONT_TEXT_CTRL_GAP; + if (maxCharacters>0) + { + // We have an overriding field width + if (fixedWidthGetValue(); + } + else + { + path=""; + } + message="Select File"; + + GenericOKCancelDialog dialog(this,-1, + message, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + FTPBrowserPanel *browserPanel=new FTPBrowserPanel( + FTPID, + path, + true); + browserPanel->Create(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("panel")); + browserPanel->CreateScreen(); + + dialog.SetPanel(browserPanel); + dialog.CreateDialog(); + result=(dialog.ShowModal()==WINDOW_ID_BUTTON_SAVE); + if (result) + { + newFilename=browserPanel->GetCurrentSelection(); + selectedSize=browserPanel->selectedSize; + // FTP and UNIX are the same format + wxFileName filename(newFilename,wxPATH_UNIX); + // above path setting doesn't bloody work + // replace by hand + textEdit.SetValue(filename.GetFullName()); + if (directoryConfig!=NULL) + { + path=filename.GetPath(); + path.Replace("\\","/"); + directoryConfig->SetValue(path); + } + } + else + { + } + +} + diff --git a/RemoteFileConfigItemGUI.h b/RemoteFileConfigItemGUI.h new file mode 100644 index 0000000..480e39f --- /dev/null +++ b/RemoteFileConfigItemGUI.h @@ -0,0 +1,49 @@ +#ifndef __REMOTEFILECONFIGITEMGUI +#define __REMOTEFILECONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" +#include "RemoteDirectoryConfigItemGUI.h" + +class RemoteFileConfigItemGUI : public BaseConfigItemGUI +{ + public: + RemoteFileConfigItemGUI(); + virtual ~RemoteFileConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + int maxCharactersIn, + wxString &FTPIDIn, + RemoteDirectoryConfigItemGUI *directoryGUIIn=NULL); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxTextCtrl textEdit; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + RemoteDirectoryConfigItemGUI *directoryConfig; + wxString FTPID; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/RemoteMachine.cpp b/RemoteMachine.cpp new file mode 100644 index 0000000..ccb0337 --- /dev/null +++ b/RemoteMachine.cpp @@ -0,0 +1,772 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "RemoteMachine.h" +#include "ErrorData.h" +#include "GlobalStatistics.h" +#include "Progress.h" +#include "RestartingFTP.h" +#include "ErrorData.h" + +RemoteMachine::RemoteMachine(wxString &IDIn) +{ + wxString configBaseKey; + wxString configKey; + wxString configValue; + + staticFTPConnection=NULL; + maxErrorSeverity=SeverityError; + + ID=IDIn; + configBaseKey="/"+ID+"/"; + + // Read in the configuration items for this machine + configKey=configBaseKey+"IPAddress"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + IPAddress=configValue; + + configKey=configBaseKey+"FTPUsername"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPUsername=configValue; + + configKey=configBaseKey+"FTPPassword"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPPassword=configValue; + + configKey=configBaseKey+"FTPPort"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"21"); + FTPPort=-1; + if (configValue.Length()>0) + { + FTPPort=atoi(configValue.GetData()); + } + + configKey=configBaseKey+"FTPPassive"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"y"); + FTPPassive=(configValue.CmpNoCase("y")==0); + + configKey=configBaseKey+"FTPRetries"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"3"); + FTPRetries=atoi(configValue.GetData()); +} + +RemoteMachine::~RemoteMachine() +{ + if (staticFTPConnection!=NULL) + { + delete staticFTPConnection; + staticFTPConnection=NULL; + } +} + +bool RemoteMachine::GetRemoteFile( + wxString &remoteDirectory, + wxString &remoteFilename, + wxString &localDirectory) +{ + return (GetRemoteFileRestart(remoteDirectory, + remoteFilename, + localDirectory, + false, + 0)); +} + +bool RemoteMachine::GetRemoteFileRestart( + wxString &remoteDirectory, + wxString &remoteFilename, + wxString &localDirectory, + bool restartDownload, + long maxLogfileSize) +{ + bool retVal=true; + wxString msg; + wxString ftpResponse; + + wxString fullLocalFilename; + wxString fullRemoteFilename; + int remoteFileSize; + unsigned char buffer[1024]; + int bytesRead; + int chunkRead; + wxInputStream *remoteFileStream=NULL; + wxOutputStream *localFileStream=NULL; + bool finished=false; + RestartingFTP ftpConnection; + int localFileSize=-1; + + STATSGEN_DEBUG_FUNCTION_START("RemoteFile","GetRemoteFile") + msg.Printf("Downloading %s\n",remoteFilename.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->SetStatus(msg); + fullRemoteFilename=remoteDirectory+"/"+remoteFilename; + fullLocalFilename=localDirectory+"/"+remoteFilename; + + if (wxFileExists(fullLocalFilename)) + { + wxFile localFile(fullLocalFilename); + localFileSize=localFile.Length(); + } + else + { + localFileSize=-1; + } + retVal=Connect(ftpConnection); + if (retVal) + { + // Successfully connected to the FTP RemoteMachine + retVal=ftpConnection.SetBinary(); + if (retVal) + { + // Successfully set to Binary mode + remoteFileSize=ftpConnection.GetFileSize(fullRemoteFilename); + + if ((remoteFileSize==localFileSize)&&(localFileSize!=-1)) + { + // We don't need to download as a file with the same size + // is already local + msg.Printf("Remote file [%s] with size [%d] already downloaded - skipping transfer", + remoteFilename.GetData(),remoteFileSize); + progress->LogError(msg,SeverityOK); + progress->Update(remoteFileSize); + } + else + { + if ((localFileSize==-1)||(remoteFileSize==-1)) + { + // Can't determine a file size so cannot restart + restartDownload=false; + } + else + { + if (localFileSize>remoteFileSize) + { + // Remote file is smaller than local file + // so cannot restart + restartDownload=false; + } + } + if (restartDownload) + { + remoteFileStream=ftpConnection.GetInputStreamRestart(fullRemoteFilename,localFileSize); + } + if (remoteFileStream==NULL) + { + restartDownload=false; + remoteFileStream=ftpConnection.GetInputStream(fullRemoteFilename); + } + if (remoteFileStream==NULL) + { + msg.Printf("Could not find [%s] in remote directory [%s]", + remoteFilename.GetData(),remoteDirectory.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + retVal=false; + } + if (retVal) + { + if (restartDownload) + { + + localFileStream=(wxOutputStream *)new wxFFileOutputStream(fullLocalFilename,"a+b"); + if (localFileStream!=NULL) + { + localFileStream->SeekO(localFileSize); + } + else + { + restartDownload=false; + } + } + if (localFileStream==NULL) + { + localFileStream=(wxOutputStream *)new wxFileOutputStream(fullLocalFilename); + } + + if (localFileStream==NULL) + { + msg.Printf("Could not write [%s] in local directory [%s]", + remoteFilename.GetData(),localDirectory.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + retVal=false; + } + } + + finished=false; + bytesRead=0; + if (restartDownload) + { + progress->SetOffset(localFileSize+progress->CurrentValue()); + } + while ((retVal) && (!finished) && (!remoteFileStream->Eof())) + { + remoteFileStream->Read(buffer,sizeof(buffer)); + chunkRead=remoteFileStream->LastRead(); + bytesRead+=chunkRead; + if (chunkRead>0) + { + localFileStream->Write(buffer,chunkRead); + } + else + { + finished=true; + } + progress->Update(bytesRead); + if ((maxLogfileSize!=0)&&(bytesRead>=(maxLogfileSize*1024*1024))) + { + // finished downloading the required amount of logfile data + finished=true; + } + STATSGEN_DEBUG_CODE(msg.Printf("Downloaded [%d] of [%d] bytes",bytesRead,remoteFileSize);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + } + if (remoteFileStream!=NULL) + { + delete remoteFileStream; + remoteFileStream=NULL; + } + if (localFileStream!=NULL) + { + delete localFileStream; + localFileStream=NULL; + } + } + else + { + ftpResponse=ftpConnection.GetLastResult(); + // Failed to set to Ascii mode + msg.Printf("Failed to set to ascii mode, FTP Response [%s]", + ftpResponse.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + } + else + { + ftpResponse=ftpConnection.GetLastResult(); + // Failed to connect + msg.Printf("Failed to connect to [%s] with username [%s] FTP Response [%s]", + IPAddress.GetData(), + FTPUsername.GetData(), + ftpResponse.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool RemoteMachine::GetRemoteDirectoryListing(wxString &remoteDirectory, + wxString &remoteWildcard, + wxArrayString &remoteFiles) +{ + bool retVal=true; + wxString msg; + wxString ftpResponse; + int remoteFileCount; + RestartingFTP ftpConnection; + wxArrayString workingRemoteFiles; + int remoteFileIndex; + wxString remoteFilename; + + wxString localFilename; + + STATSGEN_DEBUG_FUNCTION_START("RemoteFile","GetRemoteDirectoryListing") + remoteFiles.Clear(); + STATSGEN_DEBUG(DEBUG_ALWAYS,"Connecting") + retVal=Connect(ftpConnection); + STATSGEN_DEBUG(DEBUG_ALWAYS,"Connected") + if (retVal) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Successfully Connected") + // Successfully connected to the FTP RemoteMachine + // Successfully set to ASCII mode + // Change to the appropriate directory + if (remoteDirectory.Length()==0) + { + // Don't need to change if blank + retVal=true; + } + else + { + retVal=ftpConnection.ChDir(remoteDirectory); + } + if (retVal) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Successfully Changed To Remote Directory"); + // Changed to the remote directory + // Get a directory listing using the wild + // card setting + retVal=ftpConnection.GetFilesList(workingRemoteFiles,""); + if (retVal) + { + remoteFileCount=workingRemoteFiles.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("Got %d files from directory listing",remoteFileCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + for (remoteFileIndex=0; + remoteFileIndexLogError(msg,SeverityCaution); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + retVal=true; + } + } + else + { + ftpResponse=ftpConnection.GetLastResult(); + // Failed to change to the remote directory + msg.Printf("Failed to change to remote directory [%s] FTP Response [%s]", + remoteDirectory.GetData(), + ftpResponse.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + } + } + else + { + ftpResponse=ftpConnection.GetLastResult(); + // Failed to connect + msg.Printf("Failed to connect to [%s] with username [%s] FTP Response [%s]", + IPAddress.GetData(), + FTPUsername.GetData(), + ftpResponse.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool RemoteMachine::DownloadFileList( + wxString &remoteDirectory, + wxString &remoteWildcard, + wxString &localDirectory) +{ + bool retVal=true; + wxString msg; + + wxString localFilename; + wxString remoteFilename; + wxArrayString remoteFiles; + int remoteFileCount; + int remoteFileIndex; + RestartingFTP ftpConnection; + + Connect(ftpConnection); + retVal=GetRemoteDirectoryListing(remoteDirectory,remoteWildcard,remoteFiles); + if (retVal) + { + remoteFileCount=remoteFiles.GetCount(); + for (remoteFileIndex=0;remoteFileIndexLogError(msg,maxErrorSeverity); + retVal=false; + } + if (retVal) + { + retVal=PutFile(remoteDirectory, + localFilename, + (wxInputStream *)localFileStream, + remoteFilename, + maxSeverity); + } + if (localFileStream!=NULL) + { + delete localFileStream; + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool RemoteMachine::PutFile(wxString &remoteDirectory, + wxString &localFilename, + wxInputStream *localFileStream, + wxString &remoteFilename, + int maxSeverity) +{ + bool allOK=true; + wxOutputStream *remoteFileStream=NULL; + wxString errorMessage; + int fileSize; + int bytesTransferred; + unsigned char buffer[1024]; + wxFile localFile; + wxString message; + wxString ftpResponse; + wxString msg; +// wxFTP ftpConnection; + + STATSGEN_DEBUG_FUNCTION_START("RemoteMachine","PutFile") + maxErrorSeverity=maxSeverity; + if (staticFTPConnection!=NULL) + { + // Already connected + allOK=true; + } + else + { + staticFTPConnection=new RestartingFTP; + //allOK=Connect(ftpConnection); + allOK=Connect(*staticFTPConnection); + } + + if (allOK) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Connected OK") + if (remoteDirectory.Length()==0) + { + allOK=true; + } + else + { + //allOK=ftpConnection.ChDir(remoteDirectory); + allOK=staticFTPConnection->ChDir(remoteDirectory); + } + } + + if (!allOK) + { + msg.Printf("Failed to change to remote directory %s", + remoteDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,maxErrorSeverity); + } + if (allOK) + { + //remoteFileStream=ftpConnection.GetOutputStream(remoteFilename); + remoteFileStream=staticFTPConnection->GetOutputStream(remoteFilename); + if (remoteFileStream==NULL) + { + errorMessage.Printf("Could not create %s in remote directory %s", + remoteFilename.GetData(), + remoteDirectory.GetData()); + progress->LogError(errorMessage,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage) + allOK=false; + } + } + + bytesTransferred=0; + + while (allOK && !localFileStream->Eof()) + { + localFileStream->Read(buffer,sizeof(buffer)); + if (localFileStream->LastRead()>0) + { + remoteFileStream->Write(buffer,localFileStream->LastRead()); + } + bytesTransferred+=localFileStream->LastRead(); + progress->Update(bytesTransferred); + STATSGEN_DEBUG_CODE(message.Printf("Transferring %s - %dk", remoteFilename.GetData(), bytesTransferred/1024);) + STATSGEN_DEBUG(DEBUG_RARELY,message) + } + //if (ftpConnection.GetError()!=wxPROTO_NOERR) + if (staticFTPConnection!=NULL) + { + //if (ftpConnection.GetError()!=wxPROTO_NOERR) + if (staticFTPConnection->GetError()!=wxPROTO_NOERR) + { + msg.Printf("error during transfer of %s",localFilename.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + allOK=false; + } + } + + if (remoteFileStream!=NULL) + { + if (remoteFileStream->GetLastError()!=wxSTREAM_NO_ERROR) + { + msg.Printf("error during transfer of %s",localFilename.GetData()); + progress->LogError(msg,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + allOK=false; + } + delete remoteFileStream; + } + + STATSGEN_DEBUG_FUNCTION_END + return allOK; +} + +long RemoteMachine::GetRemoteFileSize( + wxString &remoteDirectory, + wxString &remoteFilename) +{ + wxString msg; + bool retVal; + wxString ftpResponse; + + wxString fullRemoteFilename; + int remoteFileSize=0; + RestartingFTP ftpConnection; + + STATSGEN_DEBUG_FUNCTION_START("RemoteMachine","GetRemoteFileSize") + + fullRemoteFilename=remoteDirectory+"/"+remoteFilename; + + + retVal=Connect(ftpConnection); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Connected OK") + remoteFileSize=ftpConnection.GetFileSize(fullRemoteFilename); + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Got File Size") + } + + STATSGEN_DEBUG_FUNCTION_END + return (remoteFileSize); +} + +wxString RemoteMachine::GetLastErrorMessage() +{ + return(lastErrorMessage); +} + +bool RemoteMachine::Connect(RestartingFTP &ftpConnection) +{ + bool retVal=true; + wxString msg; + wxIPV4address address; + wxString ftpResponse; + int attempts; + + + STATSGEN_DEBUG_FUNCTION_START("RemoteMachine","Connect") + + address.Hostname(IPAddress); + address.Service(FTPPort); + + ftpConnection.SetUser(FTPUsername); + ftpConnection.SetPassword(FTPPassword); + ftpConnection.SetPassive(FTPPassive); + + attempts=1; + retVal=false; + while ((!retVal)&&(attempts<=MAX_CONNECTION_ATTEMPTS)) + { + retVal=ftpConnection.Connect(address); + ftpResponse=ftpConnection.GetLastResult(); + if (!retVal) + { + lastErrorMessage.Printf("Connect Attempt %d of %d failed - last response [%s]", + attempts,MAX_CONNECTION_ATTEMPTS, + ftpResponse.GetData()); + progress->LogError(lastErrorMessage,maxErrorSeverity); + } + attempts++; + } + if (!retVal) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Connected not ok") + // Failed to connect + lastErrorMessage.Printf("Failed to connect to [%s] with username [%s] FTP Response [%s]", + IPAddress.GetData(), + FTPUsername.GetData(), + ftpResponse.GetData()); + progress->LogError(lastErrorMessage,maxErrorSeverity); + STATSGEN_DEBUG(DEBUG_ALWAYS,lastErrorMessage); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +/* +void RemoteMachine::Disconnect() +{ + ftpConnection.Destroy(); +} +*/ + +bool RemoteMachine::ChangeDirectory(wxString &fullPath) +{ + bool retVal; + wxString newPath; + RestartingFTP ftpConnection; + + STATSGEN_DEBUG_FUNCTION_START("RemoteMachine","ChangeDirectory") + Connect(ftpConnection); + STATSGEN_DEBUG(DEBUG_RARELY,"Connected") + if (fullPath.Length()==0) + { + // don't need to change if blank + retVal=true; + } + else + { + retVal=ftpConnection.ChDir(fullPath); + } + STATSGEN_DEBUG(DEBUG_RARELY,"Directory Changed") + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Current Directory Changed") + newPath=ftpConnection.Pwd(); + STATSGEN_DEBUG(DEBUG_RARELY,"Current Directory Changed") + fullPath=newPath; + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool RemoteMachine::PutFile(wxString &remoteDirectory, + wxString &localFilename) +{ + bool allOK; + int attemptsLeft; + + maxErrorSeverity=SeverityCaution; + + attemptsLeft=FTPRetries+1; + allOK=false; + while ((!allOK) && (attemptsLeft>0)) + { + if (attemptsLeft>1) + { + maxErrorSeverity=SeverityCaution; + } + else + { + maxErrorSeverity=SeverityError; + } + allOK=PutFile(remoteDirectory,localFilename,maxErrorSeverity); + if (!allOK) + { + delete staticFTPConnection; + staticFTPConnection=NULL; + } + attemptsLeft--; + } + maxErrorSeverity=SeverityError; + + return allOK; +} + +void RemoteMachine::MaxErrorSeverity(int severity) +{ + maxErrorSeverity=severity; +} + +bool RemoteMachine::MakeDir(wxString &remoteDirectory, + wxString &newDirectory) +{ + bool allOK=true; + wxString errorMessage; + wxString message; + wxString ftpResponse; + wxString msg; +// wxFTP ftpConnection; + + STATSGEN_DEBUG_FUNCTION_START("RemoteMachine","MakeDir") + if (staticFTPConnection!=NULL) + { + // Already connected + allOK=true; + } + else + { + staticFTPConnection=new RestartingFTP; + //allOK=Connect(ftpConnection); + allOK=Connect(*staticFTPConnection); + } + + if (allOK) + { + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Connected OK") + if (remoteDirectory.Length()==0) + { + allOK=true; + } + else + { + //allOK=ftpConnection.ChDir(remoteDirectory); + allOK=staticFTPConnection->ChDir(remoteDirectory); + } + } + if (!allOK) + { + msg.Printf("Failed to change to remote directory %s", + remoteDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,maxErrorSeverity); + } + else + { + allOK=staticFTPConnection->MkDir(newDirectory); + } + + STATSGEN_DEBUG_FUNCTION_END + return allOK; +} + diff --git a/RemoteMachine.h b/RemoteMachine.h new file mode 100644 index 0000000..c64b297 --- /dev/null +++ b/RemoteMachine.h @@ -0,0 +1,76 @@ +#ifndef __REMOTEMACHINE +#define __REMOTEMACHINE + +// wxWindows includes +#include +#include +#include +#include "RestartingFTP.h" + +// Statsgen Includes + +#define MAX_CONNECTION_ATTEMPTS 1 +class RemoteMachine +{ + public: + RemoteMachine(wxString &IDIn); + virtual ~RemoteMachine(); + + bool MakeDir(wxString &baseDirectory,wxString &newDirectory); + bool PutFile(wxString &remoteDirectory, + wxString &localFilename); + bool PutFile(wxString &remoteDirectory, + wxString &localFilename, + int maxSeverity); + bool PutFile(wxString &remoteDirectory, + wxString &localFilename, + wxInputStream *localFileStream, + wxString &remoteFilename, + int maxSeverity); + bool GetRemoteFile( + wxString &remoteDirectory, + wxString &remoteFilename, + wxString &localDirectory); + bool GetRemoteFileRestart( + wxString &remoteDirectory, + wxString &remoteFilename, + wxString &localDirectory, + bool restartDownload, + long maxLogfileSize); + long GetRemoteFileSize( + wxString &remoteDirectory, + wxString &remoteFilename); + + bool GetRemoteDirectoryListing(wxString &remoteDirectory, + wxString &remoteWildcard, + wxArrayString &remoteFiles); + bool DownloadFileList(wxString &remoteDirectory, + wxString &remoteWildcard, + wxString &localDirectory); + bool ChangeDirectory(wxString &fullPath); + bool Connect(RestartingFTP &ftpConnection); + void Disconnect(); + void MaxErrorSeverity(int severity); + wxString GetLastErrorMessage(); + + public: + wxString ID; + wxString IPAddress; + wxString FTPUsername; + wxString FTPPassword; + int FTPPort; + bool FTPPassive; + int FTPRetries; + + private: +// RestartingFTP ftpConnection; + RestartingFTP *staticFTPConnection; + + int maxErrorSeverity; + + wxString lastErrorMessage; + +}; + + +#endif diff --git a/RestartingFTP.cpp b/RestartingFTP.cpp new file mode 100644 index 0000000..b562237 --- /dev/null +++ b/RestartingFTP.cpp @@ -0,0 +1,1054 @@ +#include "RestartingFTP.h" + +///////////////////////////////////////////////////////////////////////////// +// Name: common/ftp.cpp +// Purpose: FTP protocol +// Author: Guilhem Lavaux +// Modified by: Mark Johnson, wxWindows@mj10777.de +// 20000917 : RmDir, GetLastResult, GetList +// Vadim Zeitlin (numerous fixes and rewrites to all part of the +// code, support ASCII/Binary modes, better error reporting, more +// robust Abort(), support for arbitrary FTP commands, ...) +// Randall Fox (support for active mode) +// Created: 07/07/1997 +// RCS-ID: $Id: ftp.cpp 47969 2007-08-08 23:34:14Z VZ $ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// (c) 1998-2004 wxWidgets team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_PROTOCOL_FTP + +#ifndef WX_PRECOMP + #include + #include "wx/string.h" + #include "wx/utils.h" + #include "wx/log.h" + #include "wx/intl.h" +#endif // WX_PRECOMP + +#include "wx/sckaddr.h" +#include "wx/socket.h" +#include "wx/url.h" +#include "wx/sckstrm.h" +#include "wx/protocol/protocol.h" +#include "wx/protocol/ftp.h" + +#if defined(__WXMAC__) + #include "wx/mac/macsock.h" +#endif + +#ifndef __MWERKS__ + #include +#endif + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the length of FTP status code (3 digits) +static const size_t LEN_CODE = 3; + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(RestartingFTP, wxProtocol) +IMPLEMENT_PROTOCOL(RestartingFTP, wxT("ftp"), wxT("ftp"), true) + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxFTP constructor and destructor +// ---------------------------------------------------------------------------- + +RestartingFTP::RestartingFTP() +{ + m_lastError = wxPROTO_NOERR; + m_streaming = false; + m_currentTransfermode = NONE; + + m_user = wxT("anonymous"); + m_passwd << wxGetUserId() << wxT('@') << wxGetFullHostName(); + + SetNotify(0); + SetFlags(wxSOCKET_NOWAIT); + m_bPassive = true; + SetDefaultTimeout(60); // Default is Sixty Seconds + m_bEncounteredError = false; +} + +RestartingFTP::~RestartingFTP() +{ + if ( m_streaming ) + { + // if we are streaming, this will issue + // an FTP ABORT command, to tell the server we are aborting + (void)Abort(); + } + + // now this issues a "QUIT" command to tell the server we are + Close(); +} + +// ---------------------------------------------------------------------------- +// wxFTP connect and login methods +// ---------------------------------------------------------------------------- + +bool RestartingFTP::Connect(wxSockAddress& addr, bool WXUNUSED(wait)) +{ + if ( !wxProtocol::Connect(addr) ) + { + m_lastError = wxPROTO_NETERR; + return false; + } + + if ( !m_user ) + { + m_lastError = wxPROTO_CONNERR; + return false; + } + + // we should have 220 welcome message + if ( !CheckResult('2') ) + { + Close(); + return false; + } + + wxString command; + command.Printf(wxT("USER %s"), m_user.c_str()); + char rc = SendCommand(command); + if ( rc == '2' ) + { + // 230 return: user accepted without password + return true; + } + + if ( rc != '3' ) + { + Close(); + return false; + } + + command.Printf(wxT("PASS %s"), m_passwd.c_str()); + if ( !CheckCommand(command, '2') ) + { + Close(); + return false; + } + + return true; +} + +bool RestartingFTP::Connect(const wxString& host) +{ + wxIPV4address addr; + addr.Hostname(host); + addr.Service(wxT("ftp")); + + return Connect(addr); +} + +bool RestartingFTP::Close() +{ + if ( m_streaming ) + { + m_lastError = wxPROTO_STREAMING; + return false; + } + + if ( IsConnected() ) + { + if ( !CheckCommand(wxT("QUIT"), '2') ) + { + wxLogDebug(_T("Failed to close connection gracefully.")); + } + } + + return wxSocketClient::Close(); +} + +// ============================================================================ +// low level methods +// ============================================================================ + +// ---------------------------------------------------------------------------- +// Send command to FTP server +// ---------------------------------------------------------------------------- + +char RestartingFTP::SendCommand(const wxString& command) +{ + if ( m_streaming ) + { + m_lastError = wxPROTO_STREAMING; + return 0; + } + + wxString tmp_str = command + wxT("\r\n"); + const wxWX2MBbuf tmp_buf = tmp_str.mb_str(); + if ( Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error()) + { + m_lastError = wxPROTO_NETERR; + return 0; + } + +#ifdef __WXDEBUG__ + // don't show the passwords in the logs (even in debug ones) + wxString cmd, password; + if ( command.Upper().StartsWith(_T("PASS "), &password) ) + { + cmd << _T("PASS ") << wxString(_T('*'), password.length()); + } + else + { + cmd = command; + } + + wxLogTrace(FTP_TRACE_MASK, _T("==> %s"), cmd.c_str()); +#endif // __WXDEBUG__ + + return GetResult(); +} + +// ---------------------------------------------------------------------------- +// Recieve servers reply +// ---------------------------------------------------------------------------- + +char RestartingFTP::GetResult() +{ + // if we've already had a read or write timeout error, the connection is + // probably toast, so don't bother, it just wastes the users time + if ( m_bEncounteredError ) + return 0; + + wxString code; + + // m_lastResult will contain the entire server response, possibly on + // multiple lines + m_lastResult.clear(); + + // we handle multiline replies here according to RFC 959: it says that a + // reply may either be on 1 line of the form "xyz ..." or on several lines + // in whuch case it looks like + // xyz-... + // ... + // xyz ... + // and the intermeidate lines may start with xyz or not + bool badReply = false; + bool firstLine = true; + bool endOfReply = false; + while ( !endOfReply && !badReply ) + { + wxString line; + m_lastError = ReadLine(this,line); + if ( m_lastError ) + { + m_bEncounteredError = true; + return 0; + } + + if ( !m_lastResult.empty() ) + { + // separate from last line + m_lastResult += _T('\n'); + } + + m_lastResult += line; + + // unless this is an intermediate line of a multiline reply, it must + // contain the code in the beginning and '-' or ' ' following it + if ( line.Len() < LEN_CODE + 1 ) + { + if ( firstLine ) + { + badReply = true; + } + else + { + wxLogTrace(FTP_TRACE_MASK, _T("<== %s %s"), + code.c_str(), line.c_str()); + } + } + else // line has at least 4 chars + { + // this is the char which tells us what we're dealing with + wxChar chMarker = line.GetChar(LEN_CODE); + + if ( firstLine ) + { + code = wxString(line, LEN_CODE); + wxLogTrace(FTP_TRACE_MASK, _T("<== %s %s"), + code.c_str(), line.c_str() + LEN_CODE + 1); + + switch ( chMarker ) + { + case _T(' '): + endOfReply = true; + break; + + case _T('-'): + firstLine = false; + break; + + default: + // unexpected + badReply = true; + } + } + else // subsequent line of multiline reply + { + if ( wxStrncmp(line, code, LEN_CODE) == 0 ) + { + if ( chMarker == _T(' ') ) + { + endOfReply = true; + } + + wxLogTrace(FTP_TRACE_MASK, _T("<== %s %s"), + code.c_str(), line.c_str() + LEN_CODE + 1); + } + else + { + // just part of reply + wxLogTrace(FTP_TRACE_MASK, _T("<== %s %s"), + code.c_str(), line.c_str()); + } + } + } + } + + if ( badReply ) + { + wxLogDebug(_T("Broken FTP server: '%s' is not a valid reply."), + m_lastResult.c_str()); + + m_lastError = wxPROTO_PROTERR; + + return 0; + } + + // if we got here we must have a non empty code string + return (char)code[0u]; +} + +// ---------------------------------------------------------------------------- +// wxFTP simple commands +// ---------------------------------------------------------------------------- + +bool RestartingFTP::SetTransferMode(TransferMode transferMode) +{ + if ( transferMode == m_currentTransfermode ) + { + // nothing to do + return true; + } + + wxString mode; + switch ( transferMode ) + { + default: + wxFAIL_MSG(_T("unknown FTP transfer mode")); + // fall through + + case BINARY: + mode = _T('I'); + break; + + case ASCII: + mode = _T('A'); + break; + } + + if ( !DoSimpleCommand(_T("TYPE"), mode) ) + { + wxLogError(_("Failed to set FTP transfer mode to %s."), (const wxChar*) + (transferMode == ASCII ? _("ASCII") : _("binary"))); + + return false; + } + + // If we get here the operation has been successfully completed + // Set the status-member + m_currentTransfermode = transferMode; + + return true; +} + +bool RestartingFTP::DoSimpleCommand(const wxChar *command, const wxString& arg) +{ + wxString fullcmd = command; + if ( !arg.empty() ) + { + fullcmd << _T(' ') << arg; + } + + if ( !CheckCommand(fullcmd, '2') ) + { + wxLogDebug(_T("FTP command '%s' failed."), fullcmd.c_str()); + + return false; + } + + return true; +} + +bool RestartingFTP::ChDir(const wxString& dir) +{ + // some servers might not understand ".." if they use different directory + // tree conventions, but they always understand CDUP - should we use it if + // dir == ".."? OTOH, do such servers (still) exist? + + return DoSimpleCommand(_T("CWD"), dir); +} + +bool RestartingFTP::MkDir(const wxString& dir) +{ + return DoSimpleCommand(_T("MKD"), dir); +} + +bool RestartingFTP::RmDir(const wxString& dir) +{ + return DoSimpleCommand(_T("RMD"), dir); +} + +wxString RestartingFTP::Pwd() +{ + wxString path; + + if ( CheckCommand(wxT("PWD"), '2') ) + { + // the result is at least that long if CheckCommand() succeeded + const wxChar *p = m_lastResult.c_str() + LEN_CODE + 1; + if ( *p != _T('"') ) + { + wxLogDebug(_T("Missing starting quote in reply for PWD: %s"), p); + } + else + { + for ( p++; *p; p++ ) + { + if ( *p == _T('"') ) + { + // check if the quote is doubled + p++; + if ( !*p || *p != _T('"') ) + { + // no, this is the end + break; + } + //else: yes, it is: this is an embedded quote in the + // filename, treat as normal char + } + + path += *p; + } + + if ( !*p ) + { + wxLogDebug(_T("Missing ending quote in reply for PWD: %s"), + m_lastResult.c_str() + LEN_CODE + 1); + } + } + } + else + { + wxLogDebug(_T("FTP PWD command failed.")); + } + + return path; +} + +bool RestartingFTP::Rename(const wxString& src, const wxString& dst) +{ + wxString str; + + str = wxT("RNFR ") + src; + if ( !CheckCommand(str, '3') ) + return false; + + str = wxT("RNTO ") + dst; + + return CheckCommand(str, '2'); +} + +bool RestartingFTP::RmFile(const wxString& path) +{ + wxString str; + str = wxT("DELE ") + path; + + return CheckCommand(str, '2'); +} + +// ---------------------------------------------------------------------------- +// wxFTP download and upload +// ---------------------------------------------------------------------------- + +class wxInputFTPStream : public wxSocketInputStream +{ +public: + wxInputFTPStream(RestartingFTP *ftp, wxSocketBase *sock) + : wxSocketInputStream(*sock) + { + m_ftp = ftp; + // socket timeout automatically set in GetPort function + } + + virtual ~wxInputFTPStream() + { + delete m_i_socket; // keep at top + + // when checking the result, the stream will + // almost always show an error, even if the file was + // properly transfered, thus, lets just grab the result + + // we are looking for "226 transfer completed" + char code = m_ftp->GetResult(); + if ('2' == code) + { + // it was a good transfer. + // we're done! + m_ftp->m_streaming = false; + return; + } + // did we timeout? + if (0 == code) + { + // the connection is probably toast. issue an abort, and + // then a close. there won't be any more waiting + // for this connection + m_ftp->Abort(); + m_ftp->Close(); + return; + } + // There was a problem with the transfer and the server + // has acknowledged it. If we issue an "ABORT" now, the user + // would get the "226" for the abort and think the xfer was + // complete, thus, don't do anything here, just return + } + + RestartingFTP *m_ftp; + + DECLARE_NO_COPY_CLASS(wxInputFTPStream) +}; + +class wxOutputFTPStream : public wxSocketOutputStream +{ +public: + wxOutputFTPStream(RestartingFTP *ftp_clt, wxSocketBase *sock) + : wxSocketOutputStream(*sock), m_ftp(ftp_clt) + { + } + + virtual ~wxOutputFTPStream(void) + { + if ( IsOk() ) + { + // close data connection first, this will generate "transfer + // completed" reply + delete m_o_socket; + + // read this reply + m_ftp->GetResult(); // save result so user can get to it + + m_ftp->m_streaming = false; + } + else + { + // abort data connection first + m_ftp->Abort(); + + // and close it after + delete m_o_socket; + } + } + + RestartingFTP *m_ftp; + + DECLARE_NO_COPY_CLASS(wxOutputFTPStream) +}; + +void RestartingFTP::SetDefaultTimeout(wxUint32 Value) +{ + m_uiDefaultTimeout = Value; + SetTimeout(Value); // sets it for this socket +} + + +wxSocketBase *RestartingFTP::GetPort() +{ + /* + PASSIVE: Client sends a "PASV" to the server. The server responds with + an address and port number which it will be listening on. Then + the client connects to the server at the specified address and + port. + + ACTIVE: Client sends the server a PORT command which includes an + address and port number which the client will be listening on. + The server then connects to the client at that address and + port. + */ + + wxSocketBase *socket = m_bPassive ? GetPassivePort() : GetActivePort(); + if ( !socket ) + { + m_bEncounteredError = true; + return NULL; + } + + // Now set the time for the new socket to the default or user selected + // timeout period + socket->SetTimeout(m_uiDefaultTimeout); + + return socket; +} + +wxSocketBase *RestartingFTP::AcceptIfActive(wxSocketBase *sock) +{ + if ( m_bPassive ) + return sock; + + // now wait for a connection from server + wxSocketServer *sockSrv = (wxSocketServer *)sock; + if ( !sockSrv->WaitForAccept() ) + { + m_lastError = wxPROTO_CONNERR; + wxLogError(_("Timeout while waiting for FTP server to connect, try passive mode.")); + delete sock; + sock = NULL; + } + else + { + sock = sockSrv->Accept(true); + delete sockSrv; + } + + return sock; +} + +wxString RestartingFTP::GetPortCmdArgument(const wxIPV4address& addrLocal, + const wxIPV4address& addrNew) +{ + // Just fills in the return value with the local IP + // address of the current socket. Also it fill in the + // PORT which the client will be listening on + + wxString addrIP = addrLocal.IPAddress(); + int portNew = addrNew.Service(); + + // We need to break the PORT number in bytes + addrIP.Replace(_T("."), _T(",")); + addrIP << _T(',') + << wxString::Format(_T("%d"), portNew >> 8) << _T(',') + << wxString::Format(_T("%d"), portNew & 0xff); + + // Now we have a value like "10,0,0,1,5,23" + return addrIP; +} + +wxSocketBase *RestartingFTP::GetActivePort() +{ + // we need an address to listen on + wxIPV4address addrNew, addrLocal; + GetLocal(addrLocal); + addrNew.AnyAddress(); + addrNew.Service(0); // pick an open port number. + + wxSocketServer *sockSrv = new wxSocketServer(addrNew); + if (!sockSrv->Ok()) + { + // We use Ok() here to see if everything is ok + m_lastError = wxPROTO_PROTERR; + delete sockSrv; + return NULL; + } + + //gets the new address, actually it is just the port number + sockSrv->GetLocal(addrNew); + + // Now we create the argument of the PORT command, we send in both + // addresses because the addrNew has an IP of "0.0.0.0", so we need the + // value in addrLocal + wxString port = GetPortCmdArgument(addrLocal, addrNew); + if ( !DoSimpleCommand(_T("PORT"), port) ) + { + m_lastError = wxPROTO_PROTERR; + delete sockSrv; + wxLogError(_("The FTP server doesn't support the PORT command.")); + return NULL; + } + + sockSrv->Notify(false); // Don't send any events + return sockSrv; +} + +wxSocketBase *RestartingFTP::GetPassivePort() +{ + if ( !DoSimpleCommand(_T("PASV")) ) + { + wxLogError(_("The FTP server doesn't support passive mode.")); + return NULL; + } + + const wxChar *addrStart = wxStrchr(m_lastResult, _T('(')); + const wxChar *addrEnd = addrStart ? wxStrchr(addrStart, _T(')')) : NULL; + if ( !addrEnd ) + { + m_lastError = wxPROTO_PROTERR; + + return NULL; + } + + // get the port number and address + int a[6]; + wxString straddr(addrStart + 1, addrEnd); + wxSscanf(straddr, wxT("%d,%d,%d,%d,%d,%d"), + &a[2],&a[3],&a[4],&a[5],&a[0],&a[1]); + + wxUint32 hostaddr = (wxUint16)a[2] << 24 | + (wxUint16)a[3] << 16 | + (wxUint16)a[4] << 8 | + a[5]; + wxUint16 port = (wxUint16)(a[0] << 8 | a[1]); + + wxIPV4address addr; + addr.Hostname(hostaddr); + addr.Service(port); + + wxSocketClient *client = new wxSocketClient(); + if ( !client->Connect(addr) ) + { + delete client; + return NULL; + } + + client->Notify(false); + + return client; +} + +bool RestartingFTP::Abort() +{ + if ( !m_streaming ) + return true; + + m_streaming = false; + if ( !CheckCommand(wxT("ABOR"), '4') ) + return false; + + return CheckResult('2'); +} + +wxInputStream *RestartingFTP::GetInputStream(const wxString& path) +{ + if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) ) + return NULL; + + wxSocketBase *sock = GetPort(); + + if ( !sock ) + { + m_lastError = wxPROTO_NETERR; + return NULL; + } + + wxString tmp_str = wxT("RETR ") + wxURI::Unescape(path); + if ( !CheckCommand(tmp_str, '1') ) + return NULL; + + sock = AcceptIfActive(sock); + if ( !sock ) + return NULL; + + sock->SetFlags(wxSOCKET_WAITALL); + + m_streaming = true; + + wxInputFTPStream *in_stream = new wxInputFTPStream(this, sock); + + return in_stream; +} + +wxOutputStream *RestartingFTP::GetOutputStream(const wxString& path) +{ + if ( ( m_currentTransfermode == NONE ) && !SetTransferMode(BINARY) ) + return NULL; + + wxSocketBase *sock = GetPort(); + + wxString tmp_str = wxT("STOR ") + path; + if ( !CheckCommand(tmp_str, '1') ) + return NULL; + + sock = AcceptIfActive(sock); + + m_streaming = true; + + return new wxOutputFTPStream(this, sock); +} + +// ---------------------------------------------------------------------------- +// FTP directory listing +// ---------------------------------------------------------------------------- + +bool RestartingFTP::GetList(wxArrayString& files, + const wxString& wildcard, + bool details) +{ + wxSocketBase *sock = GetPort(); + if (!sock) + return false; + + // NLST : List of Filenames (including Directory's !) + // LIST : depending on BS of FTP-Server + // - Unix : result like "ls" command + // - Windows : like "dir" command + // - others : ? + wxString line(details ? _T("LIST") : _T("NLST")); + if ( !wildcard.empty() ) + { + line << _T(' ') << wildcard; + } + + if ( !CheckCommand(line, '1') ) + { + m_lastError = wxPROTO_PROTERR; + wxLogDebug(_T("FTP 'LIST' command returned unexpected result from server")); + delete sock; + return false; + } + + sock = AcceptIfActive(sock); + if ( !sock ) + return false; + + files.Empty(); + while (ReadLine(sock, line) == wxPROTO_NOERR ) + { + files.Add(line); + } + + delete sock; + + // the file list should be terminated by "226 Transfer complete"" + return CheckResult('2'); +} + +bool RestartingFTP::FileExists(const wxString& fileName) +{ + // This function checks if the file specified in fileName exists in the + // current dir. It does so by simply doing an NLST (via GetList). + // If this succeeds (and the list is not empty) the file exists. + + bool retval = false; + wxArrayString fileList; + + if ( GetList(fileList, fileName, false) ) + { + // Some ftp-servers (Ipswitch WS_FTP Server 1.0.5 does this) + // displays this behaviour when queried on a nonexistent file: + // NLST this_file_does_not_exist + // 150 Opening ASCII data connection for directory listing + // (no data transferred) + // 226 Transfer complete + // Here wxFTP::GetList(...) will succeed but it will return an empty + // list. + retval = !fileList.IsEmpty(); + } + + return retval; +} + +// ---------------------------------------------------------------------------- +// FTP GetSize +// ---------------------------------------------------------------------------- + +int RestartingFTP::GetFileSize(const wxString& fileName) +{ + // return the filesize of the given file if possible + // return -1 otherwise (predominantly if file doesn't exist + // in current dir) + + int filesize = -1; + + // Check for existance of file via wxFTP::FileExists(...) + if ( FileExists(fileName) ) + { + wxString command; + + // First try "SIZE" command using BINARY(IMAGE) transfermode + // Especially UNIX ftp-servers distinguish between the different + // transfermodes and reports different filesizes accordingly. + // The BINARY size is the interesting one: How much memory + // will we need to hold this file? + TransferMode oldTransfermode = m_currentTransfermode; + SetTransferMode(BINARY); + command << _T("SIZE ") << fileName; + + bool ok = CheckCommand(command, '2'); + + if ( ok ) + { + // The answer should be one line: "213 \n" + // 213 is File Status (STD9) + // "SIZE" is not described anywhere..? It works on most servers + int statuscode; + if ( wxSscanf(GetLastResult().c_str(), _T("%i %i"), + &statuscode, &filesize) == 2 ) + { + // We've gotten a good reply. + ok = true; + } + else + { + // Something bad happened.. A "2yz" reply with no size + // Fallback + ok = false; + } + } + + // Set transfermode back to the original. Only the "SIZE"-command + // is dependant on transfermode + if ( oldTransfermode != NONE ) + { + SetTransferMode(oldTransfermode); + } + + // this is not a direct else clause.. The size command might return an + // invalid "2yz" reply + if ( !ok ) + { + // The server didn't understand the "SIZE"-command or it + // returned an invalid reply. + // We now try to get details for the file with a "LIST"-command + // and then parse the output from there.. + wxArrayString fileList; + if ( GetList(fileList, fileName, true) ) + { + if ( !fileList.IsEmpty() ) + { + // We _should_ only get one line in return, but just to be + // safe we run through the line(s) returned and look for a + // substring containing the name we are looking for. We + // stop the iteration at the first occurrence of the + // filename. The search is not case-sensitive. + bool foundIt = false; + + size_t i; + for ( i = 0; !foundIt && i < fileList.Count(); i++ ) + { + foundIt = fileList[i].Upper().Contains(fileName.Upper()); + } + + if ( foundIt ) + { + // The index i points to the first occurrence of + // fileName in the array Now we have to find out what + // format the LIST has returned. There are two + // "schools": Unix-like + // + // '-rw-rw-rw- owner group size month day time filename' + // + // or Windows-like + // + // 'date size filename' + + // check if the first character is '-'. This would + // indicate Unix-style (this also limits this function + // to searching for files, not directories) + if ( fileList[i].Mid(0, 1) == _T("-") ) + { + + if ( wxSscanf(fileList[i].c_str(), + _T("%*s %*s %*s %*s %i %*s %*s %*s %*s"), + &filesize) != 9 ) + { + // Hmm... Invalid response + wxLogTrace(FTP_TRACE_MASK, + _T("Invalid LIST response")); + } + } + else // Windows-style response (?) + { + if ( wxSscanf(fileList[i].c_str(), + _T("%*s %*s %i %*s"), + &filesize) != 4 ) + { + // something bad happened..? + wxLogTrace(FTP_TRACE_MASK, + _T("Invalid or unknown LIST response")); + } + } + } + } + } + } + } + + // filesize might still be -1 when exiting + return filesize; +} + + +wxInputStream *RestartingFTP::GetInputStreamRestart(const wxString& path,int startPos) +{ + if ((m_currentTransfermode == NONE) && !SetTransferMode(BINARY)) + { + return NULL; + } + + wxSocketBase *sock = GetPort(); + + if (!sock) + { + m_lastError = wxPROTO_NETERR; + return NULL; + } + + wxString tmp_str; + // support re-receiving + tmp_str.Printf("REST %i",startPos); + if (!CheckCommand(tmp_str,'3')) + { + return NULL; + } + + tmp_str = wxT("RETR ") + wxURI::Unescape(path); + if (!CheckCommand(tmp_str, '1')) + { + return NULL; + } + + sock = AcceptIfActive(sock); + if (!sock) + { + return NULL; + } + + sock->SetFlags(wxSOCKET_WAITALL); + m_streaming=true; + + wxInputFTPStream *in_stream=new wxInputFTPStream(this,sock); + + return (in_stream); +} + +#endif // wxUSE_PROTOCOL_FTP + diff --git a/RestartingFTP.h b/RestartingFTP.h new file mode 100644 index 0000000..f44358a --- /dev/null +++ b/RestartingFTP.h @@ -0,0 +1,184 @@ + +///////////////////////////////////////////////////////////////////////////// +// Name: ftp.h +// Purpose: FTP protocol +// Author: Vadim Zeitlin +// Modified by: Mark Johnson, wxWindows@mj10777.de +// 20000917 : RmDir, GetLastResult, GetList +// Created: 07/07/1997 +// RCS-ID: $Id: ftp.h 45498 2007-04-16 13:03:05Z VZ $ +// Copyright: (c) 1997, 1998 Guilhem Lavaux +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef __RESTARTING_WX_FTP_H__ +#define __RESTARTING_WX_FTP_H__ + +#include "wx/defs.h" + +#if wxUSE_PROTOCOL_FTP + +//#include "wx/sckaddr.h" +#include "wx/protocol/protocol.h" +#include "wx/url.h" + +class WXDLLIMPEXP_NET RestartingFTP : public wxProtocol +{ +public: + virtual wxInputStream *GetInputStreamRestart(const wxString &path,int startPos=0); + enum TransferMode + { + NONE, // not set by user explicitly + ASCII, + BINARY + }; + + RestartingFTP(); + virtual ~RestartingFTP(); + + // Connecting and disconnecting + void SetUser(const wxString& user) { m_user = user; } + void SetPassword(const wxString& passwd) { m_passwd = passwd; } + + bool Connect(wxSockAddress& addr, bool wait = true); + bool Connect(const wxString& host); + + // disconnect + virtual bool Close(); + + // Parameters set up + + // set transfer mode now + void SetPassive(bool pasv) { m_bPassive = pasv; } + void SetDefaultTimeout(wxUint32 Value); + bool SetBinary() { return SetTransferMode(BINARY); } + bool SetAscii() { return SetTransferMode(ASCII); } + bool SetTransferMode(TransferMode mode); + + // Generic FTP interface + + // the error code + virtual wxProtocolError GetError() { return m_lastError; } + + // the last FTP server reply + const wxString& GetLastResult() { return m_lastResult; } + + // send any FTP command (should be full FTP command line but without + // trailing "\r\n") and return its return code + char SendCommand(const wxString& command); + + // check that the command returned the given code + bool CheckCommand(const wxString& command, char expectedReturn) + { + return SendCommand(command) == expectedReturn; + } + + // Filesystem commands + bool ChDir(const wxString& dir); + bool MkDir(const wxString& dir); + bool RmDir(const wxString& dir); + wxString Pwd(); + bool Rename(const wxString& src, const wxString& dst); + bool RmFile(const wxString& path); + + // Get the size of a file in the current dir. + // this function tries its best to deliver the size in bytes using BINARY + // (the SIZE command reports different sizes depending on whether + // type is set to ASCII or BINARY) + // returns -1 if file is non-existant or size could not be found + int GetFileSize(const wxString& fileName); + + // Check to see if a file exists in the current dir + bool FileExists(const wxString& fileName); + + // Download methods + bool Abort(); + + virtual wxInputStream *GetInputStream(const wxString& path); + virtual wxOutputStream *GetOutputStream(const wxString& path); + + // Directory listing + + // get the list of full filenames, the format is fixed: one file name per + // line + bool GetFilesList(wxArrayString& files, + const wxString& wildcard = wxEmptyString) + { + return GetList(files, wildcard, false); + } + + // get a directory list in server dependent format - this can be shown + // directly to the user + bool GetDirList(wxArrayString& files, + const wxString& wildcard = wxEmptyString) + { + return GetList(files, wildcard, true); + } + + // equivalent to either GetFilesList() (default) or GetDirList() + bool GetList(wxArrayString& files, + const wxString& wildcard = wxEmptyString, + bool details = false); + +protected: + // this executes a simple ftp command with the given argument and returns + // true if it its return code starts with '2' + bool DoSimpleCommand(const wxChar *command, + const wxString& arg = wxEmptyString); + + // get the server reply, return the first character of the reply code, + // '1'..'5' for normal FTP replies, 0 (*not* '0') if an error occurred + char GetResult(); + + // check that the result is equal to expected value + bool CheckResult(char ch) { return GetResult() == ch; } + + // return the socket to be used, Passive/Active versions are used only by + // GetPort() + wxSocketBase *GetPort(); + wxSocketBase *GetPassivePort(); + wxSocketBase *GetActivePort(); + + // helper for GetPort() + wxString GetPortCmdArgument(const wxIPV4address& Local, const wxIPV4address& New); + + // accept connection from server in active mode, returns the same socket as + // passed in in passive mode + wxSocketBase *AcceptIfActive(wxSocketBase *sock); + + + wxString m_user, + m_passwd; + + wxString m_lastResult; + wxProtocolError m_lastError; + + // true if there is an FTP transfer going on + bool m_streaming; + + // although this should be set to ASCII by default according to STD9, + // we will use BINARY transfer mode by default for backwards compatibility + TransferMode m_currentTransfermode; + + friend class wxInputFTPStream; + friend class wxOutputFTPStream; + + bool m_bPassive; + wxUint32 m_uiDefaultTimeout; + + // following is true when a read or write times out, we then assume + // the connection is dead and abort. we avoid additional delays this way + bool m_bEncounteredError; + + + DECLARE_DYNAMIC_CLASS_NO_COPY(RestartingFTP) + DECLARE_PROTOCOL(RestartingFTP) +}; + +// the trace mask used by assorted wxLogTrace() in ftp code, do +// wxLog::AddTraceMask(FTP_TRACE_MASK) to see them in output +#define FTP_TRACE_MASK _T("ftp") + +#endif // wxUSE_PROTOCOL_FTP + +#endif // __WX_FTP_H__ diff --git a/Round.cpp b/Round.cpp new file mode 100644 index 0000000..ab9eea4 --- /dev/null +++ b/Round.cpp @@ -0,0 +1,1671 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "GlobalStatistics.h" +#include "Round.h" +#include "LogFileReader.h" +#include "ErrorData.h" +#include "PlayerInRound.h" +#include "ConfigData.h" +#include "StaticFunctions.h" +#include "Progress.h" +#include "XPPoints.h" + +void DecodedTeamWin::Clear() +{ + teamName=""; + playerIDs.Clear(); + playerRoundIDs.Clear(); + playerNames.Clear(); +} + +void DecodedTeamLoss::Clear() +{ + teamName=""; + playerIDs.Clear(); + playerRoundIDs.Clear(); + playerNames.Clear(); +} + +void RoundLine::Set(wxDateTime &lineTimeIn,wxString &lineIn) +{ + lineTime=lineTimeIn; + line=lineIn; +} + +Round::Round() +{ + logfileReader=NULL; + dropped=false; +} + +Round::~Round() +{ +} + +void Round::Debug() +{ + wxString errorMessage; + KillData kill; + ActionData action; + SpeechData speech; + TeamWinData teamWin; + TeamLossData teamLoss; + PlayerInRound player; + int killCount; + int killIndex; + int actionCount; + int actionIndex; + int speechCount; + int speechIndex; + int playerCount; + int playerIndex; + int teamWinCount; + int teamWinIndex; + int teamLossCount; + int teamLossIndex; + wxString timeString; + wxString durationString; + + STATSGEN_DEBUG_FUNCTION_START("Round","Debug") + timeString=roundStartTime.Format(); + durationString=roundDuration.Format("%H:%M:%S"); + STATSGEN_DEBUG_CODE(errorMessage.Printf("Round:[%s] Duration[%s]", timeString.GetData(), durationString.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage); + killCount=kills.GetCount(); + for (killIndex=0;killIndexGetServerType(); + teamWinAlreadyFound=false; + teamLossAlreadyFound=false; + STATSGEN_DEBUG_FUNCTION_END +} + +bool Round::IsDropped() +{ + bool retVal=true; + wxString minPlayersInRoundString; + int minPlayersInRound; + wxString msg; + + // Minimum players in round is a "Hard" drop + // i.e. we don't want to count any of these stats + // at all + STATSGEN_DEBUG_FUNCTION_START("Round","IsDropped") + + globalStatistics.configData.ReadTextValue( + "/General/MinPlayersInRound", + &minPlayersInRoundString, + "1"); + + minPlayersInRound=atoi(minPlayersInRoundString.GetData()); + + STATSGEN_DEBUG_CODE(msg.Printf("kills=%d, actions=%d, playersinround=%d, minPlayersInRound=%d",kills.GetCount(),actions.GetCount(),playersInRound.GetCount(),minPlayersInRound);) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + retVal=false; + if (((kills.GetCount()==0) && + (actions.GetCount()==0)) || + (playersInRound.GetCount()IsWorldPlayer(decode.playerID,decode.playerTeam,decode.playerName)) + { + playerID=WORLD_PLAYER_ID; + playerName=WORLD_PLAYER_NAME; + playerTeam=WORLD_PLAYER_TEAM; + } + else + { + playerID=serverType+"_"+decode.playerID; + playerName=decode.playerName; + playerTeam=serverType+"_"+decode.playerTeam.Lower(); + cheat=false; + if (globalStatistics.dropList.IsDropped(playerName,&cheat)) + { + if (cheat) + { + // Cheats get no kills + globalStatistics.cheaters.Add(playerName); + STATSGEN_DEBUG_FUNCTION_END + return; + } + } + } + + if (logfileReader->IsWorldPlayer(decode.targetID,decode.targetTeam,decode.targetName)) + { + targetID=WORLD_PLAYER_ID; + targetName=WORLD_PLAYER_NAME; + targetTeam=WORLD_PLAYER_TEAM; + } + else + { + cheat=false; + globalStatistics.dropList.IsDropped(decode.targetName,&cheat); + if (cheat) + { + // If the target is a cheat - make it appear as the + // world player - then it will be counted as a kill + // by the player but will get dropped along with the + // other stats + globalStatistics.cheaters.Add(decode.targetName); + targetID=WORLD_PLAYER_ID; + targetName=WORLD_PLAYER_NAME; + targetTeam=WORLD_PLAYER_TEAM; + } + else + { + targetID=serverType+"_"+decode.targetID; + targetTeam=serverType+"_"+decode.targetTeam.Lower(); + targetName=decode.targetName; + } + } + + weaponAndAmmo=playerWeapon+playerAmmo; + SubstituteLogEntry("CLASS",playerClass); + SubstituteLogEntry("TEAM",playerTeam); + SubstituteLogEntry("WEAPON",playerWeapon); + + if (SubstituteLogEntry("AMMO",playerAmmo)) + { + // we made an ammo substitution + playerWeapon=playerAmmo; + } + if (SubstituteLogEntry("WEAPONAMMO",weaponAndAmmo)) + { + // we made an ammo substitution + playerWeapon=weaponAndAmmo; + } + + + SubstituteLogEntry("CLASS",targetClass); + SubstituteLogEntry("TEAM",targetTeam); + SubstituteLogEntry("LOCATION",targetLocation); + + StoreLogEntry("WEAPON",playerWeapon); + StoreLogEntry("LOCATION",targetLocation); + + kill.killTime=killTime; + kill.gameType=gameType; + kill.mapName=mapName; + kill.playerIndex=globalStatistics.AddPlayer(playerName,playerID); + kill.playerClass=globalStatistics.GenericKeyAdd(globalStatistics.keysClass,playerClass); + kill.playerTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,playerTeam); + kill.playerWeapon=globalStatistics.GenericKeyAdd(globalStatistics.keysWeapon,playerWeapon); + kill.playerAmmo=globalStatistics.GenericKeyAdd(globalStatistics.keysAmmo,playerAmmo); + kill.targetIndex=globalStatistics.AddPlayer(targetName,targetID); + kill.targetClass=globalStatistics.GenericKeyAdd(globalStatistics.keysClass,targetClass); + kill.targetTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,targetTeam); + kill.targetDamage=atoi(decode.targetDamage); + kill.targetLocation=globalStatistics.GenericKeyAdd(globalStatistics.keysLocation,targetLocation); + kills.Add(kill); + STATSGEN_DEBUG_CODE( + msg.Printf("player:Name[%s],id[%s],Class[%s],Team[%s],Weapon[%s] target:Name[%s],id[%s],class[%s],team[%s],location[%s]", + playerName.GetData(), + playerID.GetData(), + playerClass.GetData(), + playerTeam.GetData(), + playerWeapon.GetData(), + targetName.GetData(), + targetID.GetData(), + targetClass.GetData(), + targetTeam.GetData(), + targetLocation.GetData()); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + UpdatePlayerInRoundTime(kill.playerIndex,killTime,false); + UpdatePlayerInRoundTime(kill.targetIndex,killTime,false); + STATSGEN_DEBUG_FUNCTION_END +} + +bool Round::WordAtTextPosition(wxString &speechLine, + int speechStartIndex, + int speechLength, + wxString &bannedWord, + int *replacementLength) +{ + bool retVal; + wxString speech; + int bannedWordLength; + + bannedWordLength=bannedWord.Length(); + speech=speechLine.Mid(speechStartIndex).Left(bannedWordLength); + retVal=(speech.CmpNoCase(bannedWord)==0); + if (retVal) + { + (*replacementLength)=bannedWordLength; + } + return (retVal); +} + +void Round::AddSpeech(DecodedSpeech &decode, + wxDateTime &speechTime) +{ + SpeechData speech; + wxString playerID=serverType+"_"+decode.playerID; + bool cheat=false; + int bannedSpeechCount; + int bannedSpeechIndex; + wxString bannedWord; + int speechLength; + int speechIndex; + bool speechFound; + int replacementLength; + wxString msg; + wxString newSpeech; + + STATSGEN_DEBUG_FUNCTION_START("Round","AddSpeech") + + speech.speechTime=speechTime; + cheat=false; + globalStatistics.WriteSpeechFile(speechTime,playerID,decode.playerName,decode.speech); + if (globalStatistics.dropList.IsDropped(decode.playerName,&cheat)) + { + if (cheat) + { + globalStatistics.cheaters.Add(decode.playerName); + // no cheats get speech + STATSGEN_DEBUG_FUNCTION_END + return; + } + } + speech.playerIndex=globalStatistics.AddPlayer(decode.playerName,playerID); + speechLength=decode.speech.Length(); + + bannedSpeechCount=globalStatistics.bannedSpeech.GetCount(); + if (bannedSpeechCount>0) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Checking Banned Speech") + speechIndex=0; + while (speechIndex0) + { + // entry found - substitute + logEntry=configValue; + retVal=true; + } + else + { + // not found - so no change + retVal=false; + } + + return (retVal); +} + +void Round::StoreLogEntry(const char *logEntryType, + wxString &logEntry) +{ + wxString configKey; + + configKey.Printf("/LogEntries%s/%s",logEntryType,logEntry.GetData()); + globalStatistics.configData.WriteTextValue(configKey,""); +} + +void Round::AddAction(DecodedAction &decode, + wxDateTime &actionTime, + int gameType, + int mapName) +{ + ActionData action; + bool cheat; + wxString msg; + wxString playerID=serverType+"_"+decode.playerID; + wxString playerClass=serverType+"_"+decode.playerClass.Lower(); + wxString playerTeam=serverType+"_"+decode.playerTeam.Lower(); + wxString playerAction=serverType+"_"+decode.action.Lower(); + + STATSGEN_DEBUG_FUNCTION_START("Round","AddAction") + + STATSGEN_DEBUG_CODE( + msg.Printf("playerName[%s] playerID[%s] playerClass[%s] playerTeam[%s] action[%s]", + decode.playerName.GetData(), + decode.playerID.GetData(), + decode.playerClass.GetData(), + decode.playerTeam.GetData(), + decode.action.GetData()); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg); + SafeString(playerClass); + SafeString(playerTeam); + SafeString(playerAction); + cheat=false; + if (globalStatistics.dropList.IsDropped(decode.playerName,&cheat)) + { + if (cheat) + { + globalStatistics.cheaters.Add(decode.playerName); + STATSGEN_DEBUG_FUNCTION_END + return; + } + } + SubstituteLogEntry("CLASS",playerClass); + SubstituteLogEntry("TEAM",playerTeam); + SubstituteLogEntry("ACTION",playerAction); + + StoreLogEntry("ACTION",playerAction); + + action.actionTime=actionTime; + action.gameType=gameType; + action.mapName=mapName; + action.playerIndex=globalStatistics.AddPlayer(decode.playerName,playerID); + action.playerClass=globalStatistics.GenericKeyAdd(globalStatistics.keysClass,playerClass); + action.playerTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,playerTeam); + action.action=globalStatistics.GenericKeyAdd(globalStatistics.keysAction,playerAction); + actions.Add(action); + UpdatePlayerInRoundTime(action.playerIndex,actionTime,false); + STATSGEN_DEBUG_FUNCTION_END +} + +void Round::AddTeamWin(DecodedTeamWin &decode, + wxDateTime &winTime, + int gameType, + int mapName) +{ + TeamWinData playerData; + bool cheat; + int playerCount; + int playerIndex; + wxString playerName; + wxString playerID; + wxString msg; + wxString teamName=serverType+"_"+decode.teamName.Lower(); + + STATSGEN_DEBUG_FUNCTION_START("Round","AddTeamWin") + + SubstituteLogEntry("TEAM",teamName); + + playerCount=decode.playerIDs.GetCount(); + for (playerIndex=0;playerIndexWakeUp(); + STATSGEN_DEBUG(DEBUG_RARELY,roundLine.line) + //if (roundLinesIndex==(roundLinesCount-1)) + //{ + roundDuration=roundLine.lineTime.Subtract(roundStartTime); + //} + if (roundDuration<0) + { + roundStartTime=roundLine.lineTime; + roundDuration=roundStartTime.Subtract(roundStartTime); + } + if (logfileReader->DecodeRoundStart(roundLine.line, + decodeRoundStart, + this)) + { + roundStartTime=roundLine.lineTime; + roundDuration=roundStartTime.Subtract(roundStartTime); + if (decodeRoundStart.mapName.Length()>0) + { + mapNameString=serverType+"_"+decodeRoundStart.mapName.Lower(); + SubstituteLogEntry("MAP",mapNameString); + mapName=globalStatistics.GenericKeyAdd(globalStatistics.keysMap,mapNameString); + } + if (decodeRoundStart.gameType.Length()>0) + { + gameTypeString=serverType+"_"+decodeRoundStart.gameType.Lower(); + SubstituteLogEntry("GAMETYPE",gameTypeString); + gameType=globalStatistics.GenericKeyAdd(globalStatistics.keysGametype,gameTypeString); + } + + } + else + if (logfileReader->DecodeSpeech(roundLine.line, + decodeSpeech)) + { + AddSpeech(decodeSpeech,roundLine.lineTime); + } + else + if (logfileReader->DecodeAction(roundLine.line, + decodeAction)) + { + AddAction(decodeAction,roundLine.lineTime,gameType,mapName); + } + else + if (logfileReader->DecodePlayerJoin(roundLine.line, + decodePlayerJoin)) + { + AddJoin(decodePlayerJoin,roundLine.lineTime); + } + else + if (logfileReader->DecodePlayerQuit(roundLine.line, + decodePlayerQuit)) + { + AddQuit(decodePlayerQuit,roundLine.lineTime); + } + else + if (logfileReader->DecodeKill(roundLine.line, + decodeKill)) + { + if (decodeKill.targetTeam.Length()==0) + { + decodeKill.targetTeam="targetteam"; + } + if (decodeKill.playerTeam.Length()==0) + { + decodeKill.playerTeam="playerteam"; + } + AddKill(decodeKill,roundLine.lineTime,gameType,mapName); + } + else + if ((!teamWinAlreadyFound) && (logfileReader->DecodeTeamWin(roundLine.line, + decodeTeamWin))) + { + AddTeamWin(decodeTeamWin,roundLine.lineTime,gameType,mapName); + if (serverType.CmpNoCase(SERVER_TYPE_COD5)!=0) + { + teamWinAlreadyFound=true; + } + } + else + if ((!teamLossAlreadyFound) && (logfileReader->DecodeTeamLoss(roundLine.line, + decodeTeamLoss))) + { + AddTeamLoss(decodeTeamLoss,roundLine.lineTime,gameType,mapName); + if (serverType.CmpNoCase(SERVER_TYPE_COD5)!=0) + { + teamLossAlreadyFound=true; + } + } + } + + + + // End of round - can remove round lines + roundLines.Clear(); + + STATSGEN_DEBUG_FUNCTION_END +} + +void Round::CalculateScores(int roundIndex) +{ + int playerCount; + int playerInRoundIndex; + int killCount; + int actionCount; + int winCount; + int lossCount; + int killIndex; + int actionIndex; + int winIndex; + int lossIndex; + wxString configKey; + wxString configValue; + + StreakData streak; + int streakIndex; + int streakCount; + + PlayerInRound playerInRound; + Player player; + ActionData action; + KillData kill; + TeamWinData teamWin; + TeamLossData teamLoss; + + float score; + float skill; + float weaponSkill; + float locationSkill; + + KillTypes killType; + wxString weaponStr; + wxString locationStr; + wxString actionStr; + + float teamLossScoreWeight; + float teamWinScoreWeight; + float killScoreWeight; + float deathScoreWeight; + float teamKillScoreWeight; + float teamSwapScoreWeight; + float suicideScoreWeight; + float gametypeScoreWeight; + float gametypeSkillWeight; + int speechCount; + int speechPoints; + int speechIndex; + bool playerInRoundUseful; + int xpCount; + int xpIndex; + XPPoints xp; + wxString xpStr; + + if (dropped) + { + // don't calculate if round dropped + return; + } + + teamWinScoreWeight=globalStatistics.ScoreWeight("TeamWin",1.0); + + teamLossScoreWeight=globalStatistics.ScoreWeight("TeamLoss",1.0); + + killScoreWeight=globalStatistics.ScoreWeight("Kill",1.0); + + deathScoreWeight=globalStatistics.ScoreWeight("Death",-1.0); + + suicideScoreWeight=globalStatistics.ScoreWeight("Suicide",-3.0); + + teamKillScoreWeight=globalStatistics.ScoreWeight("TeamKill",-2.0); + teamSwapScoreWeight=globalStatistics.ScoreWeight("TeamSwap",0.0); + gametypeScoreWeight=globalStatistics.GametypeScoreWeight(gameType); + gametypeSkillWeight=globalStatistics.GametypeSkillWeight(gameType); + + playerCount=playersInRound.GetCount(); + killCount=kills.GetCount(); + actionCount=actions.GetCount(); + winCount=teamWins.GetCount(); + lossCount=teamLosses.GetCount(); + + speechCount=speeches.GetCount(); + playerInRoundIndex=0; + while (playerInRoundIndex0) + { + playerInRound.UpdateMiscAwardPoints("Speech",speechPoints); + } + // don't calculate players score if they are dropped + + score=0.0; + skill=0.0; + // keep getting the first item as we are gonna remove it and move it to the end + playerInRound.CalculateStreaks(&kills,gameType); + // XP Scores + xpCount=xpPoints.GetCount(); + for (xpIndex=0;xpIndexplayer.longestTeamKillStreak) + { + player.longestTeamKillStreak=streak.streakSize; + } + } + // Kills + streakCount=playerInRound.killStreak.GetCount(); + for (streakIndex=0;streakIndexplayer.longestKillStreak) + { + player.longestKillStreak=streak.streakSize; + } + } + // Death Streaks + streakCount=playerInRound.deathStreak.GetCount(); + for (streakIndex=0;streakIndexplayer.longestDeathStreak) + { + player.longestDeathStreak=streak.streakSize; + } + } + + globalStatistics.playerList.Insert(player,playerInRound.playerIndex); + } + } + playersInRound.RemoveAt(0); + // + playerInRoundUseful=true; + // + if (playerInRoundUseful) + { + playersInRound.Add(playerInRound); + } + else + { + // This player did not do a thing in this round + // no talking - no killing - no dying - no team winning / losing + // so we are gonna delete them - they are probably just a + // spectator + playerCount--; + } + playerInRoundIndex++; + } + // Looped through every player + // replace the current player with the newly modified one +} + +void Round::WriteToDatabase(int roundIndex) +{ + wxString SQL; + int count; + int subIndex; + KillData kill; + ActionData action; + TeamWinData teamWin; + TeamLossData teamLoss; + SpeechData speech; + PlayerInRound player; + char droppedChar; + int variableCount; + int variableIndex; + wxString variable; + wxString value; + XPPoints xp; + int xpCount; + int xpIndex; + + STATSGEN_DEBUG_FUNCTION_START("Round","WriteToDatabase") + + variableCount=logfileVariableKeys.GetCount(); + for (variableIndex=0;variableIndexGetServerType(); + kills.Clear(); + actions.Clear(); + speeches.Clear(); + playersInRound.Clear(); + teamWins.Clear(); + teamLosses.Clear(); + + mapNameString=serverType+"_"+mapNameIn.Lower(); + gameTypeString=serverType+"_"+gameTypeIn.Lower(); + + SubstituteLogEntry("GAMETYPE",gameTypeString); + SubstituteLogEntry("MAP",mapNameString); + + mapName=globalStatistics.GenericKeyAdd(globalStatistics.keysMap,mapNameString); + gameType=globalStatistics.GenericKeyAdd(globalStatistics.keysGametype,gameTypeString); +} + +void Round::AddTeamWin(wxString &playerGUID,wxString &playerName,wxString &playerTeam, + time_t mapStartTime,time_t mapEndTime) +{ + TeamWinData playerData; + bool cheat; + wxString playerID; + wxString teamName=serverType+"_"+playerTeam.Lower(); + wxDateTime playerTime; + + SubstituteLogEntry("TEAM",teamName); + + if (globalStatistics.dropList.IsDropped(playerName,&cheat)) + { + if (cheat) + { + globalStatistics.cheaters.Add(playerName); + } + } + if (!cheat) + { + playerID=serverType+"_"+playerGUID; + playerData.playerIndex=globalStatistics.AddPlayer(playerName,playerID); + playerData.playerTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,teamName); + playerData.gameType=gameType; + playerData.mapName=mapName; + playerData.playerClass=0; + teamWins.Add(playerData); + playerTime.Set(mapStartTime); + UpdatePlayerInRoundTime(playerData.playerIndex,playerTime,true); + playerTime.Set(mapEndTime); + UpdatePlayerInRoundTime(playerData.playerIndex,playerTime,false); + } +} + +void Round::AddTeamLoss(wxString &playerGUID,wxString &playerName,wxString &playerTeam, + time_t mapStartTime,time_t mapEndTime) +{ + TeamLossData playerData; + bool cheat; + wxString playerID; + wxString teamName=serverType+"_"+playerTeam.Lower(); + wxDateTime playerTime; + + SubstituteLogEntry("TEAM",teamName); + + if (globalStatistics.dropList.IsDropped(playerName,&cheat)) + { + if (cheat) + { + globalStatistics.cheaters.Add(playerName); + } + } + if (!cheat) + { + playerID=serverType+"_"+playerGUID; + playerData.playerIndex=globalStatistics.AddPlayer(playerName,playerID); + playerData.playerTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,teamName); + playerData.gameType=gameType; + playerData.mapName=mapName; + playerData.playerClass=0; + teamLosses.Add(playerData); + playerTime.Set(mapStartTime); + UpdatePlayerInRoundTime(playerData.playerIndex,playerTime,true); + playerTime.Set(mapEndTime); + UpdatePlayerInRoundTime(playerData.playerIndex,playerTime,false); + } +} + +void Round::AddKill(DecodedKill &decode) +{ + KillData kill; + wxString playerID; + wxString playerClass; + wxString playerTeam; + wxString playerWeapon; + wxString playerAmmo; + wxString targetID; + wxString targetClass; + wxString targetTeam; + wxString targetLocation; + wxString weaponAndAmmo; + wxString playerName; + wxString targetName; + bool cheat; + wxDateTime killTime; + + STATSGEN_DEBUG_FUNCTION_START("Round","AddKill") + playerClass=serverType+"_"+decode.playerClass.Lower(); + playerWeapon=serverType+"_"+decode.playerWeapon.Lower(); + playerAmmo=serverType+"_"+decode.playerAmmo; + targetClass=serverType+"_"+decode.targetClass.Lower(); + targetTeam=serverType+"_"+decode.targetTeam.Lower(); + targetLocation=serverType+"_"+decode.targetLocation.Lower(); + + SafeString(playerClass); + SafeString(playerWeapon); + SafeString(playerAmmo); + SafeString(targetClass); + SafeString(targetTeam); + SafeString(targetLocation); + + if (logfileReader->IsWorldPlayer(decode.playerID,decode.playerTeam,decode.playerName)) + { + playerID=WORLD_PLAYER_ID; + playerName=WORLD_PLAYER_NAME; + playerTeam=WORLD_PLAYER_TEAM; + } + else + { + playerID=serverType+"_"+decode.playerID; + playerName=decode.playerName; + playerTeam=serverType+"_"+decode.playerTeam.Lower(); + cheat=false; + if (globalStatistics.dropList.IsDropped(playerName,&cheat)) + { + if (cheat) + { + // Cheats get no kills + globalStatistics.cheaters.Add(playerName); + return; + } + } + } + + if (logfileReader->IsWorldPlayer(decode.targetID,decode.targetTeam,decode.targetName)) + { + targetID=WORLD_PLAYER_ID; + targetName=WORLD_PLAYER_NAME; + targetTeam=WORLD_PLAYER_TEAM; + } + else + { + cheat=false; + globalStatistics.dropList.IsDropped(decode.targetName,&cheat); + if (cheat) + { + // If the target is a cheat - make it appear as the + // world player - then it will be counted as a kill + // by the player but will get dropped along with the + // other stats + globalStatistics.cheaters.Add(decode.targetName); + targetID=WORLD_PLAYER_ID; + targetName=WORLD_PLAYER_NAME; + targetTeam=WORLD_PLAYER_TEAM; + } + else + { + targetID=serverType+"_"+decode.targetID; + targetTeam=serverType+"_"+decode.targetTeam.Lower(); + targetName=decode.targetName; + } + } + + weaponAndAmmo=playerWeapon+playerAmmo; + SubstituteLogEntry("CLASS",playerClass); + SubstituteLogEntry("TEAM",playerTeam); + SubstituteLogEntry("WEAPON",playerWeapon); + + if (SubstituteLogEntry("AMMO",playerAmmo)) + { + // we made an ammo substitution + playerWeapon=playerAmmo; + } + if (SubstituteLogEntry("WEAPONAMMO",weaponAndAmmo)) + { + // we made an ammo substitution + playerWeapon=weaponAndAmmo; + } + + + SubstituteLogEntry("CLASS",targetClass); + SubstituteLogEntry("TEAM",targetTeam); + SubstituteLogEntry("LOCATION",targetLocation); + + StoreLogEntry("WEAPON",playerWeapon); + StoreLogEntry("LOCATION",targetLocation); + + kill.gameType=gameType; + kill.mapName=mapName; + kill.playerIndex=globalStatistics.AddPlayer(playerName,playerID); + kill.playerClass=globalStatistics.GenericKeyAdd(globalStatistics.keysClass,playerClass); + kill.playerTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,playerTeam); + kill.playerWeapon=globalStatistics.GenericKeyAdd(globalStatistics.keysWeapon,playerWeapon); + kill.playerAmmo=globalStatistics.GenericKeyAdd(globalStatistics.keysAmmo,playerAmmo); + kill.targetIndex=globalStatistics.AddPlayer(targetName,targetID); + kill.targetClass=globalStatistics.GenericKeyAdd(globalStatistics.keysClass,targetClass); + kill.targetTeam=globalStatistics.GenericKeyAdd(globalStatistics.keysTeam,targetTeam); + kill.targetDamage=0; + kill.targetLocation=globalStatistics.GenericKeyAdd(globalStatistics.keysLocation,targetLocation); + kills.Add(kill); + UpdatePlayerInRoundTime(kill.playerIndex,killTime,false); + UpdatePlayerInRoundTime(kill.targetIndex,killTime,false); +} + +void Round::AddXPPoints(wxString &playerName, + wxString &playerGUID, + wxString &xpKey, + float points) +{ + XPPoints xp; + XPPoints xpFound; + wxString xpID; + wxString playerID; + int xpIndex; + int xpCount; + bool cheat; + + xpID=serverType+"_"+xpKey.Lower(); + SafeString(xpID); + playerID=serverType+"_"+playerGUID; + xp.pointsIndex=globalStatistics.GenericKeyAdd(globalStatistics.keysXP,xpID); + xp.points=points; + + if (globalStatistics.dropList.IsDropped(playerName,&cheat)) + { + if (cheat) + { + // Cheats get no kills + globalStatistics.cheaters.Add(playerName); + return; + } + } + xp.playerIndex=globalStatistics.AddPlayer(playerName,playerID); + // First we have to remove any existing entry and replace it with + // this one + xpCount=xpPoints.GetCount(); + for (xpIndex=0;xpIndex +#include +#include +#include + +// Statsgen Includes +#include "ErrorData.h" +#include "KillData.h" +#include "ActionData.h" +#include "SpeechData.h" +#include "TeamWinData.h" +#include "TeamLossData.h" +#include "PlayerInRound.h" +#include "XPPoints.h" + +class LogFileReader; + +class DecodedTeamLoss +{ + public: + void Clear(); + wxString teamName; + wxArrayString playerIDs; + wxArrayString playerRoundIDs; + wxArrayString playerNames; +}; + +class DecodedTeamWin +{ + public: + void Clear(); + wxString teamName; + wxArrayString playerIDs; + wxArrayString playerRoundIDs; + wxArrayString playerNames; +}; + +class DecodedKill +{ + public: + wxString playerID; + wxString playerRoundID; + wxString playerName; + wxString playerClass; + wxString playerTeam; + wxString playerWeapon; + wxString playerAmmo; + wxString targetID; + wxString targetRoundID; + wxString targetName; + wxString targetClass; + wxString targetTeam; + wxString targetDamage; + wxString targetLocation; +}; +class DecodedPlayerJoin +{ + public: + wxString playerID; + wxString playerRoundID; + wxString playerName; + wxString playerClass; + wxString playerTeam; +}; + +class DecodedPlayerQuit +{ + public: + wxString playerID; + wxString playerRoundID; + wxString playerName; +}; + +class DecodedAction +{ + public: + wxString playerID; + wxString playerRoundID; + wxString playerTeam; + wxString playerClass; + wxString playerName; + wxString action; +}; + +class DecodedSpeech +{ + public: + wxString playerID; + wxString playerRoundID; + wxString playerName; + wxString speech; +}; + +class DecodedRoundStart +{ + public: + wxString admin; + wxString location; + wxString website; + wxString gameType; + wxString mapName; + wxString maxClients; + wxString privateClients; +}; + +class RoundLine +{ + public: + void Set(wxDateTime &lineTimeIn,wxString &lineIn); + wxDateTime lineTime; + wxString line; +}; + +WX_DECLARE_OBJARRAY(RoundLine,ArrayOfRoundLines); + +class Round; + +WX_DECLARE_OBJARRAY(Round,ArrayOfRounds); +class Round +{ + public: + Round(); + virtual ~Round(); + void Debug(); + void Initiate(LogFileReader *reader, + wxDateTime &lineTime, + wxString &line); + void AddLogLine(wxDateTime &lineTime,wxString &line); + void Process(ErrorData &errorData,int serverIndexIn); + bool IsDropped(); + void CalculateScores(int roundIndex); + void WriteToDatabase(int index); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + static wxString SQLCreateVariableTable(); + static wxString SQLVariableTableName(); + void AddVariable(wxString &variable,wxString &value); + void SetStartingCondition(int serverIndexIn, + wxString &mapNameIn, + time_t durationIn, + wxString &gameTypeIn); + void AddTeamLoss(wxString &guid, + wxString &playerName, + wxString &playerTeam, + time_t mapStartTime, + time_t mapEndTime); + void AddTeamWin(wxString &guid, + wxString &playerName, + wxString &playerTeam, + time_t mapStartTime, + time_t mapEndTime); + void AddKill(DecodedKill &decoded); + void AddSpeech(DecodedSpeech &decoded, + wxDateTime &speechTime); + void AddXPPoints(wxString &playerName, + wxString &playerGUID, + wxString &xpKey, + float points); + + public: + int serverIndex; + ArrayOfKillData kills; + ArrayOfActionData actions; + ArrayOfTeamWinData teamWins; + ArrayOfTeamLossData teamLosses; + ArrayOfSpeechData speeches; + ArrayOfPlayersInRound playersInRound; + ArrayOfXPPoints xpPoints; + int activePlayers; + + wxArrayString logfileVariableKeys; + wxArrayString logfileVariableValues; + bool dropped; + wxTimeSpan roundDuration; + + private: + void AddKill(DecodedKill &decoded, + wxDateTime &killTime, + int gameType, + int mapName); + void AddTeamLoss(DecodedTeamLoss &decoded, + wxDateTime &lossTime, + int gameType, + int mapName); + void AddTeamWin(DecodedTeamWin &decoded, + wxDateTime &winTime, + int gameType, + int mapName); + void AddAction(DecodedAction &decoded, + wxDateTime &actionTime, + int gameType, + int mapName); + void AddJoin(DecodedPlayerJoin &decoded, + wxDateTime &joinTime); + void AddQuit(DecodedPlayerQuit &decoded, + wxDateTime &quitTime); + + void UpdatePlayerInRoundTime(int playerIndex, wxDateTime &timeStamp,bool resetTime); + bool SubstituteLogEntry(const char *logEntryType, + wxString &logEntry); + void StoreLogEntry(const char *logEntryType, + wxString &logEntry); + + private: + bool WordAtTextPosition( + wxString &speechLine, + int speechIndex, + int speechLength, + wxString &bannedWord, + int *replacementLength); + + wxDateTime roundStartTime; + int gameType; + int mapName; + LogFileReader *logfileReader; + ArrayOfRoundLines roundLines; + wxString serverType; + + bool teamWinAlreadyFound; + bool teamLossAlreadyFound; + +}; + +#endif diff --git a/ScheduleConfigItemGUI.cpp b/ScheduleConfigItemGUI.cpp new file mode 100644 index 0000000..c8fac1a --- /dev/null +++ b/ScheduleConfigItemGUI.cpp @@ -0,0 +1,215 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "ScheduleConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "ScheduleDialog.h" + +BEGIN_EVENT_TABLE(ScheduleConfigItemGUI, wxPanel) + EVT_SIZE(ScheduleConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,ScheduleConfigItemGUI::OnTextChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,ScheduleConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +ScheduleConfigItemGUI::ScheduleConfigItemGUI() +{ + configKey=""; + intervalWithBase=false; +} + +void ScheduleConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +ScheduleConfigItemGUI::~ScheduleConfigItemGUI() +{ +} + +void ScheduleConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void ScheduleConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + bool intervalWithBaseIn) +{ + wxSizeEvent event; + wxSize buttonSize(16,16); + + labelText=labelTextIn; + defaultValue=defaultValueIn; + intervalWithBase=intervalWithBaseIn; + + //SetConfigKey(configKey); + + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + configKey=configKeyIn; + + //button.Create(this, + // WINDOW_ID_CONFIG_BUTTON, + // wxArtProvider::GetIcon(wxART_FILE_OPEN, + // wxART_OTHER, + // buttonSize)); + wxString resourceID="CLOCK_ICON"; + wxIcon buttonIcon(resourceID, + wxBITMAP_TYPE_ICO_RESOURCE, + 16,16); + button.Create(this, + WINDOW_ID_CONFIG_BUTTON, + buttonIcon); + SetConfigKey(configKey); + + OnResize(event); +} + +wxString ScheduleConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int ScheduleConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void ScheduleConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void ScheduleConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int panelWidth; + int panelHeight; + int buttonWidth; + int buttonHeight; + int widthForTextEdit; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=button.GetSize(); + buttonWidth=itemSize.GetWidth(); + buttonHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-buttonWidth; + if (widthForTextEdit<1) + { + widthForTextEdit=1; + } + + button.SetSize(labelWidth,0,buttonWidth,buttonHeight); + textEdit.SetSize(labelWidth+buttonWidth,0,widthForTextEdit,textHeight); +} + +void ScheduleConfigItemGUI::OnButtonPressed(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + const wxString title="Schedule"; + const wxString name="ScheduleEditor"; + long style=wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX; + wxWindowID id=-1; + wxPoint position=wxDefaultPosition; + wxSize size=wxSize(200,100); + + value=textEdit.GetValue(); + ScheduleDialog scheduleDialog((wxWindow *)this, + (wxWindowID)id, + title, + value, + (bool)intervalWithBase, + position, + size, + (long)style, + name); + if (scheduleDialog.DisplayDialog()) + { + textEdit.SetValue(scheduleDialog.GetValue()); + } + else + { + // Cancel + } +} diff --git a/ScheduleConfigItemGUI.h b/ScheduleConfigItemGUI.h new file mode 100644 index 0000000..4b37e13 --- /dev/null +++ b/ScheduleConfigItemGUI.h @@ -0,0 +1,44 @@ +#ifndef __SCHEDULECONFIGITEMGUI +#define __SCHEDULECONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class ScheduleConfigItemGUI : public BaseConfigItemGUI +{ + public: + ScheduleConfigItemGUI(); + virtual ~ScheduleConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + bool intervalWithBaseIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxTextCtrl textEdit; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + wxString labelText; + wxString defaultValue; + bool intervalWithBase; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ScheduleDialog.cpp b/ScheduleDialog.cpp new file mode 100644 index 0000000..eff83a2 --- /dev/null +++ b/ScheduleDialog.cpp @@ -0,0 +1,55 @@ +// Statsgen Includes +#include "ScheduleDialog.h" +#include "PlayerDataList.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" + +ScheduleDialog::ScheduleDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + wxString &value, + bool intervalWithBase, + wxPoint &pos, + wxSize &size, + long style, + const wxString &name) : GenericOKCancelDialog + (parent, + id, + title, + pos, + size, + style, + name + ) +{ + + panel=new ScheduleEditorPanel(value,intervalWithBase); + panel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); +} + +bool ScheduleDialog::DisplayDialog() +{ + return (GenericOKCancelDialog::DisplayDialog((wxPanel *)panel)); +} + +ScheduleDialog::~ScheduleDialog() +{ +} + +void ScheduleDialog::OnSave(wxCommandEvent &event) +{ + GenericOKCancelDialog::OnSave(event); +} + +void ScheduleDialog::OnQuit(wxCommandEvent &event) +{ + GenericOKCancelDialog::OnQuit(event); +} + +wxString ScheduleDialog::GetValue() +{ + return (panel->GetValue()); +} diff --git a/ScheduleDialog.h b/ScheduleDialog.h new file mode 100644 index 0000000..ee3d31d --- /dev/null +++ b/ScheduleDialog.h @@ -0,0 +1,38 @@ +#ifndef __SCHEDULEDIALOG +#define __SCHEDULEDIALOG + +#include +#include + +// Statsgen Includes +#include "GenericOKCancelDialog.h" +#include "ScheduleEditorPanel.h" +#include "WindowIDs.h" + +class ScheduleDialog : public GenericOKCancelDialog +{ + public: + ScheduleDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + wxString &value, + bool intervalWithBase, + wxPoint &pos, + wxSize &size, + long style, + const wxString &name); + + virtual ~ScheduleDialog(); + + virtual void OnSave(wxCommandEvent& event); + virtual void OnQuit(wxCommandEvent& event); + virtual bool DisplayDialog(); + virtual wxString GetValue(); + + protected: + + private: + ScheduleEditorPanel *panel; +}; + +#endif diff --git a/ScheduleEditorPanel.cpp b/ScheduleEditorPanel.cpp new file mode 100644 index 0000000..a766624 --- /dev/null +++ b/ScheduleEditorPanel.cpp @@ -0,0 +1,256 @@ +// Statsgen Includes +#include "ScheduleEditorPanel.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(ScheduleEditorPanel, wxPanel) + EVT_SIZE(ScheduleEditorPanel::OnResize) +END_EVENT_TABLE() + +ScheduleEditorPanel::ScheduleEditorPanel(wxString &valueIn, + bool intervalWithBaseIn) +{ + value=valueIn; + intervalWithBase=intervalWithBaseIn; + baseLabel=NULL; + baseHours=NULL; + baseMinutes=NULL; + baseSeconds=NULL; + intervalLabel=NULL; + intervalHours=NULL; + intervalMinutes=NULL; + intervalSeconds=NULL; +} + +ScheduleEditorPanel::~ScheduleEditorPanel() +{ +} + +void ScheduleEditorPanel::SplitValue( + wxString &baseHourString, + wxString &baseMinuteString, + wxString &baseSecondString, + wxString &intervalHourString, + wxString &intervalMinuteString, + wxString &intervalSecondString) +{ + wxString baseScheduleComponent; + wxString intervalScheduleComponent; + wxString timeComponent; + int hours; + int minutes; + int seconds; + int totalSeconds; + + baseHourString=""; + baseMinuteString=""; + baseSecondString=""; + intervalHourString=""; + intervalMinuteString=""; + intervalSecondString=""; + if (intervalWithBase) + { + baseScheduleComponent=value.BeforeFirst(','); + intervalScheduleComponent=value.AfterFirst(','); + timeComponent=baseScheduleComponent.BeforeFirst(':'); + hours=atoi(timeComponent.GetData()); + baseScheduleComponent=baseScheduleComponent.AfterFirst(':'); + timeComponent=baseScheduleComponent.BeforeFirst(':'); + minutes=atoi(timeComponent.GetData()); + baseScheduleComponent=baseScheduleComponent.AfterFirst(':'); + seconds=atoi(baseScheduleComponent.GetData()); + + baseHourString.Printf("%02d",hours); + baseMinuteString.Printf("%02d",minutes); + baseSecondString.Printf("%02d",seconds); + } + else + { + intervalScheduleComponent=value; + } + + totalSeconds=atoi(intervalScheduleComponent.GetData()); + hours=totalSeconds/3600; + totalSeconds-=(hours*3600); + minutes=totalSeconds/60; + seconds=totalSeconds % 60; + intervalHourString.Printf("%02d",hours); + intervalMinuteString.Printf("%02d",minutes); + intervalSecondString.Printf("%02d",seconds); +} + +void ScheduleEditorPanel::CreatePanel() +{ + wxString labelText; + wxString baseHourStr; + wxString baseMinuteStr; + wxString baseSecondStr; + wxString intervalHourStr; + wxString intervalMinuteStr; + wxString intervalSecondStr; + + SplitValue(baseHourStr, + baseMinuteStr, + baseSecondStr, + intervalHourStr, + intervalMinuteStr, + intervalSecondStr); + + if (intervalWithBase) + { + labelText="Base Time"; + baseLabel=new wxStaticText(); + baseLabel->Create(this,-1,labelText,wxDefaultPosition); + + baseHours=new wxTextCtrl(); + baseHours->Create(this,-1,baseHourStr); + + baseMinutes=new wxTextCtrl(); + baseMinutes->Create(this,-1,baseMinuteStr); + + baseSeconds=new wxTextCtrl(); + baseSeconds->Create(this,-1,baseSecondStr); + } + + labelText="Interval"; + intervalLabel=new wxStaticText(); + intervalLabel->Create(this,-1,labelText,wxDefaultPosition); + + intervalHours=new wxTextCtrl(); + intervalHours->Create(this,-1,intervalHourStr); + + intervalMinutes=new wxTextCtrl(); + intervalMinutes->Create(this,-1,intervalMinuteStr); + + intervalSeconds=new wxTextCtrl(); + intervalSeconds->Create(this,-1,intervalSecondStr); +} + +void ScheduleEditorPanel::SetValue() +{ + wxString baseTimeComponent; + wxString intervalTimeComponent; + + if (intervalWithBase) + { + baseTimeComponent.Printf("%02d:%02d:%02d,", + atoi(baseHours->GetValue().GetData()), + atoi(baseMinutes->GetValue().GetData()), + atoi(baseSeconds->GetValue().GetData())); + } + else + { + baseTimeComponent=""; + } + intervalTimeComponent.Printf("%d", + (atoi(intervalHours->GetValue().GetData())*3600)+ + (atoi(intervalMinutes->GetValue().GetData())*60)+ + atoi(intervalSeconds->GetValue().GetData())); + + value=baseTimeComponent+intervalTimeComponent; +} + +wxString ScheduleEditorPanel::GetValue() +{ + SetValue(); + return (value); +} + +void ScheduleEditorPanel::ResizeTime(int startX,int startY, + wxStaticText *label, + wxTextCtrl *hour, + wxTextCtrl *minute, + wxTextCtrl *second, + int *width, + int *height) +{ + wxSize itemSize; + int hourX; + int minuteX; + int secondX; + int hourWidth; + int minuteWidth; + int secondWidth; + int labelX; + int labelWidth; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("ScheduleEditorPanel","ResizeTime") + itemSize=label->GetSize(); + labelWidth=itemSize.GetWidth(); + labelWidth=10*FONT_CHAR_WIDTH; + // resize the hour to give it a basic size + //hour->SetSize(0,0,1,1); + + itemSize=hour->GetSize(); + *height=itemSize.GetHeight(); + + hourWidth=FONT_CHAR_WIDTH*2+FONT_TEXT_CTRL_GAP; + minuteWidth=FONT_CHAR_WIDTH*2+FONT_TEXT_CTRL_GAP; + secondWidth=FONT_CHAR_WIDTH*2+FONT_TEXT_CTRL_GAP; + labelX=startX; + hourX=labelX+labelWidth+FONT_CHAR_WIDTH; + minuteX=hourX+hourWidth+FONT_CHAR_WIDTH; + secondX=minuteX+minuteWidth+FONT_CHAR_WIDTH; + + label->SetSize(labelX,startY,labelWidth,*height); + hour->SetSize(hourX,startY,hourWidth,*height); + minute->SetSize(minuteX,startY,minuteWidth,*height); + second->SetSize(secondX,startY,secondWidth,*height); + + *width=secondX+secondWidth; + STATSGEN_DEBUG_CODE(msg.Printf("startX=%d,%d label=%d,%d hour=%d,%d minute=%d,%d second=%d,%d", + startX,*height, + labelX,labelWidth, + hourX,hourWidth, + minuteX,minuteWidth, + secondX,secondWidth);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + STATSGEN_DEBUG_FUNCTION_END +} + +void ScheduleEditorPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int panelWidth; + int panelHeight; + int baseWidth=0; + int baseHeight=0; + int intervalWidth=0; + int intervalHeight=0; + int startX; + int startY; + + STATSGEN_DEBUG_FUNCTION_START("ScheduleEditorPanel","OnResize") + + if (intervalHours==NULL) + { + CreatePanel(); + } + startX=0; + startY=0; + if (intervalWithBase) + { + ResizeTime(startX,startY, + baseLabel,baseHours,baseMinutes,baseSeconds, + &baseWidth,&baseHeight); + } + startX=0; + startY=baseHeight; + ResizeTime(startX,startY, + intervalLabel,intervalHours,intervalMinutes,intervalSeconds, + &intervalWidth,&intervalHeight); + itemSize=GetSize(); + if (baseWidth>intervalWidth) + { + panelWidth=baseWidth; + } + else + { + panelWidth=intervalWidth; + } + panelHeight=baseHeight+intervalHeight; + SetSize(0,0,panelWidth,panelHeight); + STATSGEN_DEBUG_FUNCTION_END +} diff --git a/ScheduleEditorPanel.h b/ScheduleEditorPanel.h new file mode 100644 index 0000000..80b03c8 --- /dev/null +++ b/ScheduleEditorPanel.h @@ -0,0 +1,55 @@ +#ifndef __SCHEDULEEDITORPANEL +#define __SCHEDULEEDITORPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" + +class ScheduleEditorPanel : public wxPanel +{ + public: + ScheduleEditorPanel(wxString &valueIn, + bool intervalWithBaseIn); + virtual ~ScheduleEditorPanel(); + + wxString GetValue(); + void OnResize(wxSizeEvent &event); + protected: + + private: + void SetValue(); + void CreatePanel(); + void SplitValue( + wxString &baseHourStr, + wxString &baseMinuteStr, + wxString &baseSecondStr, + wxString &intervalHourStr, + wxString &intervalMinuteStr, + wxString &intervalSecondStr); + + void ResizeTime(int startX,int startY, + wxStaticText *intervalLabel, + wxTextCtrl *hour, + wxTextCtrl *minute, + wxTextCtrl *second, + int *width, + int *height); + + wxTextCtrl *baseHours; + wxTextCtrl *baseMinutes; + wxTextCtrl *baseSeconds; + wxTextCtrl *intervalHours; + wxTextCtrl *intervalMinutes; + wxTextCtrl *intervalSeconds; + wxStaticText *baseLabel; + wxStaticText *intervalLabel; + bool intervalWithBase; + wxString value; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/ScheduleItem.cpp b/ScheduleItem.cpp new file mode 100644 index 0000000..1dc739e --- /dev/null +++ b/ScheduleItem.cpp @@ -0,0 +1,95 @@ +// wxWindows includes +#include + +// Statsgen includes +#include "ScheduleItem.h" + +ScheduleItem::ScheduleItem() +{ + whenToRun=time(&whenToRun); + disabled=true; + startNow=false; +} + +ScheduleItem::~ScheduleItem() +{ +} + +bool ScheduleItem::TimeToRun(long *timeRemaining) +{ + time_t currentTime; + bool timeToRun; + + if (disabled) + { + timeToRun=false; + *timeRemaining=0; + } + else + { + currentTime=time(¤tTime); + *timeRemaining=(whenToRun-currentTime); + timeToRun=((*timeRemaining)<0); + } + + if (startNow) + { + timeToRun=true; + } + startNow=false; + return (timeToRun); +} + +void ScheduleItem::IntervalStart(wxString &interval) +{ + time_t timeNow; + int value; + + value=atoi(interval.GetData()); + if (value==0) + { + disabled=true; + } + else + { + disabled=false; + timeNow=time(&timeNow); + whenToRun=timeNow+value; + } +} + +void ScheduleItem::StartNow() +{ + startNow=true; +} + +void ScheduleItem::ScheduledStart(wxString &base,wxString &interval) +{ + time_t timeNow; + long intervalSeconds; + wxDateTime currentTime=wxDateTime::Now(); + wxDateTime baseTime; + wxTimeSpan intervalTimeSpan; + + intervalSeconds=atol(interval.GetData()); + if (intervalSeconds==0) + { + disabled=true; + } + else + { + disabled=false; + intervalTimeSpan=wxTimeSpan::Seconds(intervalSeconds); + timeNow=time(&timeNow); + + baseTime=currentTime; + baseTime.ParseTime(base.GetData()); + while (baseTime.IsEarlierThan(currentTime)) + { + baseTime.Add(intervalTimeSpan); + } + + whenToRun=baseTime.GetTicks(); + } +} + diff --git a/ScheduleItem.h b/ScheduleItem.h new file mode 100644 index 0000000..8d83618 --- /dev/null +++ b/ScheduleItem.h @@ -0,0 +1,31 @@ +#ifndef __SCHEDULEITEM +#define __SCHEDULEITEM + +#include +// wxWindows includes +#include + +#include +#include + +// Statsgen Includes + +class ScheduleItem +{ + public: + ScheduleItem(); + virtual ~ScheduleItem(); + bool TimeToRun(long *timeRemaining); + void IntervalStart(wxString &interval); + void ScheduledStart(wxString &base,wxString &interval); + void StartNow(); + bool disabled; + + private: + time_t whenToRun; + bool startNow; + +}; + + +#endif diff --git a/SelectionConfigItemGUI.cpp b/SelectionConfigItemGUI.cpp new file mode 100644 index 0000000..755bfe3 --- /dev/null +++ b/SelectionConfigItemGUI.cpp @@ -0,0 +1,204 @@ +// Statsgen Includes +#include "SelectionConfigItemGUI.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(SelectionConfigItemGUI, wxPanel) + EVT_SIZE(SelectionConfigItemGUI::OnResize) + EVT_COMBOBOX(WINDOW_ID_TEXTCTRL_CONFIGVALUE,SelectionConfigItemGUI::OnTextChange) +END_EVENT_TABLE() + +SelectionConfigItemGUI::SelectionConfigItemGUI() +{ +} + +void SelectionConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString msg; + wxString key; + wxString value; + int codeCount; + int codeIndex; + wxString name; + wxString code; + + value=textEdit.GetValue(); + codeCount=codes.GetCount(); + for (codeIndex=0;codeIndex0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +SelectionConfigItemGUI::~SelectionConfigItemGUI() +{ +} + +void SelectionConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + int codeCount; + int codeIndex; + wxString code; + wxString name; + + STATSGEN_DEBUG_FUNCTION_START("SelectionConfigItemGUI","SetConfigKey") + + configKey=configKeyIn; + STATSGEN_DEBUG(DEBUG_ALWAYS,configKey) + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,value) + codeCount=codes.GetCount(); + for (codeIndex=0;codeIndex +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class SelectionConfigItemGUI : public BaseConfigItemGUI +{ + public: + SelectionConfigItemGUI(); + virtual ~SelectionConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + wxArrayString &codes, + wxArrayString &names); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxComboBox textEdit; + wxStaticText label; + wxString labelText; + wxString defaultValue; + wxArrayString codes; + wxArrayString names; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/SelectionFreeFormConfigItemGUI.cpp b/SelectionFreeFormConfigItemGUI.cpp new file mode 100644 index 0000000..fa3d794 --- /dev/null +++ b/SelectionFreeFormConfigItemGUI.cpp @@ -0,0 +1,246 @@ +// wx includes +#include "wx/artprov.h" +#include "wx/filename.h" + +// Statsgen Includes +#include "SelectionFreeFormConfigItemGUI.h" +#include "GlobalStatistics.h" +#include "Progress.h" + +BEGIN_EVENT_TABLE(SelectionFreeFormConfigItemGUI, wxPanel) + EVT_SIZE(SelectionFreeFormConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,SelectionFreeFormConfigItemGUI::OnTextChange) + EVT_TEXT(WINDOW_ID_SELECTION_CONFIGVALUE,SelectionFreeFormConfigItemGUI::OnSelectionChange) + EVT_BUTTON(WINDOW_ID_CONFIG_BUTTON,SelectionFreeFormConfigItemGUI::OnButtonPressed) +END_EVENT_TABLE() + +SelectionFreeFormConfigItemGUI::SelectionFreeFormConfigItemGUI() +{ + maxCharacters=-1; + configKey=""; +} + +void SelectionFreeFormConfigItemGUI::OnSelectionChange(wxCommandEvent& event) +{ + wxString value; + wxString code; + wxString name; + int codeCount; + int codeIndex; + + value=choices.GetValue(); + codeCount=codes.GetCount(); + for (codeIndex=0;codeIndex0) + { + globalStatistics.configData.WriteTextValue(configKey, + value); + } + if (GetParent()!=NULL) + { + wxCommandEvent newEvent; + newEvent.SetId(WINDOW_ID_TEXTCTRL_CONFIGVALUE); + newEvent.SetEventType(wxEVT_COMMAND_TEXT_UPDATED); + GetParent()->AddPendingEvent(newEvent); + } +} + +SelectionFreeFormConfigItemGUI::~SelectionFreeFormConfigItemGUI() +{ +} + +void SelectionFreeFormConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + globalStatistics.configData.ReadTextValue(configKey, + &value, + (char *)defaultValue.GetData()); + textEdit.SetValue(value); + } +} + +void SelectionFreeFormConfigItemGUI::Set( + wxString &configKeyIn, + wxString &labelTextIn, + wxString &defaultValueIn, + wxArrayString &codesIn, + wxArrayString &namesIn, + int maxCharactersIn) +{ + wxSizeEvent event; + wxString customCode=""; + wxString customName="Custom"; + wxString code; + wxString name; + + labelText=labelTextIn; + codes.Add(customCode); + names.Add(customName); + WX_APPEND_ARRAY(codes,codesIn); + WX_APPEND_ARRAY(names,namesIn); + + defaultValue=defaultValueIn; + maxCharacters=maxCharactersIn; + + //SetConfigKey(configKey); + + // Create the config items + label.Create(this, + -1, + labelText, + wxPoint(0,0)); + + choices.Create(this, + WINDOW_ID_SELECTION_CONFIGVALUE, + customName, + wxDefaultPosition, + wxDefaultSize, + names, + wxCB_DROPDOWN| + wxCB_READONLY); + + textEdit.Create(this, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + defaultValue, + wxDefaultPosition, + wxDefaultSize, + 0, + wxDefaultValidator); + + configKey=configKeyIn; + SetConfigKey(configKey); + + OnResize(event); +} + +wxString SelectionFreeFormConfigItemGUI::GetValue() +{ + return (textEdit.GetValue()); +} + +int SelectionFreeFormConfigItemGUI::GetLabelWidth() +{ + wxSize itemSize; + + itemSize=label.GetSize(); + return (itemSize.GetWidth()); +} + +void SelectionFreeFormConfigItemGUI::SetLabelWidth(int width) +{ + wxSize itemSize; + wxPoint itemPosition; + + itemSize=label.GetSize(); + itemPosition=label.GetPosition(); + + label.SetSize(itemPosition.x, + itemPosition.y, + width, + itemSize.GetHeight()); +} + +void SelectionFreeFormConfigItemGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int textWidth; + int textHeight; + int labelWidth; + int labelHeight; + int choicesWidth; + int choicesHeight; + int panelWidth; + int panelHeight; + int widthForTextEdit; + int fixedWidth; + + + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + itemSize=label.GetSize(); + labelWidth=itemSize.GetWidth(); + labelHeight=itemSize.GetHeight(); + + itemSize=choices.GetSize(); + choicesWidth=itemSize.GetWidth(); + choicesHeight=itemSize.GetHeight(); + + label.SetSize(0,0,labelWidth,labelHeight); + labelWidth+=5; + + itemSize=textEdit.GetSize(); + textWidth=itemSize.GetWidth(); + textHeight=itemSize.GetHeight(); + + widthForTextEdit=panelWidth-labelWidth-choicesWidth; + fixedWidth=(maxCharacters * FONT_CHAR_WIDTH)+FONT_TEXT_CTRL_GAP; + if (maxCharacters>0) + { + // We have an overriding field width + if (fixedWidth0) + { + textEdit.SetValue(newDirectory); + } + +} + +void SelectionFreeFormConfigItemGUI::SetValue(wxString &value) +{ + textEdit.SetValue(value); +} + diff --git a/SelectionFreeFormConfigItemGUI.h b/SelectionFreeFormConfigItemGUI.h new file mode 100644 index 0000000..214b936 --- /dev/null +++ b/SelectionFreeFormConfigItemGUI.h @@ -0,0 +1,51 @@ +#ifndef __SELECTIONFREEFORMCONFIGITEMGUI +#define __SELECTIONFREEFORMCONFIGITEMGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class SelectionFreeFormConfigItemGUI : public BaseConfigItemGUI +{ + public: + SelectionFreeFormConfigItemGUI(); + virtual ~SelectionFreeFormConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + void OnSelectionChange(wxCommandEvent& event); + void OnButtonPressed(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + wxArrayString &codes, + wxArrayString &names, + int maxCharactersIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + void SetValue(wxString &value); + protected: + + private: + wxTextCtrl textEdit; + wxComboBox choices; + wxBitmapButton button; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + wxArrayString codes; + wxArrayString names; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/Server.cpp b/Server.cpp new file mode 100644 index 0000000..49f106b --- /dev/null +++ b/Server.cpp @@ -0,0 +1,1511 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include +#include +#include + +// Statsgen includes +#include "Server.h" +#include "ErrorData.h" +#include "GlobalStatistics.h" +#include "RemoteMachine.h" +#include "Progress.h" +#include "PunkbusterBanFile.h" +#include "CODBanFile.h" +#include "QuakeWarsLogFile.h" + +char *ServerTypeCodes[SERVER_TYPE_COUNT]= +{ + SERVER_TYPE_COD1, + SERVER_TYPE_COD2, + SERVER_TYPE_COD4, + SERVER_TYPE_COD5, + SERVER_TYPE_MOHAA, + SERVER_TYPE_QUAKEWARS, + SERVER_TYPE_WOLFENSTEIN +}; + +char *ServerTypeNames[SERVER_TYPE_COUNT]= +{ + SERVER_TYPE_NAME_COD1, + SERVER_TYPE_NAME_COD2, + SERVER_TYPE_NAME_COD4, + SERVER_TYPE_NAME_COD5, + SERVER_TYPE_NAME_MOHAA, + SERVER_TYPE_NAME_QUAKEWARS, + SERVER_TYPE_NAME_WOLFENSTEIN +}; + +char *SkillTypeCodes[SKILL_TYPE_COUNT]= +{ + STAT_TYPE_CODE_WEAPON, + STAT_TYPE_CODE_LOCATION, + STAT_TYPE_CODE_GAMETYPE +}; + +char *SkillTypeNames[SKILL_TYPE_COUNT]= +{ + STAT_TYPE_NAME_WEAPON, + STAT_TYPE_NAME_LOCATION, + STAT_TYPE_NAME_GAMETYPE +}; + +char *ImageTypeCodes[IMAGE_TYPE_COUNT]= +{ + STAT_TYPE_CODE_WEAPON, + STAT_TYPE_CODE_MAP, + STAT_TYPE_CODE_LOCATION, + STAT_TYPE_CODE_GAMETYPE, + STAT_TYPE_CODE_TEAM, + STAT_TYPE_CODE_ACTION, + STAT_TYPE_CODE_CLASS +}; + +char *ImageTypeNames[IMAGE_TYPE_COUNT]= +{ + STAT_TYPE_NAME_WEAPON, + STAT_TYPE_NAME_MAP, + STAT_TYPE_NAME_LOCATION, + STAT_TYPE_NAME_GAMETYPE, + STAT_TYPE_NAME_TEAM, + STAT_TYPE_NAME_ACTION, + STAT_TYPE_NAME_CLASS +}; + +wxString sortingWildCard; + +Server::Server() +{ + STATSGEN_DEBUG_FUNCTION_START("Server","Constructor") + ID=""; + logFiles=NULL; + restartDownload=false; + STATSGEN_DEBUG_FUNCTION_END +} + +Server::~Server() +{ + STATSGEN_DEBUG_FUNCTION_START("Server","Destructor") + if (logFiles!=NULL) + { + delete (logFiles); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void Server::SetID(wxString &IDIn) +{ + ID=IDIn; +} + +bool Server::Initiate() +{ + bool retVal=false; + wxString configBaseKey; + wxString configKey; + wxString configValue; + + if (ID.Length()>0) + { + // Read in the configuration items for this server + configBaseKey="/Server"+ID; + configBaseKey+="/"; + + configKey=configBaseKey+"MaxLogfileSize"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"0"); + maxLogfileSize=atol(configValue.GetData()); + + configKey=configBaseKey+"archiveDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + archiveDirectory=configValue; + + configKey=configBaseKey+"archiveWildcard"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + archiveWildcard=configValue; + + configKey=configBaseKey+"latestDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + latestDirectory=configValue; + + configKey=configBaseKey+"latestFilename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + latestFilename=configValue; + + configKey=configBaseKey+"secondaryArchiveDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + secondaryArchiveDirectory=configValue; + + configKey=configBaseKey+"secondaryArchiveWildcard"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + secondaryArchiveWildcard=configValue; + + configKey=configBaseKey+"secondaryLatestDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + secondaryLatestDirectory=configValue; + + configKey=configBaseKey+"secondaryLatestFilename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + secondaryLatestFilename=configValue; + + configKey=configBaseKey+"serverType"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,SERVER_TYPE_COD1); + serverType=configValue; + + configKey=configBaseKey+"banFile1Type"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,SERVER_BAN_TYPE_COD); + banFile1Type=configValue; + + configKey=configBaseKey+"Ban1Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + ban1Directory=configValue; + + configKey=configBaseKey+"FTPBanFile1Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPBanFile1Directory=configValue; + + configKey=configBaseKey+"FTPBanFile1Filename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPBanFile1Filename=configValue; + + configKey=configBaseKey+"banFile2Type"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,SERVER_BAN_TYPE_COD); + banFile2Type=configValue; + + configKey=configBaseKey+"Ban2Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + ban2Directory=configValue; + + configKey=configBaseKey+"FTPBanFile2Directory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPBanFile2Directory=configValue; + + configKey=configBaseKey+"FTPBanFile2Filename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPBanFile2Filename=configValue; + + configKey=configBaseKey+"gameIP"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + gameIP=configValue; + + configKey=configBaseKey+"gamePort"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + gamePort=-1; + if (configValue.Length()>0) + { + gamePort=atoi(configValue.GetData()); + } + + configKey=configBaseKey+"FTPEnabled"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + FTPEnabled=(configValue.CmpNoCase("y")==0); + + configKey=configBaseKey+"FTPRestartDownload"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"y"); + restartDownload=(configValue.CmpNoCase("y")==0); + + configKey=configBaseKey+"FTPArchiveDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPArchiveDirectory=configValue; + + configKey=configBaseKey+"FTPArchiveWildcard"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPArchiveWildcard=configValue; + + configKey=configBaseKey+"FTPLatestDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPLatestDirectory=configValue; + + configKey=configBaseKey+"FTPLatestFilename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + FTPLatestFilename=configValue; + + configKey=configBaseKey+"FTPSecondaryArchiveDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPSecondaryArchiveDirectory=configValue; + + configKey=configBaseKey+"FTPSecondaryArchiveWildcard"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPSecondaryArchiveWildcard=configValue; + + configKey=configBaseKey+"FTPSecondaryLatestDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPSecondaryLatestDirectory=configValue; + + configKey=configBaseKey+"FTPSecondaryLatestFilename"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + FTPSecondaryLatestFilename=configValue; + + if (latestFilename.Length()==0) + { + latestFilename=FTPLatestFilename; + } + if (archiveWildcard.Length()==0) + { + archiveWildcard=FTPArchiveWildcard; + } + if (secondaryLatestFilename.Length()==0) + { + secondaryLatestFilename=FTPSecondaryLatestFilename; + } + if (secondaryArchiveWildcard.Length()==0) + { + secondaryArchiveWildcard=FTPSecondaryArchiveWildcard; + } + configKey=configBaseKey+"GuessTeamIDs"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"y"); + fakeTeamIDs=(configValue.CmpNoCase("y")==0); + } + + return (retVal); +} + +bool Server::DownloadFiles() +{ + bool retVal=true; + wxString serverID; + wxArrayString archiveFiles; + wxArrayString currentFiles; + wxArrayString secondaryArchiveFiles; + wxArrayString secondaryCurrentFiles; + bool archiveEnabled=false; + bool currentEnabled=false; + bool secondaryArchiveEnabled=false; + bool secondaryCurrentEnabled=false; + long totalFileSize=0; + long currentFileSize=0; + int fileIndex=0; + int fileCount=0; + wxString remoteFilename; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("Server","DownloadFiles") + + progress->Initiate(totalFileSize, + " kb", + 1024, + "kb", + 1024); + progress->Update(0); + if (FTPEnabled) + { + if ((archiveDirectory.Length()>0) && + (archiveWildcard.Length()>0) && + (FTPArchiveDirectory.Length()>0) && + (FTPArchiveWildcard.Length()>0)) + { + archiveEnabled=true; + } + if ((secondaryArchiveDirectory.Length()>0) && + (secondaryArchiveWildcard.Length()>0) && + (FTPSecondaryArchiveDirectory.Length()>0) && + (FTPSecondaryArchiveWildcard.Length()>0)) + { + secondaryArchiveEnabled=true; + } + if (latestFilename.Length()==0) + { + latestFilename=FTPLatestFilename; + } + if ((latestDirectory.Length()>0) && + (latestFilename.Length()>0) && + (FTPLatestDirectory.Length()>0) && + (FTPLatestFilename.Length()>0)) + { + currentEnabled=true; + } + if (secondaryLatestFilename.Length()==0) + { + secondaryLatestFilename=FTPSecondaryLatestFilename; + } + if ((secondaryLatestDirectory.Length()>0) && + (secondaryLatestFilename.Length()>0) && + (FTPSecondaryLatestDirectory.Length()>0) && + (FTPSecondaryLatestFilename.Length()>0)) + { + secondaryCurrentEnabled=true; + } + + if ((!archiveEnabled)&&(!currentEnabled)&& + (!secondaryArchiveEnabled)&&(!secondaryCurrentEnabled)) + { + // We have FTP enabled but no logfile downloading enabled + STATSGEN_DEBUG(DEBUG_ALWAYS,"FTP Download enabled, but no directory details"); + msg.Printf("FTP Enabled but no directories and/or filenames setup for this server.Latest Directory=[%s], Filename=[%s], FTP Directory [%s], FTP Latest Filename [%s]", + latestDirectory.GetData(), + latestFilename.GetData(), + FTPLatestDirectory.GetData(), + FTPLatestFilename.GetData()); + progress->LogError(msg,SeverityError); + } + } + if ((archiveEnabled)||(currentEnabled)|| + (secondaryArchiveEnabled)||(secondaryCurrentEnabled)) + { + msg="Getting Directory Listing"; + progress->SetStatus(msg); + serverID="Server"+ID; + RemoteMachine remoteMachine(serverID); + if (archiveEnabled) + { + wxString wildCard; + + wildCard=WildCardFormatToWildCard(FTPArchiveWildcard); + retVal=remoteMachine.GetRemoteDirectoryListing( + FTPArchiveDirectory, + wildCard, + archiveFiles); + if (retVal) + { + fileCount=archiveFiles.GetCount(); + for (fileIndex=0;fileIndexLogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + } + if (currentEnabled) + { + retVal=remoteMachine.GetRemoteDirectoryListing( + FTPLatestDirectory, + FTPLatestFilename, + currentFiles); + if (retVal) + { + fileCount=currentFiles.GetCount(); + for (fileIndex=0;fileIndexLogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + if (currentFiles.GetCount()==0) + { + if (FTPLatestFilename.Length()>0) + { + currentFiles.Add(FTPLatestFilename); + } + } + } + if (secondaryArchiveEnabled) + { + retVal=remoteMachine.GetRemoteDirectoryListing( + FTPSecondaryArchiveDirectory, + FTPSecondaryArchiveWildcard, + secondaryArchiveFiles); + if (retVal) + { + fileCount=secondaryArchiveFiles.GetCount(); + for (fileIndex=0;fileIndexLogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + } + if (secondaryCurrentEnabled) + { + retVal=remoteMachine.GetRemoteDirectoryListing( + FTPSecondaryLatestDirectory, + FTPSecondaryLatestFilename, + secondaryCurrentFiles); + if (retVal) + { + fileCount=secondaryCurrentFiles.GetCount(); + for (fileIndex=0;fileIndexLogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + } + if (secondaryCurrentFiles.GetCount()==0) + { + if (FTPSecondaryLatestFilename.Length()>0) + { + secondaryCurrentFiles.Add(FTPSecondaryLatestFilename); + } + } + } + progress->Initiate(totalFileSize, + " kb", + 1024, + "kb", + 1024); + fileCount=archiveFiles.GetCount(); + //progress->SetStatus(msg); + for (fileIndex=0;fileIndexSetOffset(progress->CurrentValue()); + remoteMachine.GetRemoteFileRestart(FTPArchiveDirectory, + remoteFilename, + archiveDirectory, + restartDownload, + maxLogfileSize); + } + fileCount=currentFiles.GetCount(); + for (fileIndex=0;fileIndexSetOffset(progress->CurrentValue()); + remoteMachine.GetRemoteFileRestart(FTPLatestDirectory, + remoteFilename, + latestDirectory, + restartDownload, + maxLogfileSize); + } + fileCount=secondaryArchiveFiles.GetCount(); + for (fileIndex=0;fileIndexSetOffset(progress->CurrentValue()); + remoteMachine.GetRemoteFileRestart(FTPSecondaryArchiveDirectory, + remoteFilename, + secondaryArchiveDirectory, + restartDownload, + maxLogfileSize); + } + fileCount=secondaryCurrentFiles.GetCount(); + for (fileIndex=0;fileIndexSetOffset(progress->CurrentValue()); + remoteMachine.GetRemoteFileRestart(FTPSecondaryLatestDirectory, + remoteFilename, + secondaryLatestDirectory, + restartDownload, + maxLogfileSize); + } + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"FTP Download not enabled"); + msg="Transfer Not Enabled"; + progress->LogError(msg,SeverityCaution); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + + +bool Server::FindLogfiles() +{ + // Find all the logfiles identified using the archive and latest directories / wildcards + wxArrayString archiveFiles; + wxArrayString latestFiles; + wxArrayString secondaryArchiveFiles; + wxArrayString secondaryLatestFiles; + wxString msg; + int count; + int secondaryCount; + int index; + wxString filename; + bool retVal=true; + + STATSGEN_DEBUG_FUNCTION_START("Server","FindLogfiles") + + if (serverType.CmpNoCase(SERVER_TYPE_QUAKEWARS)==0) + { + // Quake Wars is a pain in the arse with it's secondary "objective" based + // logfile - what a bunch of cocks id are for doing this + if ((secondaryArchiveDirectory.Length()>0) && + (secondaryArchiveWildcard.Length()>0)) + { + wxString wildCard; + + wildCard=WildCardFormatToWildCard(secondaryArchiveWildcard); + STATSGEN_DEBUG_CODE(msg.Printf("Secondary Archive Enabled for directory [%s] wildcard [%s]", + secondaryArchiveDirectory.GetData(), + wildCard.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + if (wxDir::Exists(secondaryArchiveDirectory)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Getting Secondary Archive File List") + wxDir::GetAllFiles(secondaryArchiveDirectory, + &secondaryArchiveFiles, + wildCard, + wxDIR_FILES); + } + else + { + // Archiving enabled - but directory does not exist + retVal=false; + msg.Printf("Secondary Archive Directory [%s] does not exist",secondaryArchiveDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + SortFiles(secondaryArchiveFiles,secondaryArchiveWildcard); + } + else + { + // Archive directory access disabled - this is ok + STATSGEN_DEBUG(DEBUG_ALWAYS,"Secondary Archive directory access disabled") + retVal=true; + } + if ((secondaryLatestDirectory.Length()>0) && + (secondaryLatestFilename.Length()>0)) + { + STATSGEN_DEBUG_CODE(msg.Printf("Secondary Latest Enabled for directory [%s] wildcard [%s]", + secondaryLatestDirectory.GetData(), + secondaryLatestFilename.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (wxDir::Exists(secondaryLatestDirectory)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Getting Secondary Latest File List"); + wxDir::GetAllFiles(secondaryLatestDirectory, + &secondaryLatestFiles, + secondaryLatestFilename, + wxDIR_FILES); + } + else + { + // latest directory enabled but directory does not exist + retVal=false; + msg.Printf("Secondary Latest Directory [%s] does not exist",secondaryLatestDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else + { + retVal=true; + STATSGEN_DEBUG(DEBUG_ALWAYS,"Latest directory access disabled"); + } + } + + if ((archiveDirectory.Length()>0) && + (archiveWildcard.Length()>0)) + { + wxString wildCard; + wildCard=WildCardFormatToWildCard(archiveWildcard); + STATSGEN_DEBUG_CODE(msg.Printf("Archive Enabled for directory [%s] wildcard [%s]", + archiveDirectory.GetData(), + wildCard.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + if (wxDir::Exists(archiveDirectory)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Getting Archive File List") + wxDir::GetAllFiles(archiveDirectory, + &archiveFiles, + wildCard, + wxDIR_FILES); + } + else + { + // Archiving enabled - but directory does not exist + retVal=false; + msg.Printf("Archive Directory [%s] does not exist",archiveDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + SortFiles(archiveFiles,archiveWildcard); + } + else + { + // Archive directory access disabled - this is ok + STATSGEN_DEBUG(DEBUG_ALWAYS,"Archive directory access disabled") + retVal=true; + } + if (retVal) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"After Archive we are ok") + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"After Archive we are not ok") + } + if ((latestDirectory.Length()>0) && + (latestFilename.Length()>0)) + { + STATSGEN_DEBUG_CODE(msg.Printf("latest Enabled for directory [%s] wildcard [%s]", + latestDirectory.GetData(), + latestFilename.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + if (wxDir::Exists(latestDirectory)) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Getting Latest File List"); + wxDir::GetAllFiles(latestDirectory, + &latestFiles, + latestFilename, + wxDIR_FILES); + } + else + { + // latest directory enabled but directory does not exist + retVal=false; + msg.Printf("Latest Directory [%s] does not exist",latestDirectory.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else + { + retVal=true; + STATSGEN_DEBUG(DEBUG_ALWAYS,"Latest directory access disabled"); + } + + logFilenames.Clear(); + secondaryLogFilenames.Clear(); + + if (retVal) + { + count=archiveFiles.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("Archive Files Found = %d\n",count);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + for (index=0;indexLogError(msg,SeverityError); + } + } +*/ + for (index=0;indexRetrieveLastRoundPositions(&lastRoundEndedAt, + &secondaryLastRoundEndedAt); + delete (logFiles); + logFiles=NULL; + } + + if (serverType.Cmp("QUAKEWARS")==0) + { + quakeWarsLogFile=new QuakeWarsLogFile(); + quakeWarsLogFile->Initiate(serverType,logFilenames,secondaryLogFilenames); + logFiles=quakeWarsLogFile; + } + else + { + standardLogFile=new LogFile(); + standardLogFile->Initiate(serverType,logFilenames); + logFiles=standardLogFile; + standardLogFile->FakeTeamIDs(fakeTeamIDs); + } + logFiles->SetLastRoundPositions(lastRoundEndedAt, + secondaryLastRoundEndedAt); + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +long Server::LogfileSize() +{ + return (logFiles->Size()); +} + +bool Server::ProcessLogFiles(int serverIndex) +{ + bool retVal=true; + + STATSGEN_DEBUG_FUNCTION_START("Server","ProcessLogFiles") + + logfileVariableKeys.Clear(); + logfileVariableValues.Clear(); + logfilesSize=logFiles->Size(); + progress->Initiate( + logfilesSize, + " kb", + 1024, + "kb", + 1024); + logFiles->Process(this,serverIndex,maxLogfileSize); + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool Server::DownloadBanFiles() +{ + bool retVal=true; + wxString serverID; + wxString msg; + int banFilesIndex; + wxString remoteDirectory; + wxString remoteFilename; + wxString localDirectory; + wxString thisBanType; + long currentProgress; + wxArrayString remoteFiles; + + if (FTPEnabled) + { + serverID="Server"+ID; + RemoteMachine remoteMachine(serverID); + for (banFilesIndex=1;banFilesIndex<3;banFilesIndex++) + { + switch (banFilesIndex) + { + case 1: + remoteDirectory=FTPBanFile1Directory; + remoteFilename=FTPBanFile1Filename; + thisBanType=banFile1Type; + localDirectory=ban1Directory; + break; + case 2: + remoteDirectory=FTPBanFile2Directory; + remoteFilename=FTPBanFile2Filename; + thisBanType=banFile2Type; + localDirectory=ban2Directory; + break; + } + if ((remoteDirectory.Length()>0) && + (remoteFilename.Length()>0) && + (localDirectory.Length()>0)) + { + currentProgress=progress->CurrentValue(); + // For some reason i have to do a directory + // listing otherwise connection can fail + remoteMachine.MaxErrorSeverity(SeverityOK); + remoteMachine.GetRemoteDirectoryListing( + remoteDirectory, + remoteFilename, + remoteFiles); + remoteMachine.MaxErrorSeverity(SeverityError); + remoteMachine.GetRemoteFile(remoteDirectory, + remoteFilename, + localDirectory); + progress->Update(currentProgress); + + // Create a ban file object based upon the ban type + } + } + } + + return (retVal); +} + +bool Server::ProcessBanFiles() +{ + bool retVal=true; + wxString msg; + int banFilesIndex; + wxString remoteFilename; + wxString localDirectory; + wxString thisBanType; + //BanFile *banFile; + + for (banFilesIndex=1;banFilesIndex<3;banFilesIndex++) + { + switch (banFilesIndex) + { + case 1: + remoteFilename=FTPBanFile1Filename; + thisBanType=banFile1Type; + localDirectory=ban1Directory; + break; + case 2: + remoteFilename=FTPBanFile2Filename; + thisBanType=banFile2Type; + localDirectory=ban2Directory; + break; + } + if ((remoteFilename.Length()>0) && + (localDirectory.Length()>0)) + { + if (thisBanType.Cmp("COD")==0) + { + wxFileName filename; + filename.AssignDir(localDirectory); + filename.SetFullName(remoteFilename); + + CODBanFile banfile(filename); + + banfile.AddToDropList(); + } + if (thisBanType.Cmp("PUNKBUSTER")==0) + { + wxFileName filename; + filename.AssignDir(localDirectory); + filename.SetFullName(remoteFilename); + + PunkbusterBanFile banfile(filename); + + banfile.AddToDropList(); + } + } + } + + return (retVal); +} + +void Server::StartFromBeginning() +{ + logFiles->StartFromBeginning(); +} + +void Server::InitiateMessageCentre() +{ + messageCentre.SetID(ID); + messageCentre.Initiate(); +} + +void Server::SendMessage() +{ + messageCentre.SendMessage(); +} + +void Server::AddVariable(wxString &variable,wxString &value) +{ + int variableCount; + int variableIndex; + wxString key; + + variableCount=logfileVariableKeys.GetCount(); + for (variableIndex=0;variableIndex0) + { + // if we have variables to process then delete any existing + // ones first + SQL.Printf("delete from %s where serveridx=%d", + Server::SQLVariableTableName().GetData(), + serverIndex); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + } + for (variableIndex=0;variableIndexRetrieveLastRoundPositions(&primaryPosition,&secondaryPosition); + SQL.Printf("insert into %s " + "(serverid, primaryposition, secondaryposition) " + "values ('%s','%ld','%ld')", + Server::SQLProgressTableName().GetData(), + StatsgenDatabase::SafeForInsert(ID).GetData(), + primaryPosition, + secondaryPosition); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + + } +} + +void Server::AdjustLogfilePosition() +{ + TemplateOpenQuery query; + wxString sql; + long primaryPosition; + long secondaryPosition; + wxString fieldValue; + wxString property; + + primaryPosition=0; + secondaryPosition=0; + sql.Printf( + "select primaryposition,secondaryposition from %s where serverid=\'%s\' limit 1", + SQLProgressTableName().GetData(), + StatsgenDatabase::SafeForInsert(ID).GetData()); + query.Initiate(sql,globalStatistics.statsgenDatabase.DBHandle()); + if (query.NextRow()) + { + property="primaryposition"; + fieldValue=query.RetrieveProperty(property); + primaryPosition=atol(fieldValue.GetData()); + + property="secondaryposition"; + fieldValue=query.RetrieveProperty(property); + secondaryPosition=atol(fieldValue.GetData()); + } + + if (logFiles!=NULL) + { + logFiles->SetLastRoundPositions(primaryPosition,secondaryPosition); + } +} + +wxString Server::WildCardFormatToWildCard(wxString &wildCardFormat) +{ + wxString retVal; + + retVal=wildCardFormat; + + // Wild Card Format Codes are surrounded by $$ symbols + // DAY = 1-31 + // 0DAY = 01-31 + // MONTH = 1 - 12 + // 0MONTH = 01 - 12 + // YEAR = 2000 - 2999 + // HOUR = 0 - 23 + // 0HOUR = 00 - 23 + // MINUTE = 0 - 59 + // 0MINUTE = 00 - 59 + // SECOND = 0 - 59 + // 0SECOND = 00 - 59 + retVal.Replace("$$DAY$$","*"); + retVal.Replace("$$0DAY$$","*"); + retVal.Replace("$$MONTH$$","*"); + retVal.Replace("$$0MONTH$$","*"); + retVal.Replace("$$YEAR$$","*"); + retVal.Replace("$$HOUR$$","*"); + retVal.Replace("$$0HOUR$$","*"); + retVal.Replace("$$MINUTE$$","*"); + retVal.Replace("$$0MINUTE$$","*"); + retVal.Replace("$$SECOND$$","*"); + retVal.Replace("$$0SECOND$$","*"); + + return (retVal); +} + +void Server::SortFiles(wxArrayString &filenameList,wxString &wildCard) +{ + // We have a wild card - we need to sort the file based upon any + // Date components + int filenameCount; + int filenameIndex; + wxString filename; + + STATSGEN_DEBUG_FUNCTION_START("Server","SortFiles") + + STATSGEN_DEBUG(DEBUG_ALWAYS,wildCard) + filenameCount=filenameList.GetCount(); + STATSGEN_DEBUG(DEBUG_ALWAYS,"Before Sort") + for (filenameIndex=0;filenameIndexLogError(msg,SeverityCaution); + dateUsed=false; + } + else + { + int matchIndex; + regularExp.Matches(first); + for (matchIndex=0;matchIndexLogError(msg,SeverityCaution); + dateUsed=false; + } + else + { + wxDateTime firstDate; + wxDateTime secondDate; + wxString firstValueStr; + wxString secondValueStr; + int firstValue; + int secondValue; + int positionIndex; + int position; + + for (positionIndex=0; + positionIndexLogError(msg,SeverityCaution); + dateUsed=false; + } + } + if (!dateUsed) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"Date Not Used") + retVal=first.Cmp(second); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +int Server::CompareInts(int *first,int *second) +{ + int retVal=0; + + if ((*first) < (*second)) + { + retVal=-1; + } + if ((*first) > (*second)) + { + retVal=+1; + } + + return (retVal); +} diff --git a/Server.h b/Server.h new file mode 100644 index 0000000..e008543 --- /dev/null +++ b/Server.h @@ -0,0 +1,150 @@ +#ifndef __SERVER +#define __SERVER + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes +#include "LogFile.h" +#include "MessageCentre.h" + +class Server; +class LogFile; + +#define SERVER_TYPE_COD1 "COD1" +#define SERVER_TYPE_COD2 "COD2" +#define SERVER_TYPE_COD4 "COD4" +#define SERVER_TYPE_COD5 "COD5" +#define SERVER_TYPE_MOHAA "MOHAA" +#define SERVER_TYPE_QUAKEWARS "QUAKEWARS" +#define SERVER_TYPE_WOLFENSTEIN "WOLFENSTEIN" + +#define SERVER_TYPE_NAME_COD1 "Call Of Duty 1" +#define SERVER_TYPE_NAME_COD2 "Call Of Duty 2" +#define SERVER_TYPE_NAME_COD4 "Call Of Duty 4" +#define SERVER_TYPE_NAME_COD5 "Call Of Duty 5" +#define SERVER_TYPE_NAME_MOHAA "Medal Of Honour" +#define SERVER_TYPE_NAME_QUAKEWARS "Enemy Territory: Quake Wars" +#define SERVER_TYPE_NAME_WOLFENSTEIN "RTCW / Wolfenstein ET" + +#define SERVER_TYPE_COUNT 7 + +#define STAT_TYPE_CODE_ACTION "action" +#define STAT_TYPE_CODE_LOCATION "location" +#define STAT_TYPE_CODE_WEAPON "weapon" +#define STAT_TYPE_CODE_MAP "map" +#define STAT_TYPE_CODE_TEAM "team" +#define STAT_TYPE_CODE_CLASS "class" +#define STAT_TYPE_CODE_GAMETYPE "gametype" + +#define STAT_TYPE_NAME_ACTION "Action" +#define STAT_TYPE_NAME_LOCATION "Location" +#define STAT_TYPE_NAME_WEAPON "Weapon" +#define STAT_TYPE_NAME_MAP "Map" +#define STAT_TYPE_NAME_TEAM "Team" +#define STAT_TYPE_NAME_CLASS "Class" +#define STAT_TYPE_NAME_GAMETYPE "Game Type" + +#define SKILL_TYPE_COUNT 3 +#define IMAGE_TYPE_COUNT 7 + +extern char *ImageTypeCodes[]; +extern char *ImageTypeNames[]; +extern char *SkillTypeCodes[]; +extern char *SkillTypeNames[]; +extern char *ServerTypeCodes[]; +extern char *ServerTypeNames[]; + +#define SERVER_BAN_TYPE_PB "PUNKBUSTER" +#define SERVER_BAN_TYPE_COD "COD" + +WX_DECLARE_OBJARRAY(Server,ArrayOfServer); +class Server +{ + public: + Server(); + virtual ~Server(); + + void SetID(wxString &IDIn); + bool Initiate(); + bool FindLogfiles(); + bool CreateLogFiles(); + bool ProcessLogFiles(int serverIndex); + bool ProcessBanFiles(); + bool DownloadFiles(); + bool DownloadBanFiles(); + void StartFromBeginning(); + void InitiateMessageCentre(); + void SendMessage(); + void AddVariable(wxString &variable,wxString &value); + void WriteToDatabase(int serverIndex); + void AdjustLogfilePosition(); + static wxString SQLCreateTable(); + static wxString SQLCreateVariableTable(); + static wxString SQLCreateProgressTable(); + static wxString SQLTableName(); + static wxString SQLVariableTableName(); + static wxString SQLProgressTableName(); + wxString WildCardFormatToWildCard(wxString &wildCardFormat); + void SortFiles(wxArrayString &filenameList,wxString &wildCard); + static int CompareFilenames(const wxString &first,const wxString &second); + static int CompareInts(int *first,int *second); + long LogfileSize(); + + public: + bool restartDownload; + bool fakeTeamIDs; + wxString ID; + wxArrayString logFilenames; + wxArrayString secondaryLogFilenames; + //ArrayOfLogFile logFiles; + LogFile *logFiles; + + MessageCentre messageCentre; + + + wxString archiveDirectory; + wxString archiveWildcard; + wxString latestDirectory; + wxString latestFilename; + + wxString secondaryArchiveDirectory; + wxString secondaryArchiveWildcard; + wxString secondaryLatestDirectory; + wxString secondaryLatestFilename; + wxString serverType; + + int gamePort; + wxString gameIP; + + bool FTPEnabled; + wxString FTPArchiveDirectory; + wxString FTPArchiveWildcard; + wxString FTPLatestDirectory; + wxString FTPLatestFilename; + wxString FTPSecondaryArchiveDirectory; + wxString FTPSecondaryArchiveWildcard; + wxString FTPSecondaryLatestDirectory; + wxString FTPSecondaryLatestFilename; + + wxString FTPBanFile1Directory; + wxString FTPBanFile1Filename; + wxString banFile1Type; + wxString ban1Directory; + + wxString FTPBanFile2Directory; + wxString FTPBanFile2Filename; + wxString banFile2Type; + wxString ban2Directory; + + wxArrayString logfileVariableKeys; + wxArrayString logfileVariableValues; + long logfilesSize; + long maxLogfileSize; + +}; + + +#endif diff --git a/ServerTypePanel.cpp b/ServerTypePanel.cpp new file mode 100644 index 0000000..0a10a38 --- /dev/null +++ b/ServerTypePanel.cpp @@ -0,0 +1,73 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "ServerTypePanel.h" +#include "Server.h" +#include "GlobalStatistics.h" +#include "WindowIDs.h" + +wxString ServerTypePanel::GetLabel() +{ + wxString label="Server Type"; + return (label); +} + +wxString ServerTypePanel::AllName() +{ + wxString all="All Server Types"; + + return (all); +} + +wxString ServerTypePanel::AllCode() +{ + wxString all=""; + + return (all); +} + +void ServerTypePanel::DropDownEntries(wxArrayString &entries, + wxString &defaultSelection) +{ + int index; + wxString serverName; + int count; + + entries.Clear(); + defaultSelection=""; + + count=SERVER_TYPE_COUNT; + for (index=0;index +#include +#include + +// Statsgen Includes +#include "BoxedDropDown.h" + +class ServerTypePanel : public BoxedDropDown +{ + protected: + virtual wxString GetLabel(); + virtual void DropDownEntries(wxArrayString &entries, + wxString &defaultSelection); + virtual wxString AllCode(); + virtual wxString AllName(); + virtual wxString FindCodeFromName(wxString &name); + private: +}; + + +#endif diff --git a/SkillTypePanel.cpp b/SkillTypePanel.cpp new file mode 100644 index 0000000..fdfa6d6 --- /dev/null +++ b/SkillTypePanel.cpp @@ -0,0 +1,74 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "SkillTypePanel.h" +#include "Server.h" +#include "GlobalStatistics.h" +#include "WindowIDs.h" + +wxString SkillTypePanel::GetLabel() +{ + wxString label="Skill Type"; + return (label); +} + +wxString SkillTypePanel::AllName() +{ + wxString all="All Skill Types"; + + return (all); +} + +wxString SkillTypePanel::AllCode() +{ + wxString all=""; + + return (all); +} + +wxString SkillTypePanel::FindCodeFromName(wxString &name) +{ + int count; + int index; + wxString foundName; + wxString retVal=""; + + count=SKILL_TYPE_COUNT; + + for (index=0;index +#include +#include + +// Statsgen Includes +#include "BoxedDropDown.h" + +class SkillTypePanel : public BoxedDropDown +{ + protected: + virtual wxString GetLabel(); + virtual void DropDownEntries(wxArrayString &entries, + wxString &defaultSelection); + virtual wxString AllCode(); + virtual wxString AllName(); + virtual wxString FindCodeFromName(wxString &name); + private: +}; + + +#endif diff --git a/SpeechData.cpp b/SpeechData.cpp new file mode 100644 index 0000000..2fb66db --- /dev/null +++ b/SpeechData.cpp @@ -0,0 +1,61 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "SpeechData.h" +#include "GlobalStatistics.h" + +SpeechData::SpeechData() +{ +} + +SpeechData::~SpeechData() +{ +} + +wxString SpeechData::SQLTableName() +{ + wxString retVal="speechdata"; + + return (retVal); +} + +wxString SpeechData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "speechidx integer," + "playerindex integer," + "%s" + ")", + SQLTableName().GetData(), + StatsgenDatabase::StringFieldDefinition("speech","speech",FIELD_WIDTH_SPEECH).GetData()); + + return SQL; +} + +bool SpeechData::WriteToDatabase(int roundIndex,int itemIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + + SQL.Printf("insert into %s" + "(roundindex,speechidx,playerindex,speech)" + "values" + "('%d','%d','%d','%s')", + SQLTableName().GetData(), + roundIndex, + itemIndex, + player.actualPlayerIndex, + StatsgenDatabase::SafeForInsert(speech).GetData()); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} diff --git a/SpeechData.h b/SpeechData.h new file mode 100644 index 0000000..0a1c907 --- /dev/null +++ b/SpeechData.h @@ -0,0 +1,31 @@ +#ifndef __SPEECHDATA +#define __SPEECHDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class SpeechData; + +WX_DECLARE_OBJARRAY(SpeechData,ArrayOfSpeechData); +class SpeechData +{ + public: + SpeechData(); + virtual ~SpeechData(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int itemIndex); + + + wxDateTime speechTime; + int playerIndex; + wxString speech; + +}; + + +#endif diff --git a/StaticFunctions.cpp b/StaticFunctions.cpp new file mode 100644 index 0000000..0352a63 --- /dev/null +++ b/StaticFunctions.cpp @@ -0,0 +1,354 @@ +// wxWindows includes +#include +#include + +// Statsgen includes +#include "StaticFunctions.h" +#include "GlobalStatistics.h" + +void ExportTemplateQuick(wxString &directory); +void ExportTemplateFile(wxString &directory,wxArrayString &fileLines,char *filename); +wxFileName BaseDirectoryFileName(const char *filename) +{ + wxFileName baseDirectory(wxGetApp().argv[0]); + wxFileName retVal; + wxString filenameStr; + + filenameStr=filename; + baseDirectory.MakeAbsolute(); + retVal=baseDirectory; + retVal.SetFullName(filenameStr); + + return (retVal); +} + +bool NeedsFirstTimeRun() +{ + wxString configKey; + wxString configValue; + + configKey="/General/FirstTimeRun"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + return (configValue.CmpNoCase("n")!=0); +} + +bool FirstTimeRun() +{ + bool retVal=false; + wxFileName baseDirectory(wxGetApp().argv[0]); + wxFileName htmlDirectory; + wxFileName templateDirectory; + wxFileName playercacheFilename; + wxFileName aliasFilename; + wxFileName droplistFilename; + wxFileName fullTemplateFileName; + wxString fullTemplateName="full.template"; + wxString droplistname="droplist.dat"; + wxString aliasname="aliaslist.dat"; + wxString playercachename="playercache.dat"; + wxString configKey; + wxString configValue; + wxString directory; + + baseDirectory.MakeAbsolute(); + STATSGEN_DEBUG_FUNCTION_START("","FirstTimeRun") + //baseDirectory=baseDirectory.GetPath(); + htmlDirectory=baseDirectory; + templateDirectory=baseDirectory; + playercacheFilename=baseDirectory; + aliasFilename=baseDirectory; + droplistFilename=baseDirectory; + + htmlDirectory.AppendDir("html"); + templateDirectory.AppendDir("templates"); + fullTemplateFileName=templateDirectory; + fullTemplateFileName.SetFullName(fullTemplateName); + droplistFilename.SetFullName(droplistname); + aliasFilename.SetFullName(aliasname); + playercacheFilename.SetFullName(playercachename); + + configKey="/General/FirstTimeRun"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + if (configValue.CmpNoCase("n")!=0) + { + retVal=true; + // First time run + // Create basic directories + #ifdef _LINUX + mkdir(htmlDirectory.GetPath(),0777); + mkdir(templateDirectory.GetPath(),0777); + #else + wxMkDir(htmlDirectory.GetPath()); + wxMkDir(templateDirectory.GetPath()); + #endif + // Create base config entries + configValue="n"; + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/General/playercache"; + configValue=playercacheFilename.GetFullPath(); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/General/aliaslist"; + configValue=aliasFilename.GetFullPath(); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/General/LocalOutput"; + configValue=htmlDirectory.GetPath(); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/General/DropList"; + configValue=droplistFilename.GetFullPath(); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + configKey="/Template/FullRun"; + configValue=fullTemplateFileName.GetFullPath(); + globalStatistics.configData.WriteTextValue(configKey,configValue); + + directory=fullTemplateFileName.GetPath(); + ExportTemplateFull(directory); + + globalStatistics.configData.CommitChanges(); + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +void SafeString(wxString &string) +{ + int index; + int length; + wxString workString; + + length=string.Length(); + for (index=0;index='A')&&(string[index]<='Z') || + (string[index]>='a')&&(string[index]<='z') || + (string[index]>='0')&&(string[index]<='9') + ) + { + workString+=string[index]; + } + else + { + workString+="_"; + } + } + string=workString.Lower(); + /* + string.Replace("*","_"); + string.Replace(":","_"); + string.Replace(".","_"); + string.Replace(" ","_"); + string.Replace("[","_"); + string.Replace("]","_"); + string.Replace("=","_"); + */ +} + +wxString DecolouriseName(wxString &name) +{ + wxString decolourisedName=name; + + decolourisedName.Replace("^0",""); + decolourisedName.Replace("^1",""); + decolourisedName.Replace("^2",""); + decolourisedName.Replace("^3",""); + decolourisedName.Replace("^4",""); + decolourisedName.Replace("^5",""); + decolourisedName.Replace("^6",""); + decolourisedName.Replace("^7",""); + decolourisedName.Replace("^8",""); + decolourisedName.Replace("^9",""); + + return (decolourisedName); +} + +void ExportTemplateFile(wxString &directory,wxArrayString &fileLines,char *filename) +{ + wxString filenameStr; + wxFileName templateFilename=wxFileName::DirName(directory); + wxTextFile templateFile; + + + filenameStr=filename; + templateFilename.SetFullName(filenameStr); + + if (wxFileExists(templateFilename.GetFullPath())) + { + wxRemoveFile(templateFilename.GetFullPath()); + } + if (templateFile.Create(templateFilename.GetFullPath())) + { + int lineCount; + int lineIndex; + wxString line; + + lineCount=fileLines.GetCount(); + for (lineIndex=0;lineIndex0) + { + ConfigData upgradeConfigFile; + wxFileName upgradeFileName(upgradeFilenameStr); + wxString group; + wxArrayString groups; + int groupCount; + int groupIndex; + wxString description; + wxString recommendation; + wxString answerTypeStr; + wxArrayString choices; + wxString choice; + int choiceIndex; + int answerType; + choices.Clear(); + choice=UPGRADE_CHOICE_DEFAULT;choices.Add(choice); + choice=UPGRADE_CHOICE_DO_NOTHING;choices.Add(choice); + choice=UPGRADE_CHOICE_UPDATE;choices.Add(choice); + choice=UPGRADE_CHOICE_OVERWRITE;choices.Add(choice); + + upgradeConfigFile.Initiate(upgradeFileName); + group="UPGRADELIST"; + upgradeConfigFile.ReadList(group,groups); + groupCount=groups.GetCount(); + choiceIndex=2; + + for (groupIndex=0;groupIndex 0) + { + if ((stringLength % 2) == 0) + { + // string is multiples of 2 chars + for (stringIndex=0;stringIndex= 'a') && (stringChar <='f')) || + ((stringChar >= 'A') && (stringChar <='Z')) + )) + + { + // not a number and not a valid hex digit + retVal=false; + break; + } + } + } + } + else + { + // not multiples of 2 chars + retVal=false; + } + } + else + { + // Zero length + retVal=false; + } + + return (retVal); +} diff --git a/StaticFunctions.h b/StaticFunctions.h new file mode 100644 index 0000000..6f21599 --- /dev/null +++ b/StaticFunctions.h @@ -0,0 +1,28 @@ +#ifndef __STATICFUNCTIONS +#define __STATICFUNCTIONS + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen Includes +#include "StatsgenApp.h" + +#define UPGRADE_CHOICE_DEFAULT "Default" +#define UPGRADE_CHOICE_DO_NOTHING "Do Nothing" +#define UPGRADE_CHOICE_UPDATE "Update" +#define UPGRADE_CHOICE_OVERWRITE "Overwrite" + +bool NeedsFirstTimeRun(); +bool FirstTimeRun(); +wxString DecolouriseName(wxString &name); +void SafeString(wxString &string); +wxFileName BaseDirectoryFileName(const char *filename); +void ExportTemplateFull(wxString &directory); +void UpgradeConfigFile(wxString &upgradeFilenameStr); +bool IsHexString(wxString &stringToCheck); +DECLARE_APP(wxWidgetsApp) + +#endif diff --git a/StatsgenApp.cpp b/StatsgenApp.cpp new file mode 100644 index 0000000..a4fd7d1 --- /dev/null +++ b/StatsgenApp.cpp @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include "StatsgenApp.h" +#include "StatsgenFrame.h" +#include "Progress.h" +#include "ErrorData.h" +#include "StaticFunctions.h" + + +IMPLEMENT_APP(wxWidgetsApp) + +// ============================================================================ +// implementation +// ============================================================================ +wxWidgetsApp::wxWidgetsApp() +{ +} + +wxWidgetsApp::~wxWidgetsApp() +{ +} + +bool wxWidgetsApp::OnInit() +{ + wxImage::AddHandler(new wxGIFHandler); + wxImage::AddHandler(new wxJPEGHandler); + wxString filename; + wxString titleBar; + + filename=wxGetApp().argv[0]; + titleBar.Printf("Statsgen 2: (%s)",filename.GetData()); + wxFileSystem::AddHandler(new wxZipFSHandler); + wxWidgetsFrame *frame = new wxWidgetsFrame(titleBar, + wxPoint(50, 50), wxSize(640, 480)); + + wxHelpControllerHelpProvider *provider=new wxHelpControllerHelpProvider; + wxHelpProvider::Set(provider); + provider->SetHelpController(&frame->GetAdvancedHtmlHelpController()); + frame->Show(TRUE); + + SetTopWindow(frame); + + wxSize itemSize; + int menuWidth; + int menuHeight; + int statusWidth; + int statusHeight; + int progressWidth; + int progressHeight; + int frameWidth; + int frameHeight; + int panelHeight; + int heightOffset; + wxString msg; + + + itemSize=frame->GetMenuBar()->GetSize(); + menuWidth=itemSize.GetWidth(); + menuHeight=itemSize.GetHeight(); + menuHeight=46; + itemSize=frame->GetStatusBar()->GetSize(); + statusWidth=itemSize.GetWidth(); + statusHeight=itemSize.GetHeight(); + + itemSize=progress->GetSize(); + progressWidth=itemSize.GetWidth(); + progressHeight=itemSize.GetHeight(); + + itemSize=frame->GetSize(); + frameWidth=itemSize.GetWidth(); + frameHeight=itemSize.GetHeight(); + + frameWidth=progressWidth; + panelHeight=frameHeight-(statusHeight+menuHeight); + heightOffset=progressHeight-panelHeight; + frameHeight+=heightOffset; + frame->SetSize(frameWidth+10,frameHeight); + + frame->GetAdvancedHtmlHelpController().Initialize(_T("help")); + + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,WINDOW_ID_WIZARD); + + //wxPostEvent(frame,event); + return TRUE; +} + diff --git a/StatsgenApp.h b/StatsgenApp.h new file mode 100644 index 0000000..3a2b8df --- /dev/null +++ b/StatsgenApp.h @@ -0,0 +1,16 @@ +#ifndef __WXWIDGETSAPP_H +#define __WXWIDGETSAPP_H + +#include + +class wxWidgetsApp : public wxApp +{ +public: + wxWidgetsApp(); + virtual ~wxWidgetsApp(); + virtual bool OnInit(); +}; + +DECLARE_APP(wxWidgetsApp) + +#endif //__WXWIDGETSAPP_H diff --git a/StatsgenDatabase.cpp b/StatsgenDatabase.cpp new file mode 100644 index 0000000..d38cb4c --- /dev/null +++ b/StatsgenDatabase.cpp @@ -0,0 +1,1885 @@ +#include + +// wxWindows includes +#include + +// Statsgen includes +#include "ErrorData.h" +#include "StatsgenDatabase.h" +#include "KillData.h" +#include "ActionData.h" +#include "AKAListEntry.h" +#include "Round.h" +#include "TeamWinData.h" +#include "TeamLossData.h" +#include "SpeechData.h" +#include "PlayerInRound.h" +#include "GenericKey.h" +#include "Player.h" +#include "Clan.h" +#include "GlobalStatistics.h" +#include "Progress.h" +#include "TemplateOpenQuery.h" +#include "StaticFunctions.h" + + +StatsgenDatabase::StatsgenDatabase() +{ + wxString configKey; + + sqliteDBHandle=NULL; + roundCount=0; + playerCount=0; + +// configKey="/Database/filename"; +// globalStatistics.configData.ReadTextValue(configKey, +// &databaseFilename, +// ":memory:"); + +} + +StatsgenDatabase::~StatsgenDatabase() +{ + CloseDB(); +} + +void StatsgenDatabase::CreateIndexListTable(const char *tableName) +{ + wxString SQL; + + SQL.Printf("create table %s ( idx integer )",tableName); + SimpleExecute(SQL); +} +void StatsgenDatabase::CreateChangedPlayersTable() +{ + CreateIndexListTable("changedplayers"); +} +void StatsgenDatabase::CreateChangedRoundsTable() +{ + CreateIndexListTable("changedrounds"); +} + +void StatsgenDatabase::EmptyIndexListTable(const char *tableName) +{ + wxString SQL; + + SQL.Printf("delete from %s",tableName); + SimpleExecute(SQL); +} +void StatsgenDatabase::EmptyChangedPlayersTable() +{ + EmptyIndexListTable("changedplayers"); +} +void StatsgenDatabase::EmptyChangedRoundsTable() +{ + EmptyIndexListTable("changedrounds"); +} + +void StatsgenDatabase::WriteIndexListToTable(const char *tableName,wxArrayInt &list) +{ + int listCount; + int listIndex; + int index; + wxString SQL; + wxString statusStr; + bool openCommit=false; + + listCount=list.GetCount(); + for (listIndex=0;listIndexSetStatus(statusStr); + } + index=list.Item(listIndex); + SQL.Printf("insert into %s " + "(idx)" + "values" + "('%d')", + tableName, + index); + SimpleExecute(SQL); + } + if (openCommit) + { + SQL="commit"; + SimpleExecute(SQL); + } +} + +void StatsgenDatabase::WriteChangedPlayersList(wxArrayInt &listOfPlayerIndexes) +{ + WriteIndexListToTable("changedplayers",listOfPlayerIndexes); +} + +void StatsgenDatabase::WriteChangedRoundsList(wxArrayInt &listOfRoundIndexes) +{ + WriteIndexListToTable("changedrounds",listOfRoundIndexes); +} + +void StatsgenDatabase::WriteChangedRoundsList() +{ + wxString sql="insert into changedrounds select roundindex from playerinround where playerindex in (select idx from changedplayers) group by roundindex"; + + SimpleExecute(sql); +} + +bool StatsgenDatabase::CreateGenericKeyTable(char *tableName) +{ + wxString SQL; + wxString errorString; + bool retVal=true; + + SQL=GenericKey::SQLCreateTable(tableName); + SimpleExecute(SQL); + + return retVal; +} + +bool StatsgenDatabase::CloseDB() +{ + if (sqliteDBHandle!=NULL) + { + sqlite3_close(sqliteDBHandle); + sqliteDBHandle=NULL; + } + + return (true); +} + +bool StatsgenDatabase::OpenDB() +{ + wxString msg; + wxString configKey; + bool retVal=true; + int status; + + STATSGEN_DEBUG_FUNCTION_START("StatsgenDatabase","OpenDB") + STATSGEN_DEBUG_CODE(msg.Printf("SQLITE3 Version [%s]",sqlite3_libversion());) + STATSGEN_DEBUG(DEBUG_SOMETIMES,msg) + if (sqliteDBHandle!=NULL) + { + } + else + { + wxFileName dbFilename; + wxString defaultDBFilename; + + dbFilename=BaseDirectoryFileName("statsgen2.db"); + defaultDBFilename=dbFilename.GetFullPath(); + configKey="/Database/filename"; + globalStatistics.configData.ReadTextValue(configKey, + &databaseFilename, + (char *)defaultDBFilename.GetData()); + STATSGEN_DEBUG(DEBUG_SOMETIMES,"Opening DB") + status=sqlite3_open(databaseFilename.GetData(), + &sqliteDBHandle); + if (status!=SQLITE_OK) + { + STATSGEN_DEBUG_CODE(msg.Printf("Opening Database [%s]", sqlite3_errmsg(sqliteDBHandle));) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->LogError(msg,SeverityError); + retVal=false; + } + else + { +// STATSGEN_DEBUG(DEBUG_SOMETIMES,"Opening Database:Success") + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +wxString StatsgenDatabase::Filename() +{ + return(databaseFilename); +} + +void StatsgenDatabase::Create() +{ + wxString errorString; + wxString SQL; + long topValue=22; + long step=0; + static bool alreadyCreated=false; + + progress->Initiate(topValue, + " Steps", + (long)1, + " Steps", + (long)1); + progress->DisableTimeToGo(); + OpenDB(); + progress->Update(step++); + + if (!alreadyCreated) + { + alreadyCreated=true; + CreateChangedPlayersTable(); + progress->Update(step++);progress->SetStatus("Changed Players"); + CreateChangedRoundsTable(); + progress->Update(step++);progress->SetStatus("Changed Rounds"); + // Key Tables (weapons, maps, teams etc) + CreateGenericKeyTable(TABLE_NAME_KEY_ACTION); + progress->Update(step++);progress->SetStatus("Keys:Actions"); + CreateGenericKeyTable(TABLE_NAME_KEY_AMMO); + progress->Update(step++);progress->SetStatus("Keys:Ammo"); + CreateGenericKeyTable(TABLE_NAME_KEY_WEAPON); + progress->Update(step++);progress->SetStatus("Keys:Weapons"); + CreateGenericKeyTable(TABLE_NAME_KEY_MAP); + progress->Update(step++);progress->SetStatus("Keys:Maps"); + CreateGenericKeyTable(TABLE_NAME_KEY_TEAM); + progress->Update(step++);progress->SetStatus("Keys:Teams"); + CreateGenericKeyTable(TABLE_NAME_KEY_CLASS); + progress->Update(step++);progress->SetStatus("Keys:Classes"); + CreateGenericKeyTable(TABLE_NAME_KEY_GAMETYPE); + progress->Update(step++);progress->SetStatus("Keys:Gametypes"); + CreateGenericKeyTable(TABLE_NAME_KEY_LOCATION); + progress->Update(step++);progress->SetStatus("Keys:Locations"); + CreateGenericKeyTable(TABLE_NAME_KEY_XP); + progress->Update(step++);progress->SetStatus("Keys:XP"); + + // Cheaters + globalStatistics.cheaters.CreateDatabase(); + progress->Update(step++);progress->SetStatus("Cheats"); + + // Skill Weights + globalStatistics.skillWeights.CreateDatabase(); + progress->Update(step++);progress->SetStatus("Skill Weights"); + // Score Weights + globalStatistics.scoreWeights.CreateDatabase(); + progress->Update(step++);progress->SetStatus("Score Weights"); + + // Avatars / Player Data + globalStatistics.playerDataAvatars->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Avatars"); + // Avatars / Player Data + globalStatistics.playerDataPicture->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Picture"); + // Avatars / Player Data + globalStatistics.playerDataWebsite->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Website"); + // Avatars / Player Data + globalStatistics.playerDataXfire->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:XFire"); + // Avatars / Player Data + globalStatistics.playerDataClanRole->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Clan Role"); + // Avatars / Player Data + globalStatistics.playerDataRealName->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Real Name"); + // Avatars / Player Data + globalStatistics.playerDataMisc1->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Misc 1"); + // Avatars / Player Data + globalStatistics.playerDataMisc2->CreateDatabaseTable(); + progress->Update(step++);progress->SetStatus("Player Data:Misc 2"); + + // Create progressbar Table + SQL=ProgressPanel::CreateTableSQL(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("progressbar"); + + // Create aka Table + SQL=AKAListEntry::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("AKA List"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("maps"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Maps"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("gametypes"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Game Types"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("weapons"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Weapons"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("locations"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Locations"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("teams"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Teams"); + + // Create killtotals Table + SQL=KillTotal::SQLCreateTable("classes"); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kill Totals:Classes"); + + // Create Server Table + SQL=Server::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Servers"); + + // Create Server Variables Table + SQL=Server::SQLCreateVariableTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Server Variables"); + + // Create Server Variables Table + SQL=Server::SQLCreateProgressTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Server Progress"); + + // Create Clans Table + SQL=Clan::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Clans"); + + // Create Players Table + SQL=Player::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Players"); + + // Create appropriate data tables + SQL=Round::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Rounds"); + + // Create appropriate data tables + SQL=Round::SQLCreateVariableTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Round Variables"); + + SQL=KillData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Kills"); + + SQL=TeamWinData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Team Wins"); + + SQL=TeamLossData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Team Losses"); + + SQL=ActionData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Actions"); + + SQL=SpeechData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Speech"); + + SQL=PlayerInRound::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Players In Rounds"); + + SQL=PlayerInRound::SQLCreateTableAward(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Award Points"); + + SQL=XPPoints::SQLTotalCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Total XP Points"); + + SQL=XPPoints::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("XP Points"); + + SQL=StreakData::SQLCreateTable(); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Streaks"); + + SQL=AwardDefinition::SQLCreateTable(); + SimpleExecute(SQL); + + SQL=AwardDefinition::SQLCreateTableComponent("weaponkill");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("weapondeath");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("weapontk");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("locationkill");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("locationdeath");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("locationtk");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("action");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("misc");SimpleExecute(SQL); + SQL=AwardDefinition::SQLCreateTableComponent("xp");SimpleExecute(SQL); + + progress->Update(step++);progress->SetStatus("Award Definitions"); + + // Miscellaneous Statistics + SQL.Printf("create table miscellaneous " + "(" + "%s," + "%s" + ")", + StringFieldDefinition("statistic","miscstatistic",FIELD_WIDTH_MISC_STATISTIC).GetData(), + StringFieldDefinition("value","miscvalue",FIELD_WIDTH_MISC_VALUE).GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Miscellaneous"); +// CreateIndexes(); +// progress->Update(step++);progress->SetStatus("Indexes"); + CreateViews(); + progress->Update(step++);progress->SetStatus("Views"); + CreateIndexes(); + } +} + +bool StatsgenDatabase::WriteMiscellaneousStatistic(char *statistic,int value) +{ + wxString valueStr; + + valueStr.Printf("%d",value); + return (WriteMiscellaneousStatistic(statistic,valueStr)); +} + +bool StatsgenDatabase::WriteMiscellaneousStatistic(char *statistic,long value) +{ + wxString valueStr; + + valueStr.Printf("%ld",value); + return (WriteMiscellaneousStatistic(statistic,valueStr)); +} +bool StatsgenDatabase::WriteMiscellaneousStatistic(char *statistic,wxString &value) +{ + wxString safeValue; + wxString SQL; + + safeValue=SafeForInsert(value); + + SQL="begin"; + SimpleExecute(SQL); + + SQL.Printf("insert into miscellaneous " + "(statistic,value)" + "values" + "('%s','%s')", + statistic, + safeValue.GetData()); + SimpleExecute(SQL); + + SQL="commit"; + SimpleExecute(SQL); + + return (true); +} + +bool StatsgenDatabase::SimpleExecute(wxString &SQL) +{ + wxString errorString; + bool retVal; + int status; + char *errorMessage; + wxString err; + + + STATSGEN_DEBUG_FUNCTION_START("StatsgenDatabase","SimpleExecute") + // Create appropriate tables + +// StatsgenDebug(SQL); + if (sqliteDBHandle==NULL) + { + retVal=false; + } + else + { + status=sqlite3_exec(sqliteDBHandle, + SQL.GetData(), + NULL, + NULL, + &errorMessage); + if (status!=SQLITE_OK) + { + err=errorMessage; + if (!err.EndsWith(" already exists")) + { + errorString.Printf("ERROR [%s][%s]",SQL.GetData(),errorMessage); + STATSGEN_DEBUG(DEBUG_ALWAYS,errorString) + progress->LogError(errorString,SeverityError); + } + sqlite3_free(errorMessage); + } + else + { +// STATSGEN_DEBUG(DEBUG_RARELY,"SUCCESS") + } + retVal=true; + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +wxString StatsgenDatabase::SafeForInsert(wxString &text) +{ + wxString retVal; + + retVal=text; + + retVal.Replace("'","''"); + + return (retVal); +} + +void StatsgenDatabase::Empty() +{ + wxString errorString; + wxString SQL; + long topValue=20; + long step=0; + + progress->Initiate(topValue, + " Steps", + (long)1, + " Steps", + (long)1); + progress->DisableTimeToGo(); + OpenDB(); + progress->Update(step++);progress->SetStatus("Starting"); + + EmptyChangedPlayersTable(); + progress->Update(step++);progress->SetStatus("Changed Players"); + EmptyChangedRoundsTable(); + progress->Update(step++);progress->SetStatus("Changed Rounds"); + // Key Tables (weapons, maps, teams etc) + EmptyGenericKeyTable(TABLE_NAME_KEY_ACTION); + progress->Update(step++);progress->SetStatus("Keys:Actions"); + EmptyGenericKeyTable(TABLE_NAME_KEY_AMMO); + progress->Update(step++);progress->SetStatus("Keys:Ammo"); + EmptyGenericKeyTable(TABLE_NAME_KEY_WEAPON); + progress->Update(step++);progress->SetStatus("Keys:Weapons"); + EmptyGenericKeyTable(TABLE_NAME_KEY_MAP); + progress->Update(step++);progress->SetStatus("Keys:Maps"); + EmptyGenericKeyTable(TABLE_NAME_KEY_TEAM); + progress->Update(step++);progress->SetStatus("Keys:Teams"); + EmptyGenericKeyTable(TABLE_NAME_KEY_CLASS); + progress->Update(step++);progress->SetStatus("Keys:Classes"); + EmptyGenericKeyTable(TABLE_NAME_KEY_GAMETYPE); + progress->Update(step++);progress->SetStatus("Keys:Game Types"); + EmptyGenericKeyTable(TABLE_NAME_KEY_LOCATION); + progress->Update(step++);progress->SetStatus("Keys:Locations"); + EmptyGenericKeyTable(TABLE_NAME_KEY_XP); + progress->Update(step++);progress->SetStatus("Keys:XP"); + + // Empty Total XP + // SQL.Printf("delete from %s",XPPoints::SQLTotalTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Total XP List"); + + // Empty XP + // SQL.Printf("delete from %s",XPPoints::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("XP List"); + + // Empty Cheaters + // SQL.Printf("delete from %s",Cheaters::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Cheaters List"); + + // Empty AKA + // SQL.Printf("delete from %s",AKAListEntry::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("AKA List"); + + // Empty Skill Weights + globalStatistics.skillWeights.EmptyDatabase(); + progress->Update(step++);progress->SetStatus("Skill Weights"); + + // Empty Score Weights + globalStatistics.scoreWeights.EmptyDatabase(); + progress->Update(step++);progress->SetStatus("Score Weights"); + + // Empty Avatars / Player Data + SQL.Printf("delete from %s",globalStatistics.playerDataAvatars->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Avatars"); + + SQL.Printf("delete from %s",globalStatistics.playerDataPicture->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Pictures"); + + SQL.Printf("delete from %s",globalStatistics.playerDataWebsite->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Website"); + + SQL.Printf("delete from %s",globalStatistics.playerDataXfire->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:XFire"); + + SQL.Printf("delete from %s",globalStatistics.playerDataClanRole->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Clan Roles"); + + SQL.Printf("delete from %s",globalStatistics.playerDataRealName->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Real Names"); + + SQL.Printf("delete from %s",globalStatistics.playerDataMisc1->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Misc 1"); + + SQL.Printf("delete from %s",globalStatistics.playerDataMisc2->SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Player Data:Misc 2"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("maps").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Maps"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("gametypes").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Game Types"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("weapons").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Weapons"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("locations").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Locations"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("teams").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Teams"); + + // Empty kill totals + // SQL.Printf("delete from %s",KillTotal::SQLTableName("classes").GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kill Totals:Classes"); + + // Empty Server Variables Table + // SQL.Printf("delete from %s",Server::SQLVariableTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Server Variables"); + + // Empty Server Table + SQL.Printf("delete from %s",Server::SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Servers"); + + // Create Clans Table + SQL.Printf("delete from %s",Clan::SQLTableName().GetData()); + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Clans"); + + // Create Players Table + // SQL.Printf("delete from %s",Player::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Players"); + + // Create appropriate data tables + // SQL.Printf("delete from %s",Round::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Rounds"); + + // SQL.Printf("delete from %s",Round::SQLVariableTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Round Variables"); + + // SQL.Printf("delete from %s",KillData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Kills"); + + // SQL.Printf("delete from %s",TeamWinData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Team Wins"); + + // SQL.Printf("delete from %s",TeamLossData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Team Losses"); + + // SQL.Printf("delete from %s",ActionData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Actions"); + + // SQL.Printf("delete from %s",SpeechData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Speech"); + + // SQL.Printf("delete from %s",PlayerInRound::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Players In Rounds"); + + // SQL.Printf("delete from %s",PlayerInRound::SQLTableNameAward().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Award Points"); + + // SQL.Printf("delete from %s",StreakData::SQLTableName().GetData()); + // SimpleExecute(SQL); + // progress->Update(step++);progress->SetStatus("Streaks"); + + SQL.Printf("delete from %s",AwardDefinition::SQLTableName().GetData()); + SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("weaponkill").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("weapondeath").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("weapontk").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("locationkill").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("locationdeath").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("locationtk").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("action").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("misc").GetData());SimpleExecute(SQL); + SQL.Printf("delete from %s",AwardDefinition::SQLTableNameComponent("xp").GetData());SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Award Definition"); + + SQL="delete from miscellaneous"; + SimpleExecute(SQL); + progress->Update(step++);progress->SetStatus("Miscellaneous"); +} + +sqlite3 *StatsgenDatabase::DBHandle() +{ + return (sqliteDBHandle); +} + +bool StatsgenDatabase::EmptyGenericKeyTable(char *tableName) +{ + wxString SQL; + wxString errorString; + bool retVal=true; + + SQL.Printf("delete from %s",tableName); + SimpleExecute(SQL); + + return retVal; +} + +void StatsgenDatabase::CreateViews() +{ + wxString SQL; + wxString errorString; + + SQL="create view VIEW_KILLDATA as" + " select " + "killdata.roundindex as roundindex," + "killdata.killidx as killidx," + "killdata.killtype as killtype," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "playerclass.id as playerclassid," + "playerclass.realname as playerclassname," + "playerclass.image as playerclassimage," + "playerteam.id as playerteamid," + "playerteam.realname as playerteamname," + "playerteam.image as playerteamimage," + "playerweapon.id as playerweaponid," + "playerweapon.realname as playerweaponname," + "playerweapon.image as playerweaponimage," + "target.name as targetname," + "target.id as targetid," + "target.clanindex as targetclanindex," + "target.playerindex as targetindex," + "targetclass.id as targetclassid," + "targetclass.realname as targetclassname," + "targetclass.image as targetclassimage," + "targetteam.id as targetteamid," + "targetteam.realname as targetteamname," + "targetteam.image as targetteamimage," + "targetlocation.id as targetlocationid," + "targetlocation.realname as targetlocationname," + "targetlocation.image as targetlocationimage" + " from " + " killdata," + "player," + "class as playerclass," + "team as playerteam," + "weapon as playerweapon," + "player as target," + "class as targetclass," + "team as targetteam," + "location as targetlocation" + " where " + "killdata.playerindex=player.playerindex and " + "killdata.playerclass=playerclass.idx and " + "killdata.playerteam=playerteam.idx and " + "killdata.playerweapon=playerweapon.idx and " + "killdata.targetindex=target.playerindex and " + "killdata.targetclass=targetclass.idx and " + "killdata.targetteam=targetteam.idx and " + "killdata.targetlocation=targetlocation.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_AWARDPOINTS as" + " select " + "awardpoints.roundindex as roundindex," + "awardpoints.playerindex as playerindex," + "awardpoints.awardindex as awardindex," + "awardpoints.score as score," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex" + " from " + " awardpoints," + " player" + " where " + "awardpoints.playerindex=player.playerindex" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_PLAYERINROUND as" + " select " + "playerinround.roundindex as roundindex," + "playerinround.playerindex as playerindex," + "playerinround.score as score," + "playerinround.skill as skill," + "playerinround.kills as kills," + "playerinround.deaths as deaths," + "playerinround.teamkills as teamkills," + "playerinround.suicides as suicides," + "playerinround.duration as duration," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.dropped as dropped" + " from " + " playerinround," + " player" + " where " + "playerinround.playerindex=player.playerindex AND " + "dropped='N'" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_PLAYER as" + " select " + " * " + " from " + " player" + " where " + "player.dropped='N'" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_ROUNDS as" + " select " + "rounds.roundidx as roundidx," + "rounds.starttime as starttime," + "rounds.duration as duration," + "rounds.gametype as gametype," + "rounds.mapname as mapname," + "servers.serveridx as serverindex," + "servers.servertype as servertype," + "servers.logfilesize as logfilesize," + "servers.hostname as hostname," + "servers.gameport as gameport," + "map.id as mapid," + "map.realname as maprealname," + "map.image as mapimage," + "gametype.id as gametypeid," + "gametype.realname as gametyperealname," + "gametype.image as gametypeimage" + " from " + " map," + " gametype," + " rounds," + " servers" + " where " + "servers.serveridx=rounds.serverindex AND " + "rounds.dropped='N' AND " + "rounds.gametype=gametype.idx AND " + "rounds.mapname=map.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_ACTIONDATA as" + " select " + "actiondata.roundindex as roundindex," + "actiondata.actionidx as actionindex," + "actiondata.playerclass as classidx," + "actiondata.playerteam as teamidx," + "actiondata.action as actionidx," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "class.realname as playerclassname," + "class.image as playerclassimage," + "team.realname as playerteamname," + "team.image as playerteamimage," + "action.realname as actionname," + "action.image as actionimage " + " from " + " actiondata," + "player," + "class as class," + "team as team," + "action as action " + " where " + "actiondata.playerindex=player.playerindex and " + "actiondata.playerclass=class.idx and " + "actiondata.playerteam=team.idx and " + "actiondata.action=action.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_XPTOTALPOINTS as" + " select " + "xptotalpoints.pointsindex as pointsindex," + "xptotalpoints.points as points," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "xp.realname as xpname," + "xp.id as xpid," + "xp.image as xpimage " + " from " + " xptotalpoints," + "player," + "xp as xp " + " where " + "xptotalpoints.playerindex=player.playerindex and " + "player.dropped='N' and " + "xptotalpoints.pointsindex=xp.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_XPPOINTS as" + " select " + "xppoints.roundindex as roundindex," + "xppoints.pointsindex as pointsindex," + "xppoints.points as points," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "xp.realname as xpname," + "xp.id as xpid," + "xp.image as xpimage " + " from " + " xppoints," + "player," + "xp as xp " + " where " + "xppoints.playerindex=player.playerindex and " + "player.dropped='N' and " + "xppoints.pointsindex=xp.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_TEAMWINDATA as" + " select " + "teamwindata.roundindex as roundindex," + "teamwindata.teamwinidx as teamwinidx," + "teamwindata.playerclass as classidx," + "teamwindata.playerteam as teamidx," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "class.realname as playerclassname," + "class.image as playerclassimage," + "team.realname as playerteamname," + "team.image as playerteamimage " + " from " + " teamwindata," + "player," + "class as class," + "team as team " + " where " + "teamwindata.playerindex=player.playerindex and " + "teamwindata.playerclass=class.idx and " + "teamwindata.playerteam=team.idx" + ";"; + SimpleExecute(SQL); + + SQL="create view VIEW_TEAMLOSSDATA as" + " select " + "teamlossdata.roundindex as roundindex," + "teamlossdata.teamlossidx as teamlossidx," + "teamlossdata.playerclass as classidx," + "teamlossdata.playerteam as teamidx," + "player.name as playername," + "player.id as playerid," + "player.clanindex as playerclanindex," + "player.playerindex as playerindex," + "class.realname as playerclassname," + "class.image as playerclassimage," + "team.realname as playerteamname," + "team.image as playerteamimage " + " from " + " teamlossdata," + "player," + "class as class," + "team as team " + " where " + "teamlossdata.playerindex=player.playerindex and " + "teamlossdata.playerclass=class.idx and " + "teamlossdata.playerteam=team.idx" + ";"; + SimpleExecute(SQL); + + + CreateTotalListView("classes","class"); + CreateTotalListView("gametypes","gametype"); + CreateTotalListView("locations","location"); + CreateTotalListView("maps","map"); + CreateTotalListView("teams","team"); + CreateTotalListView("weapons","weapon"); +} + +void StatsgenDatabase::CreateTotalListView(const char *totalsuffix,const char *indextable) +{ + wxString SQL; + wxString totalTable; + + totalTable=KillTotal::SQLTableName(totalsuffix); + + SQL.Printf("create view VIEW_%s as" + " select " + "%s.itemindex as itemindex," + "%s.playerindex as playerindex," + "%s.kills as kills," + "%s.deaths as deaths," + "%s.suicides as suicides," + "%s.teamkills as teamkills," + "player.name as name," + "%s.id as id," + "%s.realname as realname," + "%s.image as image " + "from " + "%s,%s,player " + "where " + "%s.itemindex=%s.idx and " + "%s.playerindex=player.playerindex and " + "player.dropped='N'" + ";", + totalTable.GetData(), + totalTable.GetData(), + totalTable.GetData(), + totalTable.GetData(), + totalTable.GetData(), + totalTable.GetData(), + totalTable.GetData(), + indextable, + indextable, + indextable, + totalTable.GetData(), + indextable, + totalTable.GetData(), + indextable, + totalTable.GetData()); + + SimpleExecute(SQL); +} + +void StatsgenDatabase::CreateKillTotalIndexes(const char *totaltype) +{ + wxString SQL; + progress->SetStatus(totaltype); + SQL.Printf("create index index_killtotal%s_1 " + "on killtotal%s (itemindex,kills) " + ";",totaltype,totaltype); + SimpleExecute(SQL); +} + +void StatsgenDatabase::CreateIndexes() +{ + wxString SQL; + wxString errorString; + wxString indexesEnabled; + + progress->SetStatus("Create Indexes"); + globalStatistics.configData.ReadTextValue( + "/Database/CreateIndexes", + &indexesEnabled, + "y"); + + if (indexesEnabled.CmpNoCase("y")==0) + { + progress->SetStatus("changedplayers"); + SQL="create index index_changedplayers_1 " + "on changedplayers (idx) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("changedrounds"); + SQL="create index index_changedrounds_1 " + "on changedrounds (idx) " + ";"; + SimpleExecute(SQL); + + CreateKillTotalIndexes("classes"); + CreateKillTotalIndexes("gametypes"); + CreateKillTotalIndexes("locations"); + CreateKillTotalIndexes("maps"); + CreateKillTotalIndexes("teams"); + CreateKillTotalIndexes("weapons"); + + progress->SetStatus("xppoints_1"); + SQL="create index index_xppoints_1 " + "on xppoints (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_2"); + SQL="create index index_xppoints_2 " + "on xppoints (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_3"); + SQL="create index index_xppoints_3 " + "on xppoints (pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_4"); + SQL="create index index_xppoints_4 " + "on xppoints (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_5"); + SQL="create index index_xppoints_5 " + "on xppoints (playerindex,roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_6"); + SQL="create index index_xppoints_6 " + "on xppoints (playerindex,pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_7"); + SQL="create index index_xppoints_7 " + "on xppoints (roundindex,pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_8"); + SQL="create index index_xppoints_8 " + "on xppoints (roundindex,playerindex,pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xppoints_9"); + SQL="create index index_xppoints_9 " + "on xppoints (playerindex,roundindex,pointsindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("xptotalpoints_1"); + SQL="create index index_xptotalpoints_1 " + "on xptotalpoints (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xptotalpoints_2"); + SQL="create index index_xptotalpoints_2 " + "on xptotalpoints (pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xptotalpoints_3"); + SQL="create index index_xptotalpoints_3 " + "on xptotalpoints (playerindex,pointsindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("xptotalpoints_4"); + SQL="create index index_xptotalpoints_4 " + "on xptotalpoints (pointsindex,playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("roundvariables_1"); + SQL="create index index_roundvariables_1 " + "on roundvariables (roundidx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("roundvariables_2"); + SQL="create index index_roundvariables_2 " + "on roundvariables (serverindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("roundvariables_3"); + SQL="create index index_roundvariables_3 " + "on roundvariables (serverindex,roundidx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("roundvariables_4"); + SQL="create index index_roundvariables_4 " + "on roundvariables (roundidx,serverindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("action_1"); + SQL="create index index_action_1 " + "on action (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("action_2"); + SQL="create index index_action_2 " + "on action (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("class_1"); + SQL="create index index_class_1 " + "on class (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("class_2"); + SQL="create index index_class_2 " + "on class (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("gametype_1"); + SQL="create index index_gametype_1 " + "on gametype (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("gametype_2"); + SQL="create index index_gametype_2 " + "on gametype (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("location_1"); + SQL="create index index_location_1 " + "on location (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("location_2"); + SQL="create index index_location_2 " + "on location (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("map_1"); + SQL="create index index_map_1 " + "on map (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("map_2"); + SQL="create index index_map_2 " + "on map (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("team_1"); + SQL="create index index_team_1 " + "on team (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("team_2"); + SQL="create index index_team_2 " + "on team (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("weapon_1"); + SQL="create index index_weapon_1 " + "on weapon (idx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("weapon_2"); + SQL="create index index_weapon_2 " + "on weapon (id) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("actiondata_1"); + SQL="create index index_actiondata_1 " + "on actiondata (roundindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("actiondata_2"); + SQL="create index index_actiondata_2 " + "on actiondata (actionidx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("actiondata_3"); + SQL="create index index_actiondata_3 " + "on actiondata (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("actiondata_4"); + SQL="create index index_actiondata_4 " + "on actiondata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("killdata_1"); + SQL="create index index_killdata_1 " + "on killdata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_2"); + SQL="create index index_killdata_2 " + "on killdata (roundindex,killtype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_3"); + SQL="create index index_killdata_3 " + "on killdata (playerindex,killtype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_4"); + SQL="create index index_killdata_4 " + "on killdata (playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("killdata_5"); + SQL="create index index_killdata_5 " + "on killdata (killtype,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_6"); + SQL="create index index_killdata_6 " + "on killdata (killtype,playerweapon) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_7"); + SQL="create index index_killdata_7 " + "on killdata (playerweapon) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_8"); + SQL="create index index_killdata_8 " + "on killdata (killtype,roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_9"); + SQL="create index index_killdata_9 " + "on killdata (targetlocation) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_10"); + SQL="create index index_killdata_10 " + "on killdata (killtype,targetindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("killdata_11"); + SQL="create index index_killdata_11 " + "on killdata (targetindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("player_1"); + SQL="create index index_player_1 " + "on player (playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("player_2"); + SQL="create index index_player_2 " + "on player (dropped) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("playerinround_1"); + SQL="create index index_playerinround_1 " + "on playerinround (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_2"); + SQL="create index index_playerinround_2 " + "on playerinround (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_3"); + SQL="create index index_playerinround_3 " + "on playerinround (roundindex,score) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_4"); + SQL="create index index_playerinround_4 " + "on playerinround (roundindex,skill) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_5"); + SQL="create index index_playerinround_5 " + "on playerinround (roundindex,kills) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_6"); + SQL="create index index_playerinround_6 " + "on playerinround (roundindex,deaths) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_7"); + SQL="create index index_playerinround_7 " + "on playerinround (roundindex,teamkills) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_8"); + SQL="create index index_playerinround_8 " + "on playerinround (roundindex,suicides) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_9"); + SQL="create index index_playerinround_9 " + "on playerinround (roundindex,duration) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("playerinround_10"); + SQL="create index index_playerinround_10 " + "on playerinround (playerindex,roundindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("rounds_1"); + SQL="create index index_rounds_1 " + "on rounds (roundidx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_2"); + SQL="create index index_rounds_2 " + "on rounds (gametype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_3"); + SQL="create index index_rounds_3 " + "on rounds (mapname) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_4"); + SQL="create index index_rounds_4 " + "on rounds (dropped) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("rounds_5"); + SQL="create index index_rounds_5 " + "on rounds (serverindex,roundidx) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_6"); + SQL="create index index_rounds_6 " + "on rounds (serverindex,gametype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_7"); + SQL="create index index_rounds_7 " + "on rounds (serverindex,mapname) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_8"); + SQL="create index index_rounds_8 " + "on rounds (serverindex,dropped) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("rounds_9"); + SQL="create index index_rounds_9 " + "on rounds (serverindex,mapname,gametype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_10"); + SQL="create index index_rounds_10 " + "on rounds (serverindex,gametype,mapname) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("rounds_11"); + SQL="create index index_rounds_11 " + "on rounds (mapname,gametype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("rounds_12"); + SQL="create index index_rounds_12 " + "on rounds (gametype,mapname) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("speechdata_1"); + SQL="create index index_speechdata_1 " + "on speechdata (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("speechdata_2"); + SQL="create index index_speechdata_2 " + "on speechdata (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("speechdata_3"); + SQL="create index index_speechdata_3 " + "on speechdata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("teamlossdata_1"); + SQL="create index index_teamlossdata_1 " + "on teamlossdata (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("teamlossdata_2"); + SQL="create index index_teamlossdata_2 " + "on teamlossdata (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("teamlossdata_3"); + SQL="create index index_teamlossdata_3 " + "on teamlossdata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("teamwindata_1"); + SQL="create index index_teamwindata_1 " + "on teamwindata (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("teamwindata_2"); + SQL="create index index_teamwindata_2 " + "on teamwindata (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("teamwindata_3"); + SQL="create index index_teamwindata_3 " + "on teamwindata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("streakdata_1"); + SQL="create index index_streakdata_1 " + "on streakdata (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_2"); + SQL="create index index_streakdata_2 " + "on streakdata (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_3"); + SQL="create index index_streakdata_3 " + "on streakdata (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_4"); + SQL="create index index_streakdata_4 " + "on streakdata (streaktype) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_5"); + SQL="create index index_streakdata_5 " + "on streakdata (playerindex,roundindex,streaksize) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_6"); + SQL="create index index_streakdata_6 " + "on streakdata (roundindex,playerindex,streaksize) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_7"); + SQL="create index index_streakdata_7 " + "on streakdata (roundindex,streaksize) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_8"); + SQL="create index index_streakdata_8 " + "on streakdata (playerindex,streaksize) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_9"); + SQL="create index index_streakdata_9 " + "on streakdata (streaktype,streaksize) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("streakdata_10"); + SQL="create index index_streakdata_10 " + "on streakdata (playerindex,roundindex,streaksize) " + ";"; + SimpleExecute(SQL); + + progress->SetStatus("awardpoints_1"); + SQL="create index index_awardpoints_1 " + "on awardpoints (roundindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_2"); + SQL="create index index_awardpoints_2 " + "on awardpoints (roundindex,playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_3"); + SQL="create index index_awardpoints_3 " + "on awardpoints (roundindex,score) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_4"); + SQL="create index index_awardpoints_4 " + "on awardpoints (roundindex,awardindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_5"); + SQL="create index index_awardpoints_5 " + "on awardpoints (playerindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_6"); + SQL="create index index_awardpoints_6 " + "on awardpoints (playerindex,score) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_7"); + SQL="create index index_awardpoints_7 " + "on awardpoints (playerindex,awardindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_8"); + SQL="create index index_awardpoints_8 " + "on awardpoints (awardindex) " + ";"; + SimpleExecute(SQL); + progress->SetStatus("awardpoints_9"); + SQL="create index index_awardpoints_9 " + "on awardpoints (awardindex,score) " + ";"; + SimpleExecute(SQL); + } + +} + +void StatsgenDatabase::GetDatabaseComponent( + const char *componentType, + wxArrayString &componentNames, + wxArrayString &componentSQLList) +{ + wxString SQL; + TemplateOpenQuery query; + wxString componentName; + wxString fieldName; + wxString componentSQL; + + STATSGEN_DEBUG_FUNCTION_START("StatsgenDatabase","GetDatabaseComponent") + componentNames.Clear(); + componentSQLList.Clear(); + + SQL.Printf("select name,sql from sqlite_master where type='%s' order by name",componentType); + query.Initiate(SQL,sqliteDBHandle); + while (query.NextRow()) + { + fieldName="name";componentName=query.RetrieveProperty(fieldName); + fieldName="sql";componentSQL=query.RetrieveProperty(fieldName); + componentNames.Add(componentName); + componentSQLList.Add(componentSQL); + STATSGEN_DEBUG(DEBUG_ALWAYS,componentName) + STATSGEN_DEBUG(DEBUG_ALWAYS,componentSQL) + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void StatsgenDatabase::DropIndexes() +{ + wxString SQL; + TemplateOpenQuery *query; + wxString indexName; + wxString fieldName; + wxArrayString indexNames; + int indexCount; + int indexIndex; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("StatsgenDatabase","DropIndexes") + + query=new TemplateOpenQuery(); + fieldName="name"; + SQL="select name from sqlite_master where type='index' order by name"; + query->Initiate(SQL,sqliteDBHandle); + while (query->NextRow()) + { + indexName=query->RetrieveProperty(fieldName); + indexNames.Add(indexName); + } + delete (query); + indexCount=indexNames.GetCount(); + for (indexIndex=0;indexIndexSetStatus(msg); + SQL.Printf("drop index %s",indexName.GetData()); + SimpleExecute(SQL); + } + + STATSGEN_DEBUG_FUNCTION_END +} + +int StatsgenDatabase::RetrieveTableCount(const char *tableName,const char *fieldName) +{ + wxString sql; + TemplateOpenQuery query; + int tableCount=-1; + wxString property="counter"; + + sql.Printf("select max(%s) as counter from %s",fieldName,tableName); + query.Initiate(sql,sqliteDBHandle); + if (query.NextRow()) + { + tableCount=atoi(query.RetrieveProperty(property).GetData()); + } + return tableCount; +} + +void StatsgenDatabase::UpdateRoundCount() +{ + roundCount=RetrieveTableCount("rounds","roundidx"); +} + +void StatsgenDatabase::UpdatePlayerCount() +{ + playerCount=RetrieveTableCount("player","playerindex"); +} + +int StatsgenDatabase::NextPlayerIndex() +{ + return (playerCount+1); +} + +int StatsgenDatabase::NextRoundIndex() +{ + return (roundCount+1); +} + +void StatsgenDatabase::UpdatePlayerKillTotal(int playerIndex, + int databasePlayerIndex, + const char *tableNameSuffix, + ArrayOfKillTotal &killTotals) +{ + static wxString propertyItemIndex ="itemindex"; + static wxString propertyKills ="kills"; + static wxString propertyDeaths ="deaths"; + static wxString propertySuicides ="suicides"; + static wxString propertyTeamKills ="teamkills"; + TemplateOpenQuery query; + wxString sql; + + sql.Printf("select * from killtotal%s where playerindex=\'%d\'", + tableNameSuffix, + databasePlayerIndex); + query.Initiate(sql,sqliteDBHandle); + while (query.NextRow()) + { + KillTotal killTotal; + + killTotal.playerIndex=playerIndex; + killTotal.itemIndex =atoi(query.RetrieveProperty(propertyItemIndex).GetData()); + killTotal.kills =atoi(query.RetrieveProperty(propertyKills).GetData()); + killTotal.deaths =atoi(query.RetrieveProperty(propertyDeaths).GetData()); + killTotal.suicides =atoi(query.RetrieveProperty(propertySuicides).GetData()); + killTotal.teamkills =atoi(query.RetrieveProperty(propertyTeamKills).GetData()); + + killTotals.Add(killTotal); + } +} + +void StatsgenDatabase::UpdatePlayerKillTotals( + int playerIndex, + int databasePlayerIndex, + ArrayOfKillTotal &maps, + ArrayOfKillTotal &gameTypes, + ArrayOfKillTotal &weapons, + ArrayOfKillTotal &locations, + ArrayOfKillTotal &teams, + ArrayOfKillTotal &classes) +{ + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"maps",maps); + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"gametypes",gameTypes); + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"weapons",weapons); + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"locations",locations); + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"teams",teams); + UpdatePlayerKillTotal(playerIndex,databasePlayerIndex,"classes",classes); +} + +void StatsgenDatabase::Zap() +{ + wxArrayString tableNames; + wxArrayString tableSQL; + wxString tableName; + int tableCount; + int tableIndex; + wxString sql; + wxString statusText; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("StatsgenDatabase","Zap") + + GetDatabaseComponent("table",tableNames,tableSQL); + tableCount=tableNames.GetCount(); + msg.Printf("Emptying %d tables",tableCount); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->Initiate((long)tableCount," tables",1, " tables",1); + for (tableIndex=0;tableIndexUpdate((long)tableIndex); + tableName=tableNames.Item(tableIndex); + msg.Printf("Emptying %d table %s",tableIndex,tableName.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + statusText="Emptying "+tableName; + progress->SetStatus(statusText); + sql="delete from "+tableName; + SimpleExecute(sql); + } + progress->Finalise(); + STATSGEN_DEBUG_FUNCTION_END +} + +void StatsgenDatabase::ApplyAliases(wxArrayInt &changedPlayers) +{ + int aliasCount; + int aliasIndex; + AliasListEntry aliasEntry; + int playerIndex; + int updatedIndex; + + + changedPlayers.Clear(); + aliasCount=globalStatistics.aliasList.GetCount(); + progress->Initiate(aliasCount," aliases", 1, " aliases",1); + for (aliasIndex=0;aliasIndexUpdate(aliasIndex); + aliasEntry=globalStatistics.aliasList.Item(aliasIndex); + updatedIndex=aliasEntry.UpdateInDatabase(); + if (updatedIndex!=-1) + { + changedPlayers.Add(updatedIndex); + } + } +} + +void StatsgenDatabase::Optimize() +{ + wxString SQL; + + SQL="analyze"; + SimpleExecute(SQL); +} + +wxString StatsgenDatabase::StringFieldDefinition(const char *fieldname,const char *key,int defaultFieldWidth) +{ + wxString configKey; + wxString configValue; + wxString defaultWidth; + + wxString fieldDefinition; + + configKey="/Database/UseFixedFieldWidths"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"y"); + if (configValue.CmpNoCase("y")==0) + { + configKey="/DatabaseFieldWidths/"; + configKey+=key; + defaultWidth.Printf("%d",defaultFieldWidth); + globalStatistics.configData.ReadTextValue(configKey,&configValue,(char *)defaultWidth.GetData()); + // Using a fixed width field + fieldDefinition.Printf("%s string (%d)",fieldname,atoi(configValue.GetData())); + } + else + { + // using variable width field + fieldDefinition.Printf("%s string",fieldname); + } + + return (fieldDefinition); +} diff --git a/StatsgenDatabase.h b/StatsgenDatabase.h new file mode 100644 index 0000000..50ac472 --- /dev/null +++ b/StatsgenDatabase.h @@ -0,0 +1,117 @@ +#ifndef __STATSGENDATABASE +#define __STATSGENDATABASE + +// wxWindows includes +#include +#include + +// Statsgen Includes +#include "sqlite3.h" +#include "KillTotal.h" +//#include "libsqlitewrapped.h" + +// #defines +#define TABLE_NAME_KEY_AMMO "ammo" +#define TABLE_NAME_KEY_ACTION "action" +#define TABLE_NAME_KEY_WEAPON "weapon" +#define TABLE_NAME_KEY_MAP "map" +#define TABLE_NAME_KEY_TEAM "team" +#define TABLE_NAME_KEY_CLASS "class" +#define TABLE_NAME_KEY_GAMETYPE "gametype" +#define TABLE_NAME_KEY_LOCATION "location" +#define TABLE_NAME_KEY_XP "xp" + +#define FIELD_WIDTH_MISC_STATISTIC 50 +#define FIELD_WIDTH_MISC_VALUE 50 +#define FIELD_WIDTH_KEY_ID 32 +#define FIELD_WIDTH_KEY_REALNAME 100 +#define FIELD_WIDTH_KEY_IMAGE 150 +#define FIELD_WIDTH_PLAYER_DATA 150 +#define FIELD_WIDTH_PLAYER_NAME 50 +#define FIELD_WIDTH_SERVER_TYPE 10 +#define FIELD_WIDTH_HOSTNAME 50 +#define FIELD_WIDTH_VARIABLE 50 +#define FIELD_WIDTH_VALUE 50 +#define FIELD_WIDTH_CLAN_TAG 10 +#define FIELD_WIDTH_CLAN_NAME 50 +#define FIELD_WIDTH_CLAN_WEBADDRESS 150 +#define FIELD_WIDTH_CLAN_BANNER 150 +#define FIELD_WIDTH_PLAYER_NAME 50 +#define FIELD_WIDTH_PLAYER_GUID 50 +#define FIELD_WIDTH_ROUND_START_TIME 20 +#define FIELD_WIDTH_KILL_TYPE 14 +#define FIELD_WIDTH_SPEECH 80 +#define FIELD_WIDTH_AWARD_ID 32 +#define FIELD_WIDTH_AWARD_NAME 50 +#define FIELD_WIDTH_AWARD_IMAGE 150 +class StatsgenDatabase +{ + public: + static wxString StringFieldDefinition(const char *fieldName,const char *key,int defaultFieldWidth); + StatsgenDatabase(); + virtual ~StatsgenDatabase(); + wxString Filename(); + void Create(); + void Empty(); + bool SimpleExecute(wxString &sql); + bool OpenDB(); + bool CloseDB(); + void Zap(); + void ApplyAliases(wxArrayInt &changedPlayers); + static wxString SafeForInsert(wxString &text); + sqlite3 *DBHandle(); + bool WriteMiscellaneousStatistic(char *variable,wxString &value); + bool WriteMiscellaneousStatistic(char *variable,long value); + bool WriteMiscellaneousStatistic(char *variable,int value); + void GetDatabaseComponent(const char *componentType, + wxArrayString &componentNames, + wxArrayString &componentSQL); + + void CreateIndexes(); + void DropIndexes(); + int RetrieveTableCount(const char *tableName,const char *fieldName); + void UpdatePlayerCount(); + void UpdateRoundCount(); + int NextPlayerIndex(); + int NextRoundIndex(); + void CreateIndexListTable(const char *tableName); + void CreateChangedPlayersTable(); + void CreateChangedRoundsTable(); + void EmptyIndexListTable(const char *tableName); + void EmptyChangedPlayersTable(); + void EmptyChangedRoundsTable(); + void WriteIndexListToTable(const char *tableName,wxArrayInt &list); + void WriteChangedPlayersList(wxArrayInt &listOfPlayerIndexes); + void WriteChangedRoundsList(wxArrayInt &listOfRoundIndexes); + void WriteChangedRoundsList(); + + void UpdatePlayerKillTotal(int playerIndex, + int databasePlayerIndex, + const char *tableNameSuffix, + ArrayOfKillTotal &killTotals); + void UpdatePlayerKillTotals(int playerIndex, + int databasePlayerIndex, + ArrayOfKillTotal &maps, + ArrayOfKillTotal &gameTypes, + ArrayOfKillTotal &weapons, + ArrayOfKillTotal &locations, + ArrayOfKillTotal &teams, + ArrayOfKillTotal &classes); + void Optimize(); + private: + void CreateViews(); + void CreateTotalListView(const char *totalSuffix, + const char *indextable); + void CreateKillTotalIndexes(const char *totaltype); + bool CreateGenericKeyTable(char *tableName); + bool EmptyGenericKeyTable(char *tableName); + + wxString databaseFilename; + sqlite3 *sqliteDBHandle; + int roundCount; + int playerCount; + +}; + + +#endif diff --git a/StatsgenFrame.cpp b/StatsgenFrame.cpp new file mode 100644 index 0000000..29094f2 --- /dev/null +++ b/StatsgenFrame.cpp @@ -0,0 +1,2777 @@ +#include +#include +#include +#include +#include +#include +#include + + +// Statsgen Includes +#include "Version.h" +#include "StatsgenApp.h" +#include "StatsgenFrame.h" +#include "LogFileReader.h" +#include "TemplateFile.h" +#include "ErrorData.h" +#include "Server.h" +#include "WindowIDs.h" +#include "ConfigEditorGUI.h" +#include "ServerTypePanel.h" +#include "SkillTypePanel.h" +#include "ImageTypePanel.h" +#include "GenericConfigGUI.h" +#include "GenericNumberedConfigGUI.h" +#include "GenericNumberedConfigPanel.h" +#include "GroupedConfigItemsPanel.h" +#include "FTPConnectionPanel.h" +#include "PlayerCachePanel.h" +#include "AliasEditorPanel.h" +#include "AliasDialog.h" +#include "AwardEditorPanel.h" +#include "GenericOKCancelDialog.h" +#include "Progress.h" +#include "ClanEditorPanel.h" +#include "DropListDialog.h" +#include "TextListDialog.h" +#include "StatsgenApp.h" +#include "Progress.h" +#include "TemplateFile.h" +#include "StaticFunctions.h" +#include "PlayerDataDialog.h" +#include "PriorityPanel.h" +#include "TemplateFile.h" +#include "GUITriggerList.h" +#include "GlobalStatistics.h" +#include "PerformUpgradeDialog.h" +#include "StatsgenWeb.h" +#include "GUIWizards.h" +#include "WeaponGroupDialog.h" + + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- +IMPLEMENT_CLASS(wxWidgetsFrame, wxFrame) + +BEGIN_EVENT_TABLE(wxWidgetsFrame, wxFrame) + EVT_TIMER(wxID_ANY, wxWidgetsFrame::OnTimerTick) + EVT_MENU(WINDOW_ID_WIZARD, wxWidgetsFrame::OnWizard) + EVT_MENU(WINDOW_ID_MENU_ABOUT, wxWidgetsFrame::OnAbout) + EVT_MENU(WINDOW_ID_MENU_HELP, wxWidgetsFrame::OnHelp) + EVT_MENU(WINDOW_ID_MENU_THREAD, wxWidgetsFrame::OnConfigThread) + EVT_MENU(WINDOW_ID_MENU_QUIT, wxWidgetsFrame::OnQuit) + EVT_MENU(WINDOW_ID_MENU_GO, wxWidgetsFrame::OnGo) + EVT_MENU(WINDOW_ID_MENU_ADVANCED, wxWidgetsFrame::OnAdvanced) + EVT_MENU(WINDOW_ID_MENU_RESET_RECOVERY, wxWidgetsFrame::OnResetRecovery) + EVT_MENU(WINDOW_ID_MENU_STORE_PROGRESS, wxWidgetsFrame::OnStoreProgress) + EVT_MENU(WINDOW_ID_MENU_EMPTY_DATABASE, wxWidgetsFrame::OnDatabaseEmpty) + EVT_MENU(WINDOW_ID_MENU_SCORE_WEIGHTS, wxWidgetsFrame::OnEditScoreWeights) + EVT_MENU(WINDOW_ID_MENU_SKILL_WEIGHTS, wxWidgetsFrame::OnEditSkillWeights) + EVT_MENU(WINDOW_ID_MENU_REAL_NAMES, wxWidgetsFrame::OnEditRealNames) + EVT_MENU(WINDOW_ID_MENU_WEAPON_GROUPS, wxWidgetsFrame::OnEditWeaponGroups) + EVT_MENU(WINDOW_ID_MENU_IMAGES, wxWidgetsFrame::OnEditImages) + EVT_MENU(WINDOW_ID_MENU_MESSAGE_FORMATS, wxWidgetsFrame::OnEditMessageFormats) + EVT_MENU(WINDOW_ID_MENU_WEBSITE, wxWidgetsFrame::OnWebsiteConfig) + EVT_MENU(WINDOW_ID_MENU_IMAGEPACKS, wxWidgetsFrame::OnImagePackConfig) + EVT_MENU(WINDOW_ID_MENU_TEMPLATEPACKS, wxWidgetsFrame::OnTemplatePackConfig) + EVT_MENU(WINDOW_ID_MENU_FULL_CONFIG, wxWidgetsFrame::OnFullConfig) + EVT_MENU(WINDOW_ID_MENU_OUTPUT, wxWidgetsFrame::OnOutputConfig) + EVT_MENU(WINDOW_ID_MENU_EXTERNAL_DATABASE, wxWidgetsFrame::OnExternalDatabaseConfig) + EVT_MENU(WINDOW_ID_MENU_TEMPLATE_CONFIG, wxWidgetsFrame::OnTemplateConfig) + EVT_MENU(WINDOW_ID_MENU_SERVER, wxWidgetsFrame::OnServerConfig) + EVT_MENU(WINDOW_ID_MENU_CLAN, wxWidgetsFrame::OnClanConfig) + EVT_MENU(WINDOW_ID_MENU_ALIAS, wxWidgetsFrame::OnAliasConfig) + EVT_MENU(WINDOW_ID_MENU_DROPLIST, wxWidgetsFrame::OnDropListConfig) + EVT_MENU(WINDOW_ID_MENU_BAD_WORDS, wxWidgetsFrame::OnBadWordsListConfig) + EVT_MENU(WINDOW_ID_MENU_WEB_SERVER, wxWidgetsFrame::OnWebServerConfig) + EVT_MENU(WINDOW_ID_MENU_CUSTOM_MESSAGES, wxWidgetsFrame::OnCustomMessagesConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAAVATAR, wxWidgetsFrame::OnPlayerDataAvatarConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAREALNAME, wxWidgetsFrame::OnPlayerDataRealNameConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAPICTURE, wxWidgetsFrame::OnPlayerDataPictureConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAXFIRE, wxWidgetsFrame::OnPlayerDataXfireConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAWEBSITE, wxWidgetsFrame::OnPlayerDataWebsiteConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATACLANROLE, wxWidgetsFrame::OnPlayerDataClanRoleConfig) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAMISC1, wxWidgetsFrame::OnPlayerDataMisc1Config) + EVT_MENU(WINDOW_ID_MENU_PLAYERDATAMISC2, wxWidgetsFrame::OnPlayerDataMisc2Config) + EVT_MENU(WINDOW_ID_MENU_AWARD, wxWidgetsFrame::OnAwardConfig) + EVT_MENU(WINDOW_ID_MENU_RCON_CONFIG, wxWidgetsFrame::OnRCONSpamConfig) + EVT_MENU(WINDOW_ID_MENU_DEBUG, wxWidgetsFrame::OnDebugConfig) + EVT_MENU(WINDOW_ID_MENU_EXPORT_TEMPLATE, wxWidgetsFrame::OnExportTemplate) + EVT_MENU(WINDOW_ID_MENU_PERFORM_UPGRADE, wxWidgetsFrame::OnPerformUpgrade) + EVT_MENU(WINDOW_ID_MENU_EXPORT_UPGRADE, wxWidgetsFrame::OnExportUpgrade) + EVT_MENU(WINDOW_ID_MENU_EXPORT_BUILD_INI, wxWidgetsFrame::OnExportBuildINI) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_GAMETYPE, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_MAP, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_CLASS, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_TEAM, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPON, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_AMMO, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPONAMMO, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_LOCATION, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(WINDOW_ID_MENU_LOG_SUBSTITUTE_ACTION, wxWidgetsFrame::OnLogSubstitute) + EVT_MENU(EVENT_ID_PROGRESS_STATUS_TEXT, wxWidgetsFrame::OnProgressUpdate) + EVT_MENU(EVENT_ID_PROGRESS_BUTTON, wxWidgetsFrame::OnProgressUpdate) +END_EVENT_TABLE() + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- +wxWidgetsFrame::wxWidgetsFrame(const wxString& title, const wxPoint& pos, const wxSize& size) +: wxFrame((wxFrame *)NULL, -1, title, pos, size) +{ + bool runOnceFlag; + + quitNow=false; + workerThread=false; + globalStatistics.mainEventHandler=this; + + wxMenu *helpMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *fileMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *displayMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *calculationMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *mandatoryMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *optionalMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *rconMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *logSubstituteMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *devMenu = new wxMenu(_(""), wxMENU_TEAROFF); + wxMenu *playerData = new wxMenu(_(""), wxMENU_TEAROFF); + + int argIndex; + + globalStatistics.configData.Initiate(); + STATSGEN_DEBUG_INITIATE + STATSGEN_DEBUG_UPDATE_DEBUG_LEVEL(WINDOW_ID_PROGRESS_PANEL_GENERAL) + globalStatistics.configData.CommitChanges(); + + helpMenu->Append(WINDOW_ID_MENU_HELP, _("&Help"), _("Help")); + helpMenu->Append(WINDOW_ID_MENU_ABOUT, _("About"), _("Version")); + fileMenu->AppendCheckItem(WINDOW_ID_MENU_ADVANCED, _("Advanced Menus"), _("Advanced")); + fileMenu->Append(WINDOW_ID_WIZARD, _("First Time Configuration Run"), _("Run this the first time you start statsgen")); + fileMenu->Append(WINDOW_ID_MENU_GO, _("Go\tf1"), _("Go")); + fileMenu->Append(WINDOW_ID_MENU_EMPTY_DATABASE, _("Empty Database"), _("Empty Database")); + fileMenu->Append(WINDOW_ID_MENU_THREAD, _("Priority\tf2"), _("Change Priority")); + fileMenu->Append(WINDOW_ID_MENU_PERFORM_UPGRADE, _("Upgrade Configuration"), _("Use an Upgrade file to update configuration")); + fileMenu->Append(WINDOW_ID_MENU_RESET_RECOVERY, _("Clear Recovery Status"), _("Clear Recovery Status")); + fileMenu->Append(WINDOW_ID_MENU_STORE_PROGRESS, _("Write Errors To File"), _("Write Errors To File")); + fileMenu->Append(WINDOW_ID_MENU_QUIT, _("E&xit\tAlt-X"), _("Quit this program")); + + displayMenu->Append(WINDOW_ID_MENU_WEAPON_GROUPS, _("Weapon Groups"), _("Edit Weapon Groupings")); + displayMenu->Append(WINDOW_ID_MENU_REAL_NAMES, _("Real Names"), _("Edit Real Names")); + displayMenu->Append(WINDOW_ID_MENU_IMAGES, _("Images"), _("Edit Image References")); + + playerData->Append(WINDOW_ID_MENU_PLAYERDATAAVATAR, _("Avatar Editing"), _("Edit Player Avatar Images")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAREALNAME, _("Real Name Editing"), _("Edit Player Real Names")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAPICTURE, _("Personal Picture"), _("Edit Player Personal Pictures")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATACLANROLE, _("Clan Role"), _("Edit Player's Clan Role")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAXFIRE, _("Xfire"), _("Edit Player's Xfire ID")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAWEBSITE, _("Website"), _("Edit Player's Personal Website")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAMISC1, _("Miscellaneous 1"), _("Edit Player's Miscellaneous Data 1")); + playerData->Append(WINDOW_ID_MENU_PLAYERDATAMISC2, _("Miscellaneous 2"), _("Edit Player's Miscellaneous Data 2")); + + calculationMenu->Append(WINDOW_ID_MENU_SCORE_WEIGHTS, _("Score Weights"), _("Edit Score Weights")); + calculationMenu->Append(WINDOW_ID_MENU_SKILL_WEIGHTS, _("Skill Weights"), _("Edit Skill Weights")); + calculationMenu->Append(WINDOW_ID_MENU_AWARD, _("Award Editing"), _("Edit Award Configuration")); + + mandatoryMenu->Append(WINDOW_ID_MENU_TEMPLATE_CONFIG, _("Template Variable Config"), _("Change variables used by the template during output")); + mandatoryMenu->Append(WINDOW_ID_MENU_OUTPUT, _("Output Config"), _("Edit How And Where Output Is Created")); + mandatoryMenu->Append(WINDOW_ID_MENU_SERVER, _("Server Config"), _("Edit Server Connection Details")); + mandatoryMenu->Append(WINDOW_ID_MENU_WEBSITE, _("Website Config"), _("Edit Website Connection Details")); + mandatoryMenu->Append(WINDOW_ID_MENU_IMAGEPACKS, _("Upload Image Packs"), _("Upload appropriate image packs")); + mandatoryMenu->Append(WINDOW_ID_MENU_TEMPLATEPACKS, _("Upload Template Packs"), _("Upload Alternative Templates")); + + optionalMenu->Append(WINDOW_ID_MENU_CLAN, _("Clan Config"), _("Edit Clan Details")); + optionalMenu->Append(WINDOW_ID_MENU_ALIAS, _("Alias Editing"), _("Edit Player Alias Entries")); + optionalMenu->Append(WINDOW_ID_MENU_DROPLIST, _("Drop List Editing"), _("Edit List Of Allowed Players")); + optionalMenu->Append(WINDOW_ID_MENU_BAD_WORDS, _("Banned Speech Editing"), _("Edit List Of Words Not Allowed In Speech")); + optionalMenu->Append(WINDOW_ID_MENU_WEB_SERVER, _("Web Server Setting"), _("Configure Embedded Webserver")); + optionalMenu->Append(WINDOW_ID_MENU_EXTERNAL_DATABASE, _("External Database Config"), _("Configure MySQL connection")); + rconMenu->Append(WINDOW_ID_MENU_RCON_CONFIG, _("Message Centre"), _("Configure Game Server Messages")); + rconMenu->Append(WINDOW_ID_MENU_MESSAGE_FORMATS, _("Message Centre Formats"), _("Edit Message Centre Formats")); + rconMenu->Append(WINDOW_ID_MENU_CUSTOM_MESSAGES, _("Custom Messages"), _("Edit Custom Messages")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_GAMETYPE, _("Game Type"), _("Log File Substitution For Game Type")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_MAP, _("Map"), _("Log File Substitution For Map")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_CLASS, _("Class"), _("Log File Substitution For Class")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_TEAM, _("Team"), _("Log File Substitution For Team")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPON, _("Weapon"), _("Log File Substitution For Weapon")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_AMMO, _("Ammo"), _("Log File Substitution For Ammo")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPONAMMO, _("Weapon And Ammo"), _("Log File Substitution For Weapon And Ammo")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_LOCATION, _("Location"), _("Log File Substitution For Location")); + logSubstituteMenu->Append(WINDOW_ID_MENU_LOG_SUBSTITUTE_ACTION, _("Action"), _("Log File Substitution For Action")); + + devMenu->Append(WINDOW_ID_MENU_DEBUG, _("Debug Settings"), _("Developer Debug Settings")); + devMenu->Append(WINDOW_ID_MENU_EXPORT_TEMPLATE, _("Export Template"), _("Export Template To C++")); + devMenu->Append(WINDOW_ID_MENU_EXPORT_UPGRADE, _("Export Upgrade File"), _("Prepare An Upgrade File")); + devMenu->Append(WINDOW_ID_MENU_EXPORT_BUILD_INI, _("Export Build INI File"), _("The Build INI File")); + + wxMenuBar *menuBar = new wxMenuBar(); + menuBar->Append(fileMenu, _("&Run")); + menuBar->Append(calculationMenu, _("&Calculation")); + menuBar->Append(displayMenu, _("&Display")); + menuBar->Append(mandatoryMenu, _("&Mandatory")); + menuBar->Append(optionalMenu, _("&Optional")); + menuBar->Append(playerData, _("&Player Data")); + menuBar->Append(rconMenu, _("&Message Centre")); + menuBar->Append(logSubstituteMenu, _("&Logfile Substitutions")); + menuBar->Append(devMenu, _("&Developer")); + menuBar->Append(helpMenu, _("&Help")); + + SetMenuBar(menuBar); + CreateStatusBar(3); + progress=new StatusPanel(); + progress->Create(this,-1); +// progress->CreatePanels(); + SetStatusText(_("Status Text")); + globalStatistics.ReadScheduleConfig(); +/* + if (FirstTimeRun()) + { + GUIWizardPagesFirstConfig wizardPages; + RunWizard(&wizardPages); + } + Upgrade(); +*/ + if (!NeedsFirstTimeRun()) + { + Upgrade(); + } + scheduleTimer.SetOwner(this); + scheduleTimer.Start(1000); + + runOnceFlag=false; + globalStatistics.hiddenFeatures=false; + for (argIndex=1;argIndex1) + { + if (strcmp(wxGetApp().argv[argIndex],"-runonce")==0) + { + runOnceFlag=true; + } + if (strcmp(wxGetApp().argv[argIndex],"-elric")==0) + { + globalStatistics.hiddenFeatures=true; + } + } + } + if (runOnceFlag) + { + quitNow=true; + wxCommandEvent dummyEvent; + OnGo(dummyEvent); + } + SetMenuItems(); + +// globalStatistics.webServer.StartServer(); +} + +void wxWidgetsFrame::OnFullConfig(wxCommandEvent &event) +{ + GUIWizardPagesFullConfig wizardPages; + RunWizard(&wizardPages); +} + +void wxWidgetsFrame::SetMenuItems() +{ + wxString configKey; + wxString configValue; + wxMenuBar *menuBar; + configKey="/General/advancedmenus"; + bool firstTimeRun; + + runningWizard=false; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + globalStatistics.configData.CommitChanges(); + advanced=(configValue.CmpNoCase("Y")==0); + menuBar = GetMenuBar(); + + firstTimeRun=NeedsFirstTimeRun(); + menuBar->Enable(WINDOW_ID_WIZARD, firstTimeRun || advanced); + + menuBar->Enable(WINDOW_ID_MENU_ADVANCED, true && (!firstTimeRun)); + menuBar->Check(WINDOW_ID_MENU_ADVANCED, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_HELP, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_ABOUT, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_GO, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_EMPTY_DATABASE, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_THREAD, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PERFORM_UPGRADE, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_RESET_RECOVERY, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_STORE_PROGRESS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_QUIT, true && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_WEAPON_GROUPS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_REAL_NAMES, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_IMAGES, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_FULL_CONFIG, true && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAAVATAR, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAREALNAME, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAPICTURE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATACLANROLE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAXFIRE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAWEBSITE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAMISC1, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_PLAYERDATAMISC2, advanced && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_SCORE_WEIGHTS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_SKILL_WEIGHTS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_AWARD, advanced && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_TEMPLATE_CONFIG, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_OUTPUT, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_SERVER, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_WEBSITE, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_IMAGEPACKS, true && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_CLAN, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_ALIAS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_DROPLIST, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_BAD_WORDS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_WEB_SERVER, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_EXTERNAL_DATABASE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_RCON_CONFIG, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_MESSAGE_FORMATS, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_CUSTOM_MESSAGES, true && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_GAMETYPE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_MAP, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_CLASS, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_TEAM, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPON, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_AMMO, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPONAMMO, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_LOCATION, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_LOG_SUBSTITUTE_ACTION, advanced && (!firstTimeRun)); + + menuBar->Enable(WINDOW_ID_MENU_DEBUG, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_EXPORT_TEMPLATE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_EXPORT_UPGRADE, advanced && (!firstTimeRun)); + menuBar->Enable(WINDOW_ID_MENU_EXPORT_BUILD_INI, advanced && (!firstTimeRun)); +} + +void wxWidgetsFrame::OnAdvanced(wxCommandEvent &event) +{ + wxString configKey; + wxString configValue; + configKey="/General/advancedmenus"; + + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + advanced=(configValue.CmpNoCase("Y")==0); + if (advanced) + { + configValue="n"; + } + else + { + configValue="y"; + } + globalStatistics.configData.WriteTextValue(configKey,configValue); + SetMenuItems(); +} + +wxWidgetsFrame::~wxWidgetsFrame() +{ + scheduleTimer.Stop(); +} + +void wxWidgetsFrame::OnTimerTick(wxTimerEvent& event) +{ + wxStatusBar *statusBar; + bool needsToRun; + long timeLeft; + long hours; + long minutes; + long seconds; + wxString statusText; + ScheduleItem *schedule; + wxString schedulePrefix; + int scheduleIndex; + int fieldIndex; + wxString configKey; + wxString override; + + scheduleTimer.Stop(); + statusBar=GetStatusBar(); + + if ((statusBar!=NULL)&&(!runningWizard)) + { + for (scheduleIndex=0;scheduleIndex<2;scheduleIndex++) + { + override="y"; + switch (scheduleIndex) + { + case 0: + schedule=&globalStatistics.messageTimer; + schedulePrefix="Message Centre"; + configKey="/RCONSettings/Enabled"; + globalStatistics.configData.ReadTextValue(configKey,&override,"n"); + break; + case 1: + schedule=&globalStatistics.productionRunTimer; + schedulePrefix="Logfile Processing"; + break; + } + fieldIndex=scheduleIndex+1; + needsToRun=(schedule->TimeToRun(&timeLeft)&&(override.CmpNoCase("y")==0)); + if (needsToRun) + { + statusText.Printf("%s: Running",schedulePrefix.GetData()); + } + else + { + if ((schedule->disabled)||(override.CmpNoCase("n")==0)) + { + statusText.Printf("%s: Disabled", + schedulePrefix.GetData()); + } + else + { + hours=timeLeft/3600; + minutes=timeLeft-(hours*3600); + seconds=minutes % 60; + minutes/=60; + statusText.Printf("%s: %02ld:%02ld:%02ld", + schedulePrefix.GetData(), + hours,minutes,seconds); + } + } + SetStatusText(statusText,fieldIndex); + if (needsToRun) + { + TemplateFile templateFile; + + switch (scheduleIndex) + { + case 0: + globalStatistics.ReadServersFromConfig(); + globalStatistics.SendMessages(); + globalStatistics.ReadMessageTimerConfig(); + break; + case 1: + wxBusyCursor cursor; + globalStatistics.ProduceStatsInitiate(); + globalStatistics.ProduceStatsDownload(); + workerThread=new WorkerThread(wxTHREAD_JOINABLE); + if (workerThread!=NULL) + { + workerThread->Create(); + workerThread->SetPriority(globalStatistics.ReadPriority(true)); + workerThread->Run(); + workerThread->Wait(); + delete (workerThread); + } + workerThread=NULL; + globalStatistics.ProduceStatsTransfer(); + globalStatistics.ProduceStatsFinalise(); + + if (quitNow) + { + progress->DisableUpdate(); + Close(TRUE); + } + globalStatistics.ReadProductionRunTimerConfig(); + globalStatistics.ReadQuickRunTimerConfig(); + break; + } + } + } + } + scheduleTimer.Start(1000); +} + +void wxWidgetsFrame::OnDatabaseEmpty(wxCommandEvent& event) +{ + wxBusyCursor busy; + globalStatistics.statsgenDatabase.OpenDB(); + + globalStatistics.statsgenDatabase.Zap(); +} +void wxWidgetsFrame::OnGo(wxCommandEvent& event) +{ + wxString msg; + + globalStatistics.productionRunTimer.StartNow(); +} + +void wxWidgetsFrame::OnQuit(wxCommandEvent& event) +{ +// globalStatistics.webServer.StopServer(); + progress->DisableUpdate(); + Close(TRUE); +} + +void wxWidgetsFrame::OnEditScoreWeights(wxCommandEvent& event) +{ + wxString group="ScoreWeights"; + wxArrayString configKeys; + wxArrayString configValues; + int keyIndex; + int keyCount; + wxString key; + ServerTypePanel *serverType=new ServerTypePanel(); + + ConfigEditorGUI *gui; + + gui=new ConfigEditorGUI(this, + -1, + _T("Edit Score Weights"), + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + (BoxedDropDown *)NULL, + (BoxedDropDown *)serverType, + (GroupedConfigItemsPanel *)NULL, + false); + + globalStatistics.configData.ReadGroup(group, + configKeys, + configValues); + + keyCount=configKeys.GetCount(); + for (keyIndex=0;keyIndexAddConfigKey(group,key,true); + } + + gui->DisplayDialog(); + + delete gui; +} + +void wxWidgetsFrame::OnEditSkillWeights(wxCommandEvent& event) +{ + wxString group="SkillWeights"; + wxArrayString configKeys; + wxArrayString configValues; + int keyIndex; + int keyCount; + wxString key; + ServerTypePanel *serverType=new ServerTypePanel(); + SkillTypePanel *skillType=new SkillTypePanel(); + wxString configKey; + wxArrayString weaponGroups; + + weaponGroups=globalStatistics.configData.ReadWeaponGroups(); + + GroupedConfigItemsPanel *configPanel=new GroupedConfigItemsPanel("Negative Skill"); + + ConfigEditorGUI gui(this, + -1, + _T("Edit Skill Weights"), + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + (BoxedDropDown *)skillType, + (BoxedDropDown *)serverType, + configPanel, + false); + + configPanel->Create(&gui, + -1, + wxDefaultPosition, + wxDefaultSize); + configKey=globalStatistics.SkillCalculationTypeConfigKey(); + configPanel->AddBoolean("Allow Negative Skill",configKey,true); + globalStatistics.configData.ReadGroup(group, + configKeys, + configValues); + + WX_APPEND_ARRAY(configKeys,weaponGroups); + keyCount=configKeys.GetCount(); + for (keyIndex=0;keyIndexCreate(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + ftpSettings->CreateConfigs((char *)configGroup.GetData()); + remoteDirectory=new GroupedConfigItemsPanel("Remote Directory"); + remoteDirectory->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey="/website/FTPRemoteDirectory"; + remoteDirectory->AddRemoteDirectory("Remote Directory",configKey,"",-1,configGroup,&triggerList); + configPanel->AddConfigGroup(ftpSettings); + configPanel->AddConfigGroup(remoteDirectory); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); + } + else + { + GUIWizardPagesWebsite wizardPages; + RunWizard(&wizardPages); + } +} + +void wxWidgetsFrame::OnImagePackConfig(wxCommandEvent& event) +{ + GUIWizardPagesImagePacks wizardPages; + RunWizard(&wizardPages); +} + +void wxWidgetsFrame::OnTemplatePackConfig(wxCommandEvent& event) +{ + GUIWizardPagesTemplatePacks wizardPages; + RunWizard(&wizardPages); +} + +wxPanel *NewServerPanel(wxWindow *parentID,wxString &serverID) +{ + FTPConnectionPanel *ftpSettings; + GenericConfigPanel *configPanel; + GroupedConfigItemsPanel *serverType; + GroupedConfigItemsPanel *mainLogFile; + GroupedConfigItemsPanel *archiveLogFile; + GroupedConfigItemsPanel *banFile1; + GroupedConfigItemsPanel *banFile2; + wxString configGroup; + wxString configKey; + DirectoryConfigItemGUI *directoryGUI; + DirectoryConfigItemGUI *secondarydirectoryGUI; + RemoteDirectoryConfigItemGUI *remoteDirectoryGUI; + RemoteDirectoryConfigItemGUI *secondaryremoteDirectoryGUI; + wxArrayString serverTypeCodes; + wxArrayString serverTypeNames; + int serverTypeIndex; + wxString serverTypeCode; + wxString serverTypeName; + wxFileName baseDirectory(wxGetApp().argv[0]); + wxFileName logDirectory; + wxFileName archiveDirectory; + wxFileName banDirectory; + wxString logDirectoryName; + wxString archiveDirectoryName; + wxString banDirectoryName; + wxString baseDirectoryName; + wxString serverTypeConfigKey; + GUITriggerList ftpTriggerList; + GUITriggerList serverTypeTriggerList; + GUITriggerList serverTypeAndFtpTriggerList; + GUITriggerItem triggerItem; + wxString enabledKey; + wxArrayString wildCardCodes; + wxArrayString wildCardNames; + wxString code; + wxString name; + + code="$$DAY$$_$$MONTH$$_$$YEAR$$_gameserver.log"; + name="Tatakai Filename Format"; + wildCardCodes.Add(code); + wildCardNames.Add(name); + //baseDirectory=baseDirectory.GetPath(); + baseDirectory.AppendDir(serverID); + baseDirectory.MakeAbsolute(); + logDirectory=baseDirectory; + archiveDirectory=baseDirectory; + banDirectory=baseDirectory; + archiveDirectory.AppendDir("archivelogs"); + banDirectory.AppendDir("ban"); + logDirectory.AppendDir("logs"); + + logDirectoryName=logDirectory.GetPath(); + banDirectoryName=banDirectory.GetPath(); + archiveDirectoryName=archiveDirectory.GetPath(); + baseDirectoryName=baseDirectory.GetPath(); + + #ifdef _LINUX + mkdir(baseDirectoryName,0777); + mkdir(banDirectoryName,0777); + mkdir(logDirectoryName,0777); + mkdir(archiveDirectoryName,0777); + #else + wxMkDir(baseDirectoryName); + wxMkDir(banDirectoryName); + wxMkDir(logDirectoryName); + wxMkDir(archiveDirectoryName); + #endif + + for (serverTypeIndex=0;serverTypeIndexCreate(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + serverType->AddSelection("Server Type",serverTypeConfigKey,"COD2",serverTypeCodes,serverTypeNames); + + mainLogFile =new GroupedConfigItemsPanel("Main Log File"); + mainLogFile->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey.Printf("/%s/GuessTeamIDs",configGroup.GetData()); + mainLogFile->AddBoolean("Guess players team if none found",configKey,true); + + configKey.Printf("/%s/MaxLogfileSize",configGroup.GetData()); + mainLogFile->Add("Max Logfile Size in MB (0 for no maximum)",configKey,"0",-1); + configKey.Printf("/%s/latestDirectory",configGroup.GetData()); + directoryGUI=mainLogFile->AddDirectory("Latest Active Logfile Directory", + configKey, + (char *)logDirectoryName.GetData(),-1); + configKey.Printf("/%s/latestFilename",configGroup.GetData()); + mainLogFile->AddFile("Latest Active Logfile Name",configKey,"",-1,directoryGUI); + + configKey.Printf("/%s/FTPLatestDirectory",configGroup.GetData()); + remoteDirectoryGUI=mainLogFile->AddRemoteDirectory("Remote Active Logfile Directory",configKey,"",-1,configGroup,&ftpTriggerList); + configKey.Printf("/%s/FTPLatestFilename",configGroup.GetData()); + mainLogFile->AddRemoteFile("Remote Active Logfile Name",configKey,"",-1,configGroup,remoteDirectoryGUI,&ftpTriggerList); + + // Quake Wars bollox :-( + configKey.Printf("/%s/secondarylatestDirectory",configGroup.GetData()); + secondarydirectoryGUI=mainLogFile->AddDirectory("(Quake Wars Objective) Latest Active Logfile Directory", + configKey, + (char *)logDirectoryName.GetData(),-1,&serverTypeTriggerList); + configKey.Printf("/%s/secondarylatestFilename",configGroup.GetData()); + mainLogFile->AddFile("(Quake Wars Objective) Latest Active Logfile Name",configKey,"",-1,secondarydirectoryGUI,&serverTypeTriggerList); + + configKey.Printf("/%s/FTPSecondaryLatestDirectory",configGroup.GetData()); + secondaryremoteDirectoryGUI=mainLogFile->AddRemoteDirectory("(Quake Wars Objective) Remote Active Logfile Directory",configKey,"",-1,configGroup,&serverTypeAndFtpTriggerList); + configKey.Printf("/%s/FTPSecondaryLatestFilename",configGroup.GetData()); + mainLogFile->AddRemoteFile("(Quake Wars Objective) Remote Active Logfile Name",configKey,"",-1,configGroup,secondaryremoteDirectoryGUI,&serverTypeAndFtpTriggerList); + + + archiveLogFile =new GroupedConfigItemsPanel("Archive Log Files"); + archiveLogFile->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey.Printf("/%s/archiveDirectory",configGroup.GetData()); + archiveLogFile->AddDirectory("Archive Directory", + configKey, + (char *)archiveDirectoryName.GetData(),-1); + configKey.Printf("/%s/archiveWildcard",configGroup.GetData()); + archiveLogFile->AddSelectionFreeForm("Archive Wildcard",configKey,"",wildCardCodes,wildCardNames,-1); + configKey.Printf("/%s/FTPArchiveDirectory",configGroup.GetData()); + remoteDirectoryGUI=archiveLogFile->AddRemoteDirectory("Remote Archive Directory",configKey,"",-1,configGroup,&ftpTriggerList); + configKey.Printf("/%s/FTPArchiveWildcard",configGroup.GetData()); + //archiveLogFile->Add("Remote Archive Wildcard",configKey,"",-1,&ftpTriggerList); + archiveLogFile->AddSelectionFreeForm("Remote Archive Wildcard",configKey,"",wildCardCodes,wildCardNames,-1,&ftpTriggerList); + + // More quake war bollox + configKey.Printf("/%s/secondaryarchiveDirectory",configGroup.GetData()); + archiveLogFile->AddDirectory("(Quake Wars Objective) Archive Directory", + configKey, + (char *)archiveDirectoryName.GetData(),-1,&serverTypeTriggerList); + configKey.Printf("/%s/secondaryarchiveWildcard",configGroup.GetData()); + //archiveLogFile->Add("(Quake Wars Objective) Archive Wildcard",configKey,"",-1,&serverTypeTriggerList); + archiveLogFile->AddSelectionFreeForm("(Quake Wars Objective) Archive Wildcard",configKey,"",wildCardCodes,wildCardNames,-1,&serverTypeTriggerList); + configKey.Printf("/%s/FTPSecondaryArchiveDirectory",configGroup.GetData()); + secondaryremoteDirectoryGUI=archiveLogFile->AddRemoteDirectory("(Quake Wars Objective) Remote Archive Directory",configKey,"",-1,configGroup,&serverTypeAndFtpTriggerList); + configKey.Printf("/%s/FTPSecondaryArchiveWildcard",configGroup.GetData()); + //archiveLogFile->Add("(Quake Wars Objective) Remote Archive Wildcard",configKey,"",-1,&serverTypeAndFtpTriggerList); + archiveLogFile->AddSelectionFreeForm("(Quake Wars Objective) Remote Archive Wildcard",configKey,"",wildCardCodes,wildCardNames,-1,&serverTypeTriggerList); + + banFile1 =new GroupedConfigItemsPanel("Ban File 1"); + banFile1->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + banFile2 =new GroupedConfigItemsPanel("Ban File 2"); + banFile2->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + wxArrayString banCodes; + wxArrayString banNames; + wxString banCode; + wxString banName; + + banCode="PUNKBUSTER";banName="Punk Buster";banCodes.Add(banCode);banNames.Add(banName); + banCode="COD";banName="Call Of Duty";banCodes.Add(banCode);banNames.Add(banName); + + configKey.Printf("/%s/banFile1Type",configGroup.GetData()); + banFile1->AddSelection("Ban File Type",configKey,"PUNKBUSTER",banCodes,banNames); + configKey.Printf("/%s/FTPBanFile1Directory",configGroup.GetData()); + remoteDirectoryGUI=banFile1->AddRemoteDirectory("Remote Ban 1 File Directory",configKey,"",-1,configGroup,&ftpTriggerList); + configKey.Printf("/%s/FTPBanFile1Filename",configGroup.GetData()); + banFile1->AddRemoteFile("Remote Ban 1 File Filename",configKey,"",-1,configGroup,remoteDirectoryGUI,&ftpTriggerList); + configKey.Printf("/%s/Ban1Directory",configGroup.GetData()); + directoryGUI=banFile1->AddDirectory("Local Ban Directory", + configKey, + (char *)banDirectoryName.GetData(),-1); + + configKey.Printf("/%s/banFile2Type",configGroup.GetData()); + banFile2->AddSelection("Ban File Type",configKey,"COD",banCodes,banNames); + configKey.Printf("/%s/FTPBanFile2Directory",configGroup.GetData()); + remoteDirectoryGUI=banFile2->AddRemoteDirectory("Remote Ban 2 File Directory",configKey,"",-1,configGroup,&ftpTriggerList); + configKey.Printf("/%s/FTPBanFile2Filename",configGroup.GetData()); + banFile2->AddRemoteFile("Remote Ban 2 File Filename",configKey,"",-1,configGroup,remoteDirectoryGUI,&ftpTriggerList); + configKey.Printf("/%s/Ban2Directory",configGroup.GetData()); + directoryGUI=banFile2->AddDirectory("Local Ban Directory", + configKey, + (char *)banDirectoryName.GetData(),-1); + +// configKey.Printf("/%s/serverType",configGroup.GetData()); +// mainLogFile->Add("Server Type",configKey,"",-1); + + ftpSettings=new FTPConnectionPanel(); + ftpSettings->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + ftpSettings->CreateConfigs((char *)configGroup.GetData()); + configPanel->AddConfigGroup(serverType); + configPanel->AddConfigGroup(ftpSettings); + configPanel->AddConfigGroup(mainLogFile); + configPanel->AddConfigGroup(archiveLogFile); + configPanel->AddConfigGroup(banFile1); + configPanel->AddConfigGroup(banFile2); + + return (configPanel); + +} + +void wxWidgetsFrame::OnServerConfig(wxCommandEvent& event) +{ + if (advanced) + { + wxString title="Server Config"; + wxString listGroup="SERVERS"; + wxString listPrefix="Server"; + wxSize dialogSize(800,600); + + GenericNumberedConfigGUI gui( + NewServerPanel, + listGroup, + listPrefix, + this, + -1, + title, + wxDefaultPosition, + dialogSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + gui.DisplayDialog(); + } + else + { + GUIWizardPagesServers wizardPages; + RunWizard(&wizardPages); + } + globalStatistics.ClearServers(); + globalStatistics.ReadServersFromConfig(); +} + +wxPanel *NewClanPanel(wxWindow *parentID,wxString &clanID) +{ + ClanEditorPanel *configPanel; + wxString configGroup; + + configGroup="Clan"+clanID; + configPanel=new ClanEditorPanel(configGroup, + parentID, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("PANEL")); + + return (configPanel); + +} + +void wxWidgetsFrame::OnClanConfig(wxCommandEvent& event) +{ + wxString title="Clan Config"; + wxString listGroup="CLANS"; + wxString listPrefix="Clan"; + wxSize guiSize(512,400); + + GenericNumberedConfigGUI gui( + NewClanPanel, + listGroup, + listPrefix, + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + gui.DisplayDialog(); +} + +GenericConfigPanel *NewRCONServerPanel(wxWindow *parentID,wxString &serverID); +void wxWidgetsFrame::OnRCONSpamConfig(wxCommandEvent& event) +{ + wxString title="RCON Spamming Config"; + wxString listGroup="SERVERS"; + wxString listPrefix="Server"; + wxString configKey; + GroupedConfigItemsPanel *commonConfigs; + GenericNumberedConfigPanel *serverSpecificConfigs; + GenericConfigPanel *configPanel; + GUITriggerList triggerList; + GUITriggerItem triggerItem; + + GenericConfigGUI gui(this, + -1, + title, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + + configPanel=new GenericConfigPanel(&gui, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("PANEL")); + + // Panel holds the various boxed configs + serverSpecificConfigs=new GenericNumberedConfigPanel + ( + NewRCONServerPanel, + listGroup, + listPrefix, + configPanel, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("")); + serverSpecificConfigs->CreateDialog(); + + commonConfigs=new GroupedConfigItemsPanel("Common RCON Settings"); + commonConfigs->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey="/RCONSettings/Enabled"; + commonConfigs->AddBoolean("Message Center Enabled",configKey,false); + triggerItem.SetPositiveDisableTrigger(configKey,"N"); + triggerList.Add(triggerItem); + + configKey="/RCONSettings/MessageIntervalTimer"; + commonConfigs->Add("Message Interval In Seconds",configKey,"60",5,&triggerList); + configKey="/RCONSettings/CustomMessageInterval"; + commonConfigs->Add("Custom Message Interval",configKey,"0",5,&triggerList); + configKey="/RCONSettings/MessagePrefix"; + commonConfigs->Add("Message Prefix",configKey,"^7",-1,&triggerList); + configKey="/RCONSettings/ClientPort"; + commonConfigs->Add("Local TCP/IP Port",configKey,"8000",5,&triggerList); + + configPanel->AddConfigGroup(commonConfigs); + configPanel->AddConfigGroup(serverSpecificConfigs); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); + globalStatistics.InitiateMessageCentres(); +} + +GenericConfigPanel *NewRCONServerPanel(wxWindow *parentID,wxString &serverID) +{ + GenericConfigPanel *configPanel; + GroupedConfigItemsPanel *punkBusterSettings; + GroupedConfigItemsPanel *gameServer; + wxString configGroup; + wxString configKey; + GUITriggerList triggerList; + GUITriggerList mainTriggerList; + GUITriggerList pbTriggerList; + GUITriggerItem triggerItem; + wxString usePunkbusterKey; + + configGroup="Server"+serverID; + usePunkbusterKey.Printf("/%s/RCONUsePunkBuster",configGroup.GetData()); + + configKey="/RCONSettings/Enabled"; + triggerItem.SetPositiveDisableTrigger(configKey,"N"); + triggerList.Add(triggerItem); + mainTriggerList.Add(triggerItem); + pbTriggerList.Add(triggerItem); + + configKey.Printf("/%s/MessagingEnabled",configGroup.GetData()); + triggerItem.SetPositiveDisableTrigger(configKey,"N"); + triggerList.Add(triggerItem); + pbTriggerList.Add(triggerItem); + + triggerItem.SetPositiveDisableTrigger(usePunkbusterKey,"N"); + pbTriggerList.Add(triggerItem); + + configPanel=new GenericConfigPanel(parentID, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("PANEL")); + + // Panels holds the various boxed configs + punkBusterSettings=new GroupedConfigItemsPanel("PunkBuster Settings"); + punkBusterSettings->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + punkBusterSettings->AddBoolean("Use Punkbuster Scheduled Tasks",usePunkbusterKey,false,&triggerList); + configKey.Printf("/%s/PunkBusterPostCommand",configGroup.GetData()); + punkBusterSettings->Add("Post Messaging PB Command",configKey,"",-1,&pbTriggerList); + configKey.Printf("/%s/FTPBanFile1Directory",configGroup.GetData()); + punkBusterSettings->AddRemoteDirectory("Remote Ban 1 File Directory",configKey,"",-1,configGroup,&pbTriggerList); + configKey.Printf("/%s/FTPBanFile2Directory",configGroup.GetData()); + punkBusterSettings->AddRemoteDirectory("Remote Ban 2 File Directory",configKey,"",-1,configGroup,&pbTriggerList); + + + gameServer =new GroupedConfigItemsPanel("Game Server Settings"); + gameServer->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + configKey.Printf("/%s/MessagingEnabled",configGroup.GetData()); + gameServer->AddBoolean("Messaging Enabled",configKey,false,&mainTriggerList); + configKey.Printf("/%s/gameIP",configGroup.GetData()); + gameServer->Add("Game IP (if different from FTP Hostname)",configKey,"",-1,&triggerList); + configKey.Printf("/%s/gamePort",configGroup.GetData()); + gameServer->Add("Game Port",configKey,"",5,&triggerList); + configKey.Printf("/%s/RCONPassword",configGroup.GetData()); + gameServer->Add("RCON Password",configKey,"",-1,&triggerList); + + configPanel->AddConfigGroup(gameServer); + configPanel->AddConfigGroup(punkBusterSettings); + return (configPanel); + +} + +void wxWidgetsFrame::OnAliasConfig(wxCommandEvent& event) +{ + wxString title="Alias Config"; + wxSize guiSize(512,500); + + AliasDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + gui.DisplayDialog(); +} + +wxPanel *NewAwardPanel(wxWindow *parentID,wxString &awardID) +{ + AwardEditorPanel *awardPanel; + + // Panels holds the various boxed configs + awardPanel=new AwardEditorPanel( + parentID, + -1, + wxDefaultPosition, + wxSize(640,480), + 0, + _T(""), + awardID); + + awardPanel->Enable(); + return (awardPanel); +} + +void wxWidgetsFrame::OnAwardConfig(wxCommandEvent& event) +{ + wxString title="Award Editor"; + wxString listGroup="AWARDLIST"; + wxString listPrefix="AWARDDEFINITION"; + + GenericNumberedConfigGUI gui( + NewAwardPanel, + listGroup, + listPrefix, + this, + -1, + title, + wxDefaultPosition, + wxSize(640,480), + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnLogSubstitute(wxCommandEvent& event) +{ + wxString group; + wxString title; + wxArrayString configKeys; + wxArrayString configValues; + int keyIndex; + int keyCount; + wxString key; + ServerTypePanel *serverType=new ServerTypePanel(); + + switch (event.GetId()) + { + case WINDOW_ID_MENU_LOG_SUBSTITUTE_GAMETYPE: + title-"Edit Logfile Substitutions For Game Types"; + group="LogSubstituteGAMETYPE"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_MAP: + title-"Edit Logfile Substitutions For Maps"; + group="LogSubstituteMAP"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_CLASS: + title-"Edit Logfile Substitutions For Player Class"; + group="LogSubstituteCLASS"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_TEAM: + title-"Edit Logfile Substitutions For Teams"; + group="LogSubstituteTEAM"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPON: + title-"Edit Logfile Substitutions For Weapons"; + group="LogSubstituteWEAPON"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_AMMO: + title-"Edit Logfile Substitutions For Ammo"; + group="LogSubstituteAMMO"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPONAMMO: + title-"Edit Logfile Substitutions For Weapon And Ammo Combinations"; + group="LogSubstituteWEAPONAMMO"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_LOCATION: + title-"Edit Logfile Substitutions For Locations"; + group="LogSubstituteLOCATION"; + break; + case WINDOW_ID_MENU_LOG_SUBSTITUTE_ACTION: + title-"Edit Logfile Substitutions For Actions"; + group="LogSubstituteACTION"; + break; + } + ConfigEditorGUI gui(this, + -1, + title, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + (BoxedDropDown *)serverType, + (BoxedDropDown *)NULL, + (GroupedConfigItemsPanel *)NULL, + false); + + globalStatistics.configData.ReadGroup(group, + configKeys, + configValues); + + keyCount=configKeys.GetCount(); + for (keyIndex=0;keyIndexCreate(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey.Printf("/Debug/Step%s",STEP_CREATE_DATABASE); + commonConfigs->AddBoolean("Create Database",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_APPLY_ALIASES); + commonConfigs->AddBoolean("Apply Aliases",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_DOWNLOAD_LOGS); + commonConfigs->AddBoolean("Download Logs",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_DATABASE_READ_STATIC); + commonConfigs->AddBoolean("Read Static",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_EMPTY_DATABASE); + commonConfigs->AddBoolean("Empty Database",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_CREATE_LOG_FILES); + commonConfigs->AddBoolean("Create Logs",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_PROCESS_LOG_FILES); + commonConfigs->AddBoolean("Process Logs",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_DROP_PLAYERS); + commonConfigs->AddBoolean("Drop Players",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_CALCULATE_SCORES); + commonConfigs->AddBoolean("Calculate Scores",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_WRITE_DATABASE); + commonConfigs->AddBoolean("Write Database",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_READ_TEMPLATE); + commonConfigs->AddBoolean("Read Template",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_PROCESS_TEMPLATE); + commonConfigs->AddBoolean("Process Template",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_POST_PROCESS_TEMPLATE); + commonConfigs->AddBoolean("Post Process Template",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_TRANSFER_DATABASE); + commonConfigs->AddBoolean("Transfer Database",configKey,true); + + configKey.Printf("/Debug/Step%s",STEP_WEBSITE); + commonConfigs->AddBoolean("Website Transfer",configKey,true); + + debugLevels=new GroupedConfigItemsPanel("Debug Levels 0 (off) - 3 (max)"); + debugLevels->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + int panelIndex; + wxString debugTitle; + + configKey="/Debug/DebugFile"; + debugLevels->AddFile("Debug File (blank for no debug)",configKey,"",-1,NULL); + for (panelIndex=WINDOW_ID_PROGRESS_PANEL_GENERAL; + panelIndexAdd((char *)debugTitle.GetData(),configKey,"0",1); + } + + configPanel->AddConfigGroup(commonConfigs); + configPanel->AddConfigGroup(debugLevels); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); + + STATSGEN_DEBUG_INITIATE +} + +void wxWidgetsFrame::OnOutputConfig(wxCommandEvent& event) +{ + wxString title="Output Config"; + wxString defaultValue; + GroupedConfigItemsPanel *databaseConfig; + GroupedConfigItemsPanel *fullTemplateConfig; + GroupedConfigItemsPanel *outputConfig; + wxString configKey; + wxString configGroup="website"; + + GenericConfigGUI gui(this, + -1, + title, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + GenericConfigPanel *configPanel; + + configPanel=new GenericConfigPanel(&gui, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("PANEL")); + + // Panel holds the various boxed configs + databaseConfig=new GroupedConfigItemsPanel("Database Config"); + databaseConfig->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + wxString dbFilename=BaseDirectoryFileName("statsgen2.db").GetFullPath(); + configKey="/Database/filename"; + databaseConfig->AddFile("Database File",configKey,(char *)dbFilename.GetData(),-1,NULL); + configKey="/Database/CreateIndexes"; + databaseConfig->AddBoolean("Create Indexes",configKey,true); + + fullTemplateConfig=new GroupedConfigItemsPanel("Template Config"); + fullTemplateConfig->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey="/Template/FullRun"; + fullTemplateConfig->AddFile("Template",configKey,"",-1,NULL); + configKey="/Schedule/ProductionRun"; + defaultValue="00:00:00,86400"; + fullTemplateConfig->AddSchedule("Schedule",configKey,defaultValue,true); + + outputConfig=new GroupedConfigItemsPanel("Local Output Config"); + outputConfig->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + configKey="/General/LocalOutput"; + outputConfig->AddDirectory("Local Output Location",configKey,"",-1); + + configKey=CONFIG_KEY_SPEECHFILE; + outputConfig->AddFile("Speech File (blank for none)",configKey,"",-1); + configPanel->AddConfigGroup(databaseConfig); + configPanel->AddConfigGroup(fullTemplateConfig); + configPanel->AddConfigGroup(outputConfig); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); + globalStatistics.ReadProductionRunTimerConfig(); + globalStatistics.ReadQuickRunTimerConfig(); +} + +void wxWidgetsFrame::OnTemplateConfig(wxCommandEvent& event) +{ + wxString group="TemplateConfigs"; + wxArrayString configKeys; + wxArrayString configValues; + int keyIndex; + int keyCount; + wxString key; + ServerTypePanel *serverType=NULL; + ImageTypePanel *imageType=NULL; + ConfigEditorGUI gui(this, + -1, + _T("Edit Template Config Items"), + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + (BoxedDropDown *)imageType, + (BoxedDropDown *)serverType, + (GroupedConfigItemsPanel *)NULL, + false); + + globalStatistics.configData.ReadGroup(group, + configKeys, + configValues); + + keyCount=configKeys.GetCount(); + for (keyIndex=0;keyIndexCreateWizardPages(&wizard); + wizard.SetInitialPageLinks(); + wizard.FitToPage(wizard.GetFirstPage()); + wizard.RunWizard(wizard.GetFirstPage()); + runningWizard=false; +} + +void wxWidgetsFrame::OnPlayerDataAvatarConfig(wxCommandEvent& event) +{ + wxString title="Avatar Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Avatar Image Reference Here"; + wxString playerTitle="Avatar Reference"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataAvatars, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataPictureConfig(wxCommandEvent& event) +{ + wxString title="Personal Picture Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Personal Picture Reference Here"; + wxString playerTitle="Personal Picture Reference"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataPicture, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataWebsiteConfig(wxCommandEvent& event) +{ + wxString title="Personal Website Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Personal Website Reference Here"; + wxString playerTitle="Personal Website Reference"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataWebsite, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataXfireConfig(wxCommandEvent& event) +{ + wxString title="Personal Xfire Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Xfire ID Here"; + wxString playerTitle="Xfire ID"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataXfire, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataClanRoleConfig(wxCommandEvent& event) +{ + wxString title="Clan Role Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Clan Role Here"; + wxString playerTitle="Clan Role"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataClanRole, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataRealNameConfig(wxCommandEvent& event) +{ + wxString title="Real Name Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Real Name Here"; + wxString playerTitle="Real Name"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataRealName, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataMisc1Config(wxCommandEvent& event) +{ + wxString title="Miscellaneous Data 1 Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Data Here"; + wxString playerTitle="Data"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataMisc1, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnPlayerDataMisc2Config(wxCommandEvent& event) +{ + wxString title="Miscellaneous Data 2 Editor"; + wxSize guiSize(768,600); + wxString playerDefaultValue="Insert Data Here"; + wxString playerTitle="Data"; + + PlayerDataDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + globalStatistics.playerDataMisc2, + playerDefaultValue, + playerTitle); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnBadWordsListConfig(wxCommandEvent& event) +{ + wxString title="Bad Words List Editor"; + wxSize guiSize(300,400); + + TextListDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + "BannedSpeech"); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnHelp(wxCommandEvent& event) +{ + m_advancedHtmlHelp.DisplayContents(); +} + +void wxWidgetsFrame::OnCustomMessagesConfig(wxCommandEvent& event) +{ + wxString title="Custom Message List"; + wxSize guiSize(300,400); + + TextListDialog gui( + this, + -1, + title, + wxDefaultPosition, + guiSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T(""), + "CustomMessages"); + gui.SortOn(false); + gui.SingleWords(false); + + gui.DisplayDialog(); +} + +void wxWidgetsFrame::CopyGroupToFile(const char *groupID,FILE *fp) +{ + wxArrayString keys; + wxArrayString values; + int keyCount; + int keyIndex; + wxString key; + wxString value; + wxString groupIDStr; + + groupIDStr=groupID; + globalStatistics.configData.ReadGroup(groupIDStr,keys,values); + keyCount=keys.GetCount(); + fprintf(fp,"[%s]\n",groupID); + for (keyIndex=0;keyIndex0) + { + globalStatistics.GenerateUpgrade(upgradeFilename); + } +} + +void wxWidgetsFrame::ManualUpgrade() +{ + wxString title="Select The Upgrade File And Then Press Perform Upgrade Button"; + wxSize dialogSize(600,250); + wxString name="performupgrade"; + long style= wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX; + + PerformUpgradeDialog dialog(this, + -1, + title, + wxDefaultPosition, + dialogSize, + style, + name); + globalStatistics.statsgenDatabase.OpenDB(); + + dialog.DisplayDialog(); +} + +void wxWidgetsFrame::Upgrade() +{ + UpgradeConfig(); + UpgradeTemplate(); + UpgradeDatabase(); +} + +void wxWidgetsFrame::UpgradeDatabase() +{ + wxString configKey; + wxString configValue; + int buildVersion; + wxString message; + + configKey="/General/DatabaseVersion"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + buildVersion=atoi(configValue.GetData()); + configValue.Printf("%d",DATABASE_VERSION); + globalStatistics.configData.WriteTextValue(configKey,configValue); + if (buildVersionCreate(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey="/ExternalDatabase/Enabled"; + databaseConfig->AddBoolean("Enabled",configKey,false); + + triggerItem.SetPositiveDisableTrigger(configKey,"N"); + triggerList.Add(triggerItem); + + configKey="/ExternalDatabase/CreateIndexes"; + databaseConfig->AddBoolean("Create Table Indexes",configKey,true,&triggerList); + + configKey="/ExternalDatabase/Hostname"; + databaseConfig->Add("Hostname",configKey,"",-1,&triggerList); + + configKey="/ExternalDatabase/Username"; + databaseConfig->Add("Username",configKey,"",-1,&triggerList); + + configKey="/ExternalDatabase/Password"; + databaseConfig->Add("Password",configKey,"",-1,&triggerList); + + configKey="/ExternalDatabase/DatabaseName"; + databaseConfig->Add("Database Name",configKey,"statsgen",-1,&triggerList); + + configKey="/ExternalDatabase/Port"; + databaseConfig->Add("Port",configKey,"3306",5,&triggerList); + + configPanel->AddConfigGroup(databaseConfig); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); +} + +void wxWidgetsFrame::OnConfigThread(wxCommandEvent& event) +{ + wxString title="Change Running Priorities, 0 = Low, 100 = High"; + wxSize dialogSize(400,150); + wxString name="threadconfig"; + long style= wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX; + GenericOKCancelDialog dialog(this, + -1, + title, + wxDefaultPosition, + dialogSize, + style, + name); + PriorityPanel *priorityPanel=new PriorityPanel(); + priorityPanel->Create(&dialog, + -1, + wxDefaultPosition, + wxDefaultSize, + wxTAB_TRAVERSAL, + _T("PANEL")); + + dialog.DisplayDialog(priorityPanel); + globalStatistics.configData.CommitChanges(); + +} + +WorkerThread::WorkerThread(wxThreadKind threadKind):wxThread(threadKind) +{ +} + +void * WorkerThread::Entry() +{ + globalStatistics.currentRunningThread=this; + globalStatistics.ProduceStatsProcess(); + return NULL; +} + +void WorkerThread::SetRunType(bool runTypeIn,wxArrayInt &allowedStepsIn,TemplateFile *templateFileIn) +{ + runType=runTypeIn; + allowedSteps=allowedStepsIn; + templateFile=templateFileIn; +} + +void WorkerThread::Exit(void *exitCode) +{ + globalStatistics.currentRunningThread=NULL; +} +void wxWidgetsFrame::OnProgressUpdate(wxCommandEvent& event) +{ + STATSGEN_DEBUG_FUNCTION_START("wxWidgetsFrame","OnProgressUpdate") + wxString eventString=event.GetString(); + + + wxSafeYield(); + if (progress->GetEventUpdating()) + { + switch (event.GetId()) + { + case EVENT_ID_PROGRESS_STATUS_TEXT: + wxStaticText *label; + label=(wxStaticText *)event.GetClientData(); + if (label!=NULL) + { + label->SetLabel(eventString); + progress->UpdateColouredBar(); + } + break; + case EVENT_ID_PROGRESS_BUTTON: + wxBitmapButton *button; + wxBitmap bitmap=ProgressPanel::SeverityImage(event.GetInt()); + button=(wxBitmapButton *)event.GetClientData(); + if (button!=NULL) + { + button->SetBitmapLabel(bitmap); + } + break; + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void wxWidgetsFrame::OnWebServerConfig(wxCommandEvent& event) +{ + wxString title="Internal Web Server Config"; + wxString defaultValue; + GroupedConfigItemsPanel *webserverConfig; + wxString configKey; + GUITriggerList triggerList; + GUITriggerItem triggerItem; + + GenericConfigGUI gui(this, + -1, + title, + wxDefaultPosition, + wxDefaultSize, + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + _T("")); + + GenericConfigPanel *configPanel; + + configPanel=new GenericConfigPanel(&gui, + -1, + wxDefaultPosition, + wxDefaultSize, + 0, + _T("PANEL")); + + // Panel holds the various boxed configs + webserverConfig=new GroupedConfigItemsPanel("Internal Web Server Config"); + webserverConfig->Create(configPanel, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey=globalStatistics.webServer.ConfigKeyEnabled(); + webserverConfig->AddBoolean("Enabled",configKey,false); + + triggerItem.SetPositiveDisableTrigger(configKey,"N"); + triggerList.Add(triggerItem); + + configKey=globalStatistics.webServer.ConfigKeyPort(); + webserverConfig->Add("Listen Port",configKey,"9000",-1,&triggerList); + + configKey=globalStatistics.webServer.ConfigKeyAdminUser(); + webserverConfig->Add("Admin Username",configKey,"",-1,&triggerList); + + configKey=globalStatistics.webServer.ConfigKeyAdminPassword(); + webserverConfig->Add("Admin Password",configKey,"",-1,&triggerList); + + configPanel->AddConfigGroup(webserverConfig); + + gui.SetConfigPanel(configPanel); + gui.DisplayDialog(); + +// globalStatistics.webServer.StartServer(); +} +/* +void wxWidgetsFrame::OnTimerTickOrg(wxTimerEvent& event) +{ + wxStatusBar *statusBar; + bool needsToRun; + long timeLeft; + long hours; + long minutes; + long seconds; + wxString statusText; + ScheduleItem *schedule; + wxString schedulePrefix; + int scheduleIndex; + int fieldIndex; + wxString configKey; + wxString override; + wxArrayInt allowedStepsDownload; + wxArrayInt allowedStepsProcess; + wxArrayInt allowedStepsTransferDatabase; + wxArrayInt allowedStepsTemplate; + wxArrayInt allowedStepsWebsite; + bool quickTemplateEnabled; + + + quickTemplateEnabled=false; + allowedStepsDownload.Add(WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS); + + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES2); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE); + allowedStepsProcess.Add(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); + + allowedStepsTransferDatabase.Add(WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE); + + allowedStepsTemplate.Add(WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE); + allowedStepsTemplate.Add(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); + + allowedStepsWebsite.Add(WINDOW_ID_PROGRESS_PANEL_WEBSITE); + + scheduleTimer.Stop(); + statusBar=GetStatusBar(); + + if (statusBar!=NULL) + { + for (scheduleIndex=0;scheduleIndex<3;scheduleIndex++) + { + override="y"; + switch (scheduleIndex) + { + case 0: + schedule=&globalStatistics.messageTimer; + schedulePrefix="Message"; + configKey="/RCONSettings/Enabled"; + globalStatistics.configData.ReadTextValue(configKey,&override,"n"); + break; + case 1: + schedule=&globalStatistics.quickRunTimer; + schedulePrefix="Quick"; + break; + case 2: + schedule=&globalStatistics.productionRunTimer; + schedulePrefix="Full"; + break; + } + fieldIndex=scheduleIndex+1; + needsToRun=(schedule->TimeToRun(&timeLeft)&&(override.CmpNoCase("y")==0)); + if (needsToRun) + { + statusText.Printf("%s: Running",schedulePrefix.GetData()); + } + else + { + if ((schedule->disabled)||(override.CmpNoCase("n")==0)) + { + statusText.Printf("%s: Disabled", + schedulePrefix.GetData()); + if (scheduleIndex==1) + { + quickTemplateEnabled=true; + } + } + else + { + hours=timeLeft/3600; + minutes=timeLeft-(hours*3600); + seconds=minutes % 60; + minutes/=60; + statusText.Printf("%s: %02ld:%02ld:%02ld", + schedulePrefix.GetData(), + hours,minutes,seconds); + } + } + SetStatusText(statusText,fieldIndex); + if (needsToRun) + { + TemplateFile templateFile; + + switch (scheduleIndex) + { + case 0: + globalStatistics.ReadServersFromConfig(); + globalStatistics.SendMessages(); + globalStatistics.ReadMessageTimerConfig(); + break; + case 1: + globalStatistics.ReadServersFromConfig(); + globalStatistics.ProduceStats(false,allowedStepsDownload,templateFile); + workerThread=new WorkerThread(wxTHREAD_JOINABLE); + if (workerThread!=NULL) + { + workerThread->SetRunType(false,allowedStepsProcess,&templateFile); + workerThread->Create(); + workerThread->SetPriority(globalStatistics.ReadPriority(false)); + workerThread->Run(); + workerThread->Wait(); + delete (workerThread); + } + workerThread=NULL; + globalStatistics.ProduceStats(false,allowedStepsTransferDatabase,templateFile); + + workerThread=new WorkerThread(wxTHREAD_JOINABLE); + if (workerThread!=NULL) + { + workerThread->SetRunType(false,allowedStepsTemplate,&templateFile); + workerThread->Create(); + workerThread->SetPriority(globalStatistics.ReadPriority(false)); + workerThread->Run(); + workerThread->Wait(); + delete (workerThread); + } + workerThread=NULL; + globalStatistics.ProduceStats(false,allowedStepsWebsite,templateFile); + + globalStatistics.ReadQuickRunTimerConfig(); + break; + + case 2: + globalStatistics.ClearServers(); + globalStatistics.ReadServersFromConfig(); + globalStatistics.ProduceStats(true,allowedStepsDownload,templateFile); + workerThread=new WorkerThread(wxTHREAD_JOINABLE); + if (workerThread!=NULL) + { + workerThread->SetRunType(true,allowedStepsProcess,&templateFile); + workerThread->Create(); + workerThread->SetPriority(globalStatistics.ReadPriority(true)); + workerThread->Run(); + workerThread->Wait(); + delete (workerThread); + } + workerThread=NULL; + globalStatistics.ProduceStats(true,allowedStepsTransferDatabase,templateFile); + + workerThread=new WorkerThread(wxTHREAD_JOINABLE); + if (workerThread!=NULL) + { + workerThread->SetRunType(true,allowedStepsTemplate,&templateFile); + workerThread->Create(); + workerThread->SetPriority(globalStatistics.ReadPriority(true)); + workerThread->Run(); + workerThread->Wait(); + delete (workerThread); + } + workerThread=NULL; + globalStatistics.ProduceStats(true,allowedStepsWebsite,templateFile); + if (quitNow) + { + progress->DisableUpdate(); + Close(TRUE); + } + globalStatistics.ReadProductionRunTimerConfig(); + globalStatistics.ReadQuickRunTimerConfig(); + if (!quickTemplateEnabled) + { + // If quick template not enabled we can release memory + globalStatistics.ResetProcessingStatus(); + } + + break; + } + } + } + } + scheduleTimer.Start(1000); +} +*/ + +void wxWidgetsFrame::OnResetRecovery(wxCommandEvent& event) +{ + progress->ClearErrors(); +} + +void wxWidgetsFrame::OnStoreProgress(wxCommandEvent& event) +{ + wxString filename; + wxString message="Where do you want to store the errors"; + + filename=wxFileSelector(message); + if (filename.Length()>0) + { + progress->StoreProgress(filename); + } +} + +void wxWidgetsFrame::OnEditWeaponGroups(wxCommandEvent& event) +{ + wxString name=""; + wxString title="Edit Weapon Groups"; + WeaponGroupDialog gui(this, + -1, + title, + wxDefaultPosition, + wxSize(640,480), + wxCAPTION | + wxCLOSE_BOX | + wxSYSTEM_MENU | + wxRESIZE_BORDER | + wxMAXIMIZE_BOX, + name); + + gui.DisplayDialog(); +} + diff --git a/StatsgenFrame.h b/StatsgenFrame.h new file mode 100644 index 0000000..cf822de --- /dev/null +++ b/StatsgenFrame.h @@ -0,0 +1,106 @@ +#ifndef __WXWIDGETSFRAME_H +#define __WXWIDGETSFRAME_H + +#include +#include +#include +#include +#include + +#include "TemplateFile.h" +#include "GUIWizards.h" + +class WorkerThread : public wxThread +{ + public: + WorkerThread(wxThreadKind); + virtual void * Entry(); + virtual void Exit(void * exitCode); + void SetRunType(bool runTypeIn, + wxArrayInt &allowedStepsIn, + TemplateFile *templateFileIn); + private: + bool runType; + wxArrayInt allowedSteps; + TemplateFile *templateFile; +}; + +class wxWidgetsFrame : public wxFrame +{ +public: + wxWidgetsFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + virtual ~wxWidgetsFrame(); + + void OnTimerTick(wxTimerEvent& event); + void OnProgressUpdate(wxCommandEvent& event); + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnConfigThread(wxCommandEvent& event); + void OnHelp(wxCommandEvent& event); + void OnWizard(wxCommandEvent &event); + void OnGo(wxCommandEvent& event); + void OnDatabaseEmpty(wxCommandEvent& event); + void OnEditScoreWeights(wxCommandEvent& event); + void OnEditSkillWeights(wxCommandEvent& event); + wxHtmlHelpController &GetAdvancedHtmlHelpController() + { return m_advancedHtmlHelp; } + void OnEditRealNames(wxCommandEvent& event); + void OnTemplateConfig(wxCommandEvent& event); + void OnEditImages(wxCommandEvent& event); + void OnEditMessageFormats(wxCommandEvent& event); + void OnWebsiteConfig(wxCommandEvent& event); + void OnImagePackConfig(wxCommandEvent& event); + void OnTemplatePackConfig(wxCommandEvent& event); + void OnFullConfig(wxCommandEvent& event); + void OnWebServerConfig(wxCommandEvent& event); + void OnOutputConfig(wxCommandEvent& event); + void OnExternalDatabaseConfig(wxCommandEvent& event); + void OnServerConfig(wxCommandEvent& event); + void OnRCONSpamConfig(wxCommandEvent& event); + void OnEditWeaponGroups(wxCommandEvent& event); + void OnLogSubstitute(wxCommandEvent& event); + void OnClanConfig(wxCommandEvent& event); + void OnAliasConfig(wxCommandEvent& event); + void OnDropListConfig(wxCommandEvent& event); + void OnBadWordsListConfig(wxCommandEvent& event); + void OnCustomMessagesConfig(wxCommandEvent& event); + void OnPlayerDataAvatarConfig(wxCommandEvent& event); + void OnPlayerDataPictureConfig(wxCommandEvent& event); + void OnPlayerDataXfireConfig(wxCommandEvent& event); + void OnPlayerDataWebsiteConfig(wxCommandEvent& event); + void OnPlayerDataClanRoleConfig(wxCommandEvent& event); + void OnPlayerDataRealNameConfig(wxCommandEvent& event); + void OnPlayerDataMisc1Config(wxCommandEvent& event); + void OnPlayerDataMisc2Config(wxCommandEvent& event); + void OnAwardConfig(wxCommandEvent& event); + void OnDebugConfig(wxCommandEvent& event); + void OnExportTemplate(wxCommandEvent& event); + void OnExportUpgrade(wxCommandEvent& event); + void OnPerformUpgrade(wxCommandEvent& event); + void OnAdvanced(wxCommandEvent& event); + void Upgrade(); + void UpgradeDatabase(); + void UpgradeTemplate(); + void UpgradeConfig(); + void ManualUpgrade(); + void OnResetRecovery(wxCommandEvent &event); + void OnStoreProgress(wxCommandEvent &event); + void SetMenuItems(); + void RunWizard(GUIWizardPages *wizardPages); + void CopyGroupToFile(const char *groupID,FILE *fp); + void CopyImagesToUpgradeFile(const char *upgradefilename,const char *filter); + void OnExportBuildINI(wxCommandEvent &event); + +private: + WorkerThread *workerThread; + bool quitNow; + wxTimer scheduleTimer; + wxHtmlHelpController m_advancedHtmlHelp; + bool advanced; + bool runningWizard; + DECLARE_CLASS(wxWidgetsFrame) + + DECLARE_EVENT_TABLE() +}; + +#endif //__WXWIDGETSFRAME_H diff --git a/StatsgenLog.cpp b/StatsgenLog.cpp new file mode 100644 index 0000000..3bedf15 --- /dev/null +++ b/StatsgenLog.cpp @@ -0,0 +1,38 @@ +// wx includes +#include "wx/log.h" + +// Statsgen Includes +#include "StatsgenLog.h" +#include "Progress.h" + +void StatsgenLog::DoLog(wxLogLevel level, + const char *msg, + time_t timestamp) +{ + int newSeverity; + wxString messageString; + + switch (level) + { + case wxLOG_FatalError: + case wxLOG_Error: + newSeverity=SeverityError; + break; + case wxLOG_Message: + case wxLOG_Status: + case wxLOG_Info: + newSeverity=SeverityOK; + break; + case wxLOG_Warning: + newSeverity=SeverityCaution; + break; + default: + newSeverity=SeverityCaution; + break; + } + + messageString=msg; + + progress->LogError(messageString,newSeverity); +} + diff --git a/StatsgenLog.h b/StatsgenLog.h new file mode 100644 index 0000000..82e5dd6 --- /dev/null +++ b/StatsgenLog.h @@ -0,0 +1,17 @@ +#ifndef __STATSGENLOG +#define __STATSGENLOG + +#include +#include + +// Statsgen Includes + +class StatsgenLog : public wxLog +{ + public: + virtual void DoLog(wxLogLevel level, + const char *msg, + time_t timestamp); +}; + +#endif diff --git a/StatsgenWeb.cpp b/StatsgenWeb.cpp new file mode 100644 index 0000000..6cf7330 --- /dev/null +++ b/StatsgenWeb.cpp @@ -0,0 +1,393 @@ +#include +#include + +#include "StatsgenWeb.h" +#include "StaticFunctions.h" +#include "WebFile.h" +#include "Website.h" +#include "GlobalStatistics.h" +#include "Progress.h" +#include "PerformUpgradeDialog.h" + +StatsgenWeb::StatsgenWeb() +{ +} + +StatsgenWeb::~StatsgenWeb() +{ +} + +wxString StatsgenWeb::Hostname() +{ + wxString retVal; + + retVal="www.statsgen.co.uk"; + //retVal="localhost"; + + return (retVal); +} + +WebFile *StatsgenWeb::GetWebFile(wxString &filepath) +{ + WebFile *retVal; + wxString hostname=Hostname(); + + retVal=new WebFile(hostname,filepath); + + return (retVal); +} + +bool StatsgenWeb::GetFileList(wxArrayString &fileDescriptions, + wxArrayString &filePaths, + wxArrayInt &fileTypes, + wxArrayString &fileServerTypes, + wxArrayString &secondFilePaths, + wxArrayString &templateFilenames, + wxArrayString &upgradeFiles, + wxArrayString &thumbnails) +{ + wxString localFilename; + wxString remoteFilename; + bool retVal; + wxString hostname=Hostname(); + wxString nodeName; + wxString nodeType; + wxString nodeAddress; + wxString nodeSecondAddress; + wxString nodeTemplateFilename; + wxString nodeServerType; + wxString nodeUpgradeFile; + wxString nodeThumbnail; + wxString nodeContent; + wxString property; + int nodeTypeInt; + + localFilename="contents.xml"; + remoteFilename="/contents.xml"; + + WebFile remoteFile(hostname,remoteFilename); + filePaths.Clear(); + secondFilePaths.Clear(); + fileTypes.Clear(); + fileDescriptions.Clear(); + fileServerTypes.Clear(); + templateFilenames.Clear(); + upgradeFiles.Clear(); + thumbnails.Clear(); + + retVal = remoteFile.Get(localFilename); + if (retVal) + { + wxXmlDocument contentsXML; + + contentsXML.Load(localFilename); + if (contentsXML.IsOk()) + { + wxXmlNode *node; + + node=contentsXML.GetRoot(); + if (node!=NULL) + { + node=node->GetChildren(); + while (node!=NULL) + { + wxString msg; + + nodeName =""; + nodeType =""; + nodeAddress =""; + nodeServerType =""; + nodeContent =""; + nodeThumbnail =""; + nodeSecondAddress =""; + nodeUpgradeFile =""; + nodeTemplateFilename =""; + + nodeName=node->GetName(); + nodeContent=node->GetNodeContent(); + property="type";node->GetPropVal(property,&nodeType); + property="address";node->GetPropVal(property,&nodeAddress); + property="servertype";node->GetPropVal(property,&nodeServerType); + property="thumbnail";node->GetPropVal(property,&nodeThumbnail); + property="secondaddress";node->GetPropVal(property,&nodeSecondAddress); + property="upgradefile";node->GetPropVal(property,&nodeUpgradeFile); + property="templatefilename";node->GetPropVal(property,&nodeTemplateFilename); + nodeTypeInt=WEBFILE_TYPE_UNKNOWN; + if (nodeName.CmpNoCase("file")==0) + { + if (nodeType.CmpNoCase(WEBFILE_TYPE_STR_IMAGEPACK)==0) + { + nodeTypeInt=WEBFILE_TYPE_IMAGEPACK; + } + if (nodeType.CmpNoCase(WEBFILE_TYPE_STR_TEMPLATE)==0) + { + nodeTypeInt=WEBFILE_TYPE_TEMPLATE; + } + } + if (nodeTypeInt!=WEBFILE_TYPE_UNKNOWN) + { + filePaths.Add(nodeAddress); + fileTypes.Add(nodeTypeInt); + fileDescriptions.Add(nodeContent); + fileServerTypes.Add(nodeServerType); + thumbnails.Add(nodeThumbnail); + secondFilePaths.Add(nodeSecondAddress); + upgradeFiles.Add(nodeUpgradeFile); + templateFilenames.Add(nodeTemplateFilename); + } + node=node->GetNext(); + } + } + } + else + { + retVal=false; + wxString msg; + msg.Printf("Failed to open contents.xml from the %s site, please try again at a later time",Hostname().GetData()); + wxMessageBox(msg); + } + } + + return (retVal); +} +bool StatsgenWeb::GetImagePackList( + wxArrayString &fileDescriptionsIn, + wxArrayString &filePathsIn, + wxArrayString &fileServerTypesIn, + wxArrayString &upgradeFilesIn, + wxArrayString &thumbnailsIn) +{ + wxArrayString fileDescriptions; + wxArrayString filePaths; + wxArrayString secondFilePaths; + wxArrayString templateFilenames; + wxArrayString fileServerTypes; + wxArrayString upgradeFiles; + wxArrayString thumbnails; + wxArrayInt fileTypes; + int fileCount; + int fileIndex; + wxString fileDescription; + wxString filePath; + wxString fileServerType; + wxString upgradeFile; + wxString thumbnail; + int fileType; + bool retVal; + + fileDescriptionsIn.Clear(); + filePathsIn.Clear(); + fileServerTypesIn.Clear(); + thumbnailsIn.Clear(); + upgradeFilesIn.Clear(); + retVal=GetFileList(fileDescriptions,filePaths,fileTypes,fileServerTypes,secondFilePaths,templateFilenames,upgradeFiles,thumbnails); + if (retVal) + { + fileCount=fileDescriptions.GetCount(); + for (fileIndex=0;fileIndexGetName(); + while (imagename.Contains('\\')) + { + newDirectory=imagename.BeforeFirst('\\'); + imagename=imagename.AfterFirst('\\'); + directory+='\\'; + directory+=newDirectory; + wxMkDir(directory); + } + if (imagename.Length()>0) + { + outputFile=directory; + outputFile+='\\'; + outputFile+=imagename; + + wxFileOutputStream outputFileStream(outputFile); + + outputFileStream.Write(zipStream); + } + zipEntry=zipStream.GetNextEntry(); + } + } + } + localConfigFile=upgradeFile.AfterLast('/'); + if ((retVal)&& (upgradeFile.Length()>0)) + { + WebFile webfile(hostname,upgradeFile); + retVal=webfile.Get(localConfigFile); + if (retVal) + { + wxFileName upgradeFileName; + wxString localConfigFileStr; + upgradeFileName=BaseDirectoryFileName(localConfigFile); + localConfigFileStr=upgradeFileName.GetFullPath(); + globalStatistics.statsgenDatabase.OpenDB(); + + UpgradeConfigFile(localConfigFileStr); + } + } + return (retVal); +} + +bool StatsgenWeb::GetTemplateList( + wxArrayString &fileDescriptionsIn, + wxArrayString &filePathsIn, + wxArrayString &fileServerTypesIn, + wxArrayString &secondFilePathsIn, + wxArrayString &templateFilenamesIn, + wxArrayString &upgradeFilesIn, + wxArrayString &thumbnailsIn) +{ + wxArrayString fileDescriptions; + wxArrayString filePaths; + wxArrayString secondFilePaths; + wxArrayString templateFilenames; + wxArrayString upgradeFiles; + wxArrayString fileServerTypes; + wxArrayString thumbnails; + wxArrayInt fileTypes; + int fileCount; + int fileIndex; + wxString fileDescription; + wxString filePath; + wxString secondFilePath; + wxString templateFilename; + wxString fileServerType; + wxString thumbnail; + wxString upgradeFile; + int fileType; + bool retVal; + + fileDescriptionsIn.Clear(); + filePathsIn.Clear(); + secondFilePathsIn.Clear(); + fileServerTypesIn.Clear(); + thumbnailsIn.Clear(); + templateFilenamesIn.Clear(); + upgradeFilesIn.Clear(); + retVal=GetFileList(fileDescriptions,filePaths,fileTypes,fileServerTypes,secondFilePaths,templateFilenames,upgradeFiles,thumbnails); + if (retVal) + { + fileCount=fileDescriptions.GetCount(); + for (fileIndex=0;fileIndex0) + { + WebFile webfile(hostname,path); + + retVal=webfile.Get(localImageFile); + if (retVal) + { + Website website; + retVal=website.UploadZipContents(localImageFile); + } + } + if (remoteTemplatePath.Length()>0) + { + WebFile webfile(hostname,remoteTemplatePath); + retVal=webfile.Get(localTemplateFile); + if (retVal) + { + Website website; + retVal=website.UploadZipTemplateContents(localTemplateFile,templateFilename); + } + } + localConfigFile=remoteUpgradePath.AfterLast('/'); + if (remoteUpgradePath.Length()>0) + { + WebFile webfile(hostname,remoteUpgradePath); + retVal=webfile.Get(localConfigFile); + if (retVal) + { + wxFileName upgradeFileName; + wxString localConfigFileStr; + upgradeFileName=BaseDirectoryFileName(localConfigFile); + localConfigFileStr=upgradeFileName.GetFullPath(); + globalStatistics.statsgenDatabase.OpenDB(); + + UpgradeConfigFile(localConfigFileStr); + } + } + return (retVal); +} + diff --git a/StatsgenWeb.h b/StatsgenWeb.h new file mode 100644 index 0000000..1b5b765 --- /dev/null +++ b/StatsgenWeb.h @@ -0,0 +1,49 @@ +#ifndef _STATSGEN_WEB_H +#define _STATSGEN_WEB_H + +#include +#include "WebFile.h" + +enum +{ + WEBFILE_TYPE_UNKNOWN=-1, + WEBFILE_TYPE_IMAGEPACK=0, + WEBFILE_TYPE_TEMPLATE +}; + +#define WEBFILE_TYPE_STR_IMAGEPACK "IMAGEPACK" +#define WEBFILE_TYPE_STR_TEMPLATE "TEMPLATE" + +class StatsgenWeb +{ + public: + StatsgenWeb(); + virtual ~StatsgenWeb(); + bool GetFileList(wxArrayString &fileDescriptions,wxArrayString &filePaths, + wxArrayInt &fileTypes, + wxArrayString &serverTypes, + wxArrayString &secondFilePaths, + wxArrayString &templateFilenames, + wxArrayString &upgradeFiles, + wxArrayString &thumbnails); + bool GetImagePackList(wxArrayString &fileDescriptions, + wxArrayString &filePaths, + wxArrayString &serverTypes, + wxArrayString &upgradeFilesIn, + wxArrayString &thumbnails); + bool GetTemplateList(wxArrayString &fileDescriptions, + wxArrayString &filePaths, + wxArrayString &serverTypes, + wxArrayString &secondFilePaths, + wxArrayString &templateFilenames, + wxArrayString &upgradeFiles, + wxArrayString &thumbnails); + bool UploadImagePack(wxString &description,wxString &path,bool storeLocally,wxString &localOutputFolder,wxString &upgradeFile); + bool UploadTemplatePack(wxString &description,wxString &path,wxString &templatePath,wxString &remoteUpgradePath,wxString &templateFilename); + WebFile *GetWebFile(wxString &filepath); + private: + wxString Hostname(); + +}; + +#endif diff --git a/StatusPanel.cpp b/StatusPanel.cpp new file mode 100644 index 0000000..cf8670b --- /dev/null +++ b/StatusPanel.cpp @@ -0,0 +1,624 @@ +// wx includes +#include + +// Statsgen Includes +#include "ProgressPanel.h" +#include "StatsgenLog.h" +#include "StatusPanel.h" +#include "ErrorData.h" +#include "WindowIDs.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(StatusPanel, wxPanel) + EVT_SIZE(StatusPanel::OnResize) +END_EVENT_TABLE() + +StatusPanel::StatusPanel() +{ + updateDisabled=false; + panelIDs.Clear(); + panelPtrs.Clear(); + dynamicPanel=NULL; + SetClone(NULL); + wxLog::SetActiveTarget(&logger); +} + +StatusPanel::~StatusPanel() +{ +} + +void StatusPanel::DisableUpdate() +{ + updateDisabled=true; +} + +void StatusPanel::SetDynamicPanel(ProgressPanel *panelIn) +{ + dynamicPanel=panelIn; +} + +void StatusPanel::ChoosePanel(int windowID) +{ + ProgressPanel *panel; + + STATSGEN_DEBUG_UPDATE_DEBUG_LEVEL(windowID) + STATSGEN_DEBUG_FUNCTION_START("StatusPanel","ChoosePanel") + STATSGEN_DEBUG(DEBUG_ALWAYS,PanelName(windowID)) + if (!updateDisabled) + + { + currentWindowID=windowID; + panel=WhichPanel(); + if (panel!=NULL) + { + panel->Reset(); + UpdateClone(panel); + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void StatusPanel::UpdateColouredBar() +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->UpdateColouredBar(); + } + } + } + +} + +void StatusPanel::UpdateLabel(const char *label) +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->SetLabel(label); + NormaliseWidths(); + UpdateClone(panel); + } + } + } +} + +void StatusPanel::NormaliseWidths() +{ + ProgressPanel *panel; + int labelWidth; + int maxLabelWidth; + int windowID; + + + if (!updateDisabled) + { + maxLabelWidth=0; + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDLabelWidth(); + if (labelWidth>maxLabelWidth) + { + maxLabelWidth=labelWidth; + } + + } + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDSetLabelWidth(maxLabelWidth); + UpdateClone(panel); + } + } +} + +void StatusPanel::OnResize(wxSizeEvent &event) +{ + wxString msg; + + wxSize itemSize; + int gap=3; + int windowID; + int currentY; + int width; + int maxWidth; + ProgressPanel *panel; + + if (!updateDisabled) + { + CreatePanels(); + currentY=0; + maxWidth=0; + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDGetSize(); + panel->SetSize(0,currentY,itemSize.GetWidth(),itemSize.GetHeight()); + currentY+=itemSize.GetHeight(); + width=itemSize.GetWidth(); + if (width>maxWidth) + { + maxWidth=width; + } + currentY+=gap; + } + + SetSize(maxWidth,currentY); + } +} + +void StatusPanel::Initiate(long topValue, + const char *units, + long scale, + const char *rateUnits, + long rateScale) +{ + ProgressPanel *panel; + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->Initiate(topValue,units,scale,rateUnits,rateScale); + UpdateClone(panel); + } + } + } +} + +void StatusPanel::WakeUp() +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + { + panel->WakeUp(); + UpdateClone(panel); + } + } + } + } +} + +void StatusPanel::Update(long value) +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + { + panel->Update(value); + UpdateClone(panel); + } + } + } + } +} + +void StatusPanel::Finalise() +{ + ProgressPanel *panel; + + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->Finalise(); + currentWindowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + UpdateClone(panel); + } + } + } +} + +long StatusPanel::CurrentValue() +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + return(panel->CurrentValue()); + } + else + { + return ((long)0); + } + } + + return ((long)0); +} + +void StatusPanel::SetOffset(long value) +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + panel->SetOffset(value); + UpdateClone(panel); + } + } +} + +void StatusPanel::CreatePanels() +{ + ProgressPanel *panel; + int windowID; + int panelCount; + + if (!updateDisabled) + { + panelCount=panelIDs.GetCount(); + if (panelCount>0) + { + return; + } + + currentWindowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDCreate(this,windowID,wxDefaultPosition,wxDefaultSize, + wxRAISED_BORDER); + + panel->SetLabel(PanelName(windowID)); + panelIDs.Add(windowID); + panelPtrs.Add((void *)panel); + } + + NormaliseWidths(); + } +} + +void StatusPanel::EnableTimeToGo() +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + panel->EnableTimeToGo(); + UpdateClone(panel); + } + } +} + +void StatusPanel::DisableTimeToGo() +{ + ProgressPanel *panel; + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + panel->DisableTimeToGo(); + UpdateClone(panel); + } + } +} + +void StatusPanel::SetStatus(wxString &statusText) +{ + ProgressPanel *panel; + + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->SetStatus(statusText); + UpdateClone(panel); + } + } + } +} + +void StatusPanel::ClearErrors() +{ + ProgressPanel *panel; + int windowID; + + if (!updateDisabled) + { + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDClearErrors(); + UpdateClone(panel); + } + } +} + +void StatusPanel::LogError(wxString &errorText,int severity) +{ + ProgressPanel *panel; + + + if (!updateDisabled) + { + panel=WhichPanel(); + if (panel!=NULL) + { + { + panel->LogError(errorText,severity); + UpdateClone(panel); + } + } + else + { + } + } +} + +ProgressPanel *StatusPanel::WhichPanel() +{ + ProgressPanel *panel=NULL; + + if (!updateDisabled) + { + if (currentWindowID==WINDOW_ID_PROGRESS_PANEL_DYNAMIC) + { + panel=dynamicPanel; + } + else + { + panel=(ProgressPanel *)panelPtrs.Item(currentWindowID-WINDOW_ID_PROGRESS_PANEL_GENERAL); + } + } + return (panel); +} + +wxString StatusPanel::PanelName(int windowID) +{ + + wxString panelName=""; + + + switch (windowID) + { + case WINDOW_ID_PROGRESS_PANEL_GENERAL: + panelName="General"; + break; + case WINDOW_ID_PROGRESS_PANEL_APPLY_ALIASES: + panelName="Apply Aliases"; + break; + case WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS: + panelName="Download Logs"; + break; + case WINDOW_ID_PROGRESS_PANEL_DATABASE_READ_STATIC: + panelName="Read Static"; + break; + case WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS: + panelName="Process Logs"; + break; + case WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS: + panelName="Dropping Players"; + break; + case WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1: + panelName="Calculating Scores 1"; + break; + case WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES2: + panelName="Calculating Scores 2"; + break; + case WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE: + panelName="Create Database"; + break; + case WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE: + panelName="Empty Database"; + break; + case WINDOW_ID_PROGRESS_PANEL_DATABASE_LOCATE_EXISTING_PLAYERS: + panelName="Locate Existing Players"; + break; + case WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE: + panelName="Write Database"; + break; + case WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE: + panelName="Transfer Database"; + break; + case WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE: + panelName="Read Template"; + break; + case WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE: + panelName="Process Template"; + break; + case WINDOW_ID_PROGRESS_PANEL_WEBSITE: + panelName="Transfer To Website"; + break; + } + + return (panelName); +} + +void StatusPanel::SetStatus(const char *statusTextIn) +{ + wxString statusText; + + statusText=statusTextIn; + if (!updateDisabled) + { + SetStatus(statusText); + } +} + +bool StatusPanel::StageRan(int windowID) +{ + wxString SQL; + wxString panelName; + TemplateOpenQuery query; + int counter; + int retVal; + + STATSGEN_DEBUG_FUNCTION_START("StatusPanel","StageRan") + panelName=PanelName(windowID); + + SQL.Printf("select * from progressbar where stage='%s' and status like '\% done'", + panelName.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,SQL); + query.Initiate(SQL,globalStatistics.statsgenDatabase.DBHandle()); + retVal=query.NextRow(); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"stage ran"); + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"stage not ran"); + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool StatusPanel::RecoveryMode() +{ + bool retVal=false; + bool writeDatabaseRan; + bool processTemplateRan; + + STATSGEN_DEBUG_FUNCTION_START("StatusPanel","RecoveryMode") + writeDatabaseRan=StageRan(WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE); + processTemplateRan=StageRan(WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE); + + retVal=writeDatabaseRan && (!processTemplateRan); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"recovery mode"); + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"not in recovery"); + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +void StatusPanel::StoreProgress(wxString &filename) +{ + FILE *fp; + TemplateOpenQuery query; + wxString SQL="select * from progressbar order by logtime,stage,statusindex"; + wxString stage; + wxString status; + wxString logtime; + wxString severity; + wxString error; + wxString propertyStage="stage"; + wxString propertyLogtime="logtime"; + wxString propertyStatus="status"; + wxString propertySeverity="severity"; + wxString propertyError="error"; + + wxString lineToWrite; + + fp=fopen(filename.GetData(),"w"); + if (fp!=NULL) + { + globalStatistics.statsgenDatabase.OpenDB(); + query.Initiate(SQL,globalStatistics.statsgenDatabase.DBHandle()); + while (query.NextRow()) + { + stage=query.RetrieveProperty(propertyStage); + logtime=query.RetrieveProperty(propertyLogtime); + wxDateTime dateTime((time_t)atoi(logtime.GetData())); + logtime=dateTime.FormatISODate() + " " + dateTime.FormatISOTime(); + status=query.RetrieveProperty(propertyStatus); + severity=query.RetrieveProperty(propertySeverity); + error=query.RetrieveProperty(propertyError); + + lineToWrite.Printf("%24s %14s %10s %30s %s", + stage.GetData(), + logtime.GetData(), + status.GetData(), + severity.GetData(), + error.GetData() + ); + fprintf(fp,"%s\n",lineToWrite.GetData()); + } + fclose(fp); + } +} + +void StatusPanel::SetClone(ProgressPanel *clonePanelIn) +{ + clonePanel=clonePanelIn; +} + +void StatusPanel::UpdateClone(ProgressPanel *sourcePanel) +{ + if (clonePanel!=NULL) + { + if (sourcePanel!=NULL) + { + sourcePanel->UpdateClone(clonePanel); + } + } +} + + +bool StatusPanel::GetEventUpdating() +{ + ProgressPanel *panel; + panel=(ProgressPanel *)panelPtrs.Item(0); + return (panel->GetEventUpdating()); +} + +void StatusPanel::EventUpdating(bool value) +{ + ProgressPanel *panel; + int windowID; + + + for (windowID=WINDOW_ID_PROGRESS_PANEL_GENERAL; + windowIDEventUpdating(value); + } +} + diff --git a/StatusPanel.h b/StatusPanel.h new file mode 100644 index 0000000..e1ab127 --- /dev/null +++ b/StatusPanel.h @@ -0,0 +1,69 @@ +#ifndef __STATUSPANEL +#define __STATUSPANEL + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "DynamicArrays.h" +#include "ProgressPanel.h" +#include "StatsgenLog.h" + +class StatusPanel : public wxPanel +{ + public: + StatusPanel(); + ~StatusPanel(); + void EventUpdating(bool value); + bool GetEventUpdating(); + void Reset(); + void WakeUp(); + long CurrentValue(); + void OnResize(wxSizeEvent &event); + static wxString PanelName(int windowID); + void NormaliseWidths(); + void ChoosePanel(int windowID); + void UpdateLabel(const char *label); + void Finalise(); + void CreatePanels(); + void UpdateColouredBar(); + void Update(long value); + void SetOffset(long value); + void EnableTimeToGo(); + void DisableTimeToGo(); + void SetStatus(wxString &statusText); + void SetStatus(const char *statusText); + void Initiate(long topValue, + const char *units, + long scale, + const char *rateUnits, + long rateScale); + void LogError(wxString &errorText, + int severity=SeverityNotRun); + void ClearErrors(); + void SetDynamicPanel(ProgressPanel *panelIn); + ProgressPanel *WhichPanel(); + void DisableUpdate(); + bool StageRan(int windowID); + bool RecoveryMode(); + void StoreProgress(wxString &filename); + void SetClone(ProgressPanel *panelIn); + void UpdateClone(ProgressPanel *clonePanel); + protected: + + public: + int currentWindowID; + private: + wxArrayInt panelIDs; + ArrayOfPointers panelPtrs; + ProgressPanel *dynamicPanel; + ProgressPanel *clonePanel; + StatsgenLog logger; + bool updateDisabled; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/StreakData.cpp b/StreakData.cpp new file mode 100644 index 0000000..a82014a --- /dev/null +++ b/StreakData.cpp @@ -0,0 +1,95 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "StreakData.h" +#include "ErrorData.h" +#include "Player.h" +#include "GlobalStatistics.h" + +StreakData::StreakData() +{ +} + +StreakData::~StreakData() +{ +} + +void StreakData::Debug() +{ + wxString errorMessage; + Player player; + + errorMessage.Printf("Streak=%d ended by ",streakSize); + if (streakEndedPlayerIndex!=-1) + { + player=globalStatistics.GetPlayer(streakEndedPlayerIndex); + errorMessage+=player.name; + } + else + { + errorMessage+="nobody"; + } +} + +wxString StreakData::SQLTableName() +{ + wxString retVal="streakdata"; + + return (retVal); +} + +wxString StreakData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "playerindex integer," + "streakidx integer," + "streaktype integer," + "streaksize integer," + "streakender integer" + ")", + SQLTableName().GetData()); + + return SQL; +} + + +bool StreakData::WriteToDatabase(int roundIndex,int playerIndex, + int streakIndex, KillTypes streakType) +{ + wxString SQL; + bool retVal=true; + Player player; + Player streakEnderPlayer; + int actualStreakEnder; + + if (streakEndedPlayerIndex>=0) + { + streakEnderPlayer=globalStatistics.playerList.Item(streakEndedPlayerIndex); + actualStreakEnder=streakEnderPlayer.actualPlayerIndex; + } + else + { + actualStreakEnder=streakEndedPlayerIndex; + } + + + SQL.Printf("insert into %s" + "(roundindex,playerindex,streakidx,streaktype," + "streaksize,streakender)" + "values" + "('%d','%d','%d','%d','%d','%d')", + SQLTableName().GetData(), + roundIndex,playerIndex,streakIndex,streakType, + streakSize,actualStreakEnder); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + + return retVal; +} + diff --git a/StreakData.h b/StreakData.h new file mode 100644 index 0000000..c85c7d7 --- /dev/null +++ b/StreakData.h @@ -0,0 +1,31 @@ +#ifndef __STREAKDATA +#define __STREAKDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes +#include "KillData.h" + +class StreakData; + +WX_DECLARE_OBJARRAY(StreakData,ArrayOfStreakData); +class StreakData +{ + public: + StreakData(); + virtual ~StreakData(); + int streakSize; + int streakEndedPlayerIndex; + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int playerIndex, + int itemIndex,KillTypes streakType); + + void Debug(); +}; + + +#endif diff --git a/TeamLossData.cpp b/TeamLossData.cpp new file mode 100644 index 0000000..51a9f5e --- /dev/null +++ b/TeamLossData.cpp @@ -0,0 +1,62 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "TeamLossData.h" +#include "GlobalStatistics.h" + +TeamLossData::TeamLossData() +{ +} + +TeamLossData::~TeamLossData() +{ +} + +wxString TeamLossData::SQLTableName() +{ + wxString retVal="teamlossdata"; + + return (retVal); +} + +wxString TeamLossData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "teamlossidx integer," + "playerindex integer," + "playerclass integer," + "playerteam integer" + ")", + SQLTableName().GetData()); + + return SQL; + +} + +bool TeamLossData::WriteToDatabase(int roundIndex,int itemIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + SQL.Printf("insert into %s" + "(roundindex,teamlossidx,playerindex,playerclass,playerteam)" + "values('%d','%d','%d','%d','%d')", + SQLTableName().GetData(), + roundIndex, + itemIndex, + player.actualPlayerIndex, + playerClass, + playerTeam); + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} + diff --git a/TeamLossData.h b/TeamLossData.h new file mode 100644 index 0000000..f9486e6 --- /dev/null +++ b/TeamLossData.h @@ -0,0 +1,33 @@ +#ifndef __TEAMLOSSDATA +#define __TEAMLOSSDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class TeamLossData; + +WX_DECLARE_OBJARRAY(TeamLossData,ArrayOfTeamLossData); +class TeamLossData +{ + public: + TeamLossData(); + virtual ~TeamLossData(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int itemIndex); + + + wxDateTime lossTime; + int gameType; + int mapName; + int playerIndex; + int playerClass; + int playerTeam; +}; + + +#endif diff --git a/TeamWinData.cpp b/TeamWinData.cpp new file mode 100644 index 0000000..fe9339d --- /dev/null +++ b/TeamWinData.cpp @@ -0,0 +1,64 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "TeamWinData.h" +#include "GlobalStatistics.h" + +TeamWinData::TeamWinData() +{ +} + +TeamWinData::~TeamWinData() +{ +} + +wxString TeamWinData::SQLTableName() +{ + wxString retVal="teamwindata"; + + return (retVal); +} + +wxString TeamWinData::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "teamwinidx integer," + "playerindex integer," + "playerclass integer," + "playerteam integer" + ")", + SQLTableName().GetData()); + return SQL; +} + +bool TeamWinData::WriteToDatabase(int roundIndex,int itemIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + + SQL.Printf("insert into %s" + "(roundindex,teamwinidx,playerindex,playerclass,playerteam)" + "values" + "('%d','%d','%d','%d','%d')", + SQLTableName().GetData(), + roundIndex, + itemIndex, + player.actualPlayerIndex, + playerClass, + playerTeam); + + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + + return retVal; +} + diff --git a/TeamWinData.h b/TeamWinData.h new file mode 100644 index 0000000..b644e37 --- /dev/null +++ b/TeamWinData.h @@ -0,0 +1,32 @@ +#ifndef __TEAMWINDATA +#define __TEAMWINDATA + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class TeamWinData; + +WX_DECLARE_OBJARRAY(TeamWinData,ArrayOfTeamWinData); +class TeamWinData +{ + public: + TeamWinData(); + virtual ~TeamWinData(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + bool WriteToDatabase(int roundIndex,int itemIndex); + + wxDateTime winTime; + int gameType; + int mapName; + int playerIndex; + int playerClass; + int playerTeam; +}; + + +#endif diff --git a/TemplateFile.cpp b/TemplateFile.cpp new file mode 100644 index 0000000..b39595b --- /dev/null +++ b/TemplateFile.cpp @@ -0,0 +1,1985 @@ +// wxWindows includes +#include +#include +#include +#include + +// Statsgen includes +#include "TemplateFile.h" +#include "LogFileReader.h" +#include "Progress.h" +#include "GlobalStatistics.h" + +TemplateFile::TemplateFile() +{ +} + +TemplateFile::~TemplateFile() +{ + Unload(); +} + +bool TemplateFile::ReadTemplateFile(wxString &filename,wxString parentOrg) +{ + bool retVal; + wxTextFile templateFile; + int lineCount; + int lineIndex; + wxString line; + wxString errorMessage; + int previousTemplateLine; + wxString previousTemplateFile; + int charIndex; + wxString includeString; + wxString lowerCaseLine; + wxString beforeInclude; + wxString afterInclude; + wxString parent; + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","ReadTemplateFile") + + previousTemplateLine=currentTemplateLine; + previousTemplateFile=currentTemplateFile; + currentTemplateFile=filename; + currentTemplateLine=0; + retVal=templateFile.Open(filename); + LoadTemplateFile(filename); + if (retVal) + { + // Successfully opened file + // Scan through each line of the file adding + // to the templateLines and searching for "include" commands + lineCount=templateFile.GetLineCount(); + for (lineIndex=0;lineIndexUpdate(templateLines.GetCount()); + currentTemplateLine=lineIndex; + line=templateFile.GetLine(lineIndex); + + // Added for Compiled Version + line+="\n"; + // Added for Compiled Version + + lowerCaseLine=line; + //lowerCaseLine.MakeLower(); + // We need to see if there is an include statement in here + charIndex=lowerCaseLine.Find("$$include"); + if (charIndex>=0) + { + // There is an include statement in this line + if (charIndex>0) + { + // A bit before the include + beforeInclude=line.Left(charIndex); + } + else + { + beforeInclude=""; + } + line=line.Mid(charIndex+9); // skip past "$$include" + charIndex=line.Find("$$"); + if (charIndex>-1) + { + afterInclude=line.Mid(charIndex+2); // skip past term $$ + // Terminating $$ found - left of it should be the filename + filename=""; + if (charIndex>0) + { + filename=line.Left(charIndex); + } + // trim any spaces from ends of filename + filename.Trim(true); + filename.Trim(false); + if (filename.Length()>0) + { + // Filename looks like it is probably valid + if (beforeInclude.Length()>0) + { + AddTemplateLine(beforeInclude,parent); + //templateLines.Add(beforeInclude); + } + wxFileName templateFilename(originalTemplateFile); + templateFilename.SetFullName(filename); + filename=templateFilename.GetFullPath(); + retVal=ReadTemplateFile(filename,parent); + if (retVal) + { + // Included file read ok + if (afterInclude.Length()>0) + { + AddTemplateLine(afterInclude,parent); + //templateLines.Add(afterInclude); + } + } + else + { + // included file not ok + // error will have been recorded + break; + } + + } + else + { + // No actual filename seems to be in the include statement + errorMessage="empty filename in $$include $$ statement"; + retVal=false; + break; + } + } + else + { + // No terminating $$ for the include - error + errorMessage="$$include not terminated with a $$"; + retVal=false; + break; + } + + } + else + { + // No include statement - just add the line + AddTemplateLine(line,parent); + //templateLines.Add(line); + } + } + templateFile.Close(); + } + else + { + // Could not open the file + // First open + errorMessage="Failed to open template file"; + } + + if (!retVal) + { + wxString addition; + addition.Printf(", Template File [%s] error line [%d]", + currentTemplateFile.GetData(), + currentTemplateLine); + errorMessage+=addition; + if (previousTemplateFile.Length()>0) + { + + addition.Printf(", Opened from [%s] at line [%d", + previousTemplateFile.GetData(), + previousTemplateLine); + errorMessage+=addition; + } + STATSGEN_DEBUG(DEBUG_ALWAYS,errorMessage); + progress->LogError(errorMessage,SeverityError); + } + currentTemplateLine=previousTemplateLine; + currentTemplateFile=previousTemplateFile; + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +void TemplateFile::AddTemplateLine(wxString &line,wxString &lineRef) +{ + templateLines.Add(line); + templateLineRef.Add(lineRef); +} + +bool TemplateFile::SplitTemplateLine(wxString &templateLine, + wxString *beforeTemplateCode, + wxString *templateCode, + wxString *afterTemplateCode) +{ + bool retVal=true; + int charIndex; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","SplitTemplateLine") + *beforeTemplateCode=""; + *templateCode=""; + *afterTemplateCode=""; + charIndex=templateLine.Find("$$"); + if (charIndex>=0) + { + // There is $$ indicating a template code present in this + // line + if (charIndex>0) + { + // A bit before the $$ + *beforeTemplateCode=templateLine.Left(charIndex); + } + else + { + // nothing before the $$ + *beforeTemplateCode=""; + } + // get the bit after the $$ (this is the template code) + templateLine=templateLine.Mid(charIndex+2); // skip past "$$" + // now - we have an open $$ - skip to the close $$ + charIndex=templateLine.Find("$$"); + if (charIndex>=0) + { + // Close $$ found + if (charIndex>0) + { + // template code is not empty + *templateCode=templateLine.Left(charIndex); + // make the templateCode line lower case + //*templateCode->MakeLower(); + templateLine=templateLine.Mid(charIndex+2); // skip past "$$" + *afterTemplateCode=templateLine; + } + else + { + // empty template code - makes no sense + msg="Empty template code encountered"; + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->LogError(msg,SeverityCaution); + retVal=false; + } + } + else + { + // There is not a close $$ for this line - error + msg="template code is not terminated by a $$"; + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->LogError(msg,SeverityCaution); + retVal=false; + } + + } + else + { + // no template code found + *beforeTemplateCode=templateLine; + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool TemplateFile::ReadTemplate(wxString &filename) +{ + bool retVal; + wxString parent; + + Unload(); + progress->Initiate((long)0, + " lines", + (long)1, + " lines", + (long)1); + templateLines.Clear(); + templateLineRef.Clear(); + originalTemplateFile=filename; + currentTemplateFile=""; + currentTemplateLine=0; + + parent=""; + retVal=ReadTemplateFile(filename,parent); + + // Template Line read in + + return (retVal); +} + +bool TemplateFile::Process() +{ + TemplateVariable templateVariable; + int lineIndex=0; + wxString initialTemplateCode=""; + bool retVal=true; + int finishedType; + //int initialTemplateCode; + CompiledTemplateSection compiledSection; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","Process") + + createdFiles.Clear(); + /* + return (ProcessTemplate(true, + templateVariable, + &lineIndex, + initialTemplateCode, + &endedOnElse)); + */ + + lineIndex=-1; + templateVariable.SetTemplateFile(this); + retVal=Compile(compiledSection, + &lineIndex, + initialTemplateCode, + &finishedType, + templateVariable); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Compiled Successfully") + + retVal=compiledSection.Process(*this,templateVariable); + if (retVal) + { + msg="Processing Succeeded";progress->LogError(msg,SeverityOK); + STATSGEN_DEBUG(DEBUG_RARELY,"Processed Successfully") + } + else + { + msg="Processing Failed";progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_RARELY,"Processing failed") + } + } + else + { + msg="Compilation Failed";progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_RARELY,"Compilation failed") + } + + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +bool TemplateFile::WriteTemplateDataToOutput(wxString &text, + TemplateVariable &templateVariable) +{ + bool retVal=true; + int openFileCount; + + openFileCount=templateVariable.openFiles.GetCount(); + if (openFileCount>0) + { + TemplateOpenFile *openFile; + + openFile=templateVariable.openFiles.Detach(openFileCount-1); + // Write the data to the open file + retVal=openFile->Write(text); + // add it back to the end of the stack + templateVariable.openFiles.Add(openFile); + } + else + { + // Trying to write data - but no open file yet + } + + return (retVal); +} + +bool TemplateFile::CloseFile(TemplateVariable &templateVariable) +{ + bool retVal=true; + int openFileCount; + + openFileCount=templateVariable.openFiles.GetCount(); + + if (openFileCount>0) + { + // pop off the top of the openFiles - this will automatically close it + templateVariable.openFiles.RemoveAt(openFileCount-1); + } + else + { + // trying to close an output file that is not open + //StatsgenDebug("Trying to close an output file that is not open"); + // no error for this - it does not really matter + } + + return (retVal); +} + +bool TemplateFile::OpenFile(wxString &templateCode, + char *mode, + TemplateVariable &templateVariable) +{ + bool retVal=true; + wxString filename; + wxString createdFilename; + TemplateOpenFile *openFile; + int tokenCount; + wxString msg; + int createdFilesCount; + int createdFilesIndex; + bool found; + wxString configKey; + wxString localDirectory; + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","OpenFile") + + filename=GetLineToken(templateCode," ",2,&tokenCount); + if (tokenCount!=2) + { + msg.Printf("openfile with too many parameters [%s]",templateCode.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityCaution); + retVal=false; + } + else + { + configKey="/General/LocalOutput"; + globalStatistics.configData.ReadTextValue(configKey,&localDirectory,""); + STATSGEN_DEBUG(DEBUG_RARELY,localDirectory); + wxFileName constructedFile=wxFileName::DirName(localDirectory); + constructedFile.SetFullName(filename); + filename=constructedFile.GetFullPath(); + STATSGEN_DEBUG(DEBUG_RARELY,filename); + openFile=new TemplateOpenFile; + retVal=openFile->Open(filename,mode); + if (retVal) + { + // Successfully opened file - add it to the openfile stack + templateVariable.openFiles.Add(openFile); + createdFilesCount=createdFiles.GetCount(); + found=false; + for (createdFilesIndex=0; + createdFilesIndexLogError(msg,SeverityError); + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +void TemplateFile::AddCreatedFile(wxString &filename) +{ + int createdFileCount; + int createdFileIndex; + wxString createdFilename; + bool found; + + createdFileCount=createdFiles.GetCount(); + found=false; + for (createdFileIndex=0;createdFileIndexLogError(msg,SeverityCaution); + retVal=false; + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool TemplateFile::ProcessTemplate(bool allowProcessing, + TemplateVariable &templateVariable, + int *lineIndex, + wxString &templateLine, + bool *endedOnElse) +{ + bool retVal=true; + int lineCount; + wxString beforeTemplateCode; + wxString afterTemplateCode; + wxString templateCodeText; + wxString msg; + int tokenCount; + wxString templateCode; + bool conditionResult=true; + bool tempElseVar; + + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","ProcessTemplate") + *endedOnElse=false; + lineCount=templateLines.GetCount(); + if (templateLine.Length()==0) + { + if ((*lineIndex)<(lineCount)) + { + templateLine=templateLines.Item(*lineIndex); + } + else + { + // No more lines left to read + templateLine=""; + } + } + while ((retVal)&&((*lineIndex)Update(*lineIndex); + + retVal=SplitTemplateLine(templateLine, + &beforeTemplateCode, + &templateCodeText, + &afterTemplateCode); + // Substitute any included variables + templateCodeText=templateVariable.SubstituteVariableValues(templateCodeText); + // We have split the template line up + if (allowProcessing) + { + WriteTemplateDataToOutput(beforeTemplateCode,templateVariable); + } + if (templateCodeText.Length()>0) + { + // We have a template code to handle + templateCode=GetLineToken(templateCodeText," ",1,&tokenCount); + if (templateCode.Cmp("openfile")==0) + { + if (allowProcessing) + { + retVal=OpenFile(templateCodeText,"w",templateVariable); + } + } + else if (templateCode.CmpNoCase("appendfile")==0) + { + if (allowProcessing) + { + retVal=OpenFile(templateCodeText,"a",templateVariable); + } + } + else if (templateCode.CmpNoCase("closefile")==0) + { + if (allowProcessing) + { + retVal=CloseFile(templateVariable); + } + } + else if (((templateCode.CmpNoCase("loop")==0))) + { + wxString rowIndexValue; + wxString rowIndexVariable; + int rowIndex; + wxString rowVariable; + wxString SQLQuery; + wxString msg; + + retVal=Loop(templateVariable, + templateCodeText, + rowVariable, + rowIndexVariable, + SQLQuery); + if (retVal) + { + wxString loopStartAfterTemplateCode; + int loopStartIndex; + bool queryRan=false; + + if (allowProcessing) + { + // We have a good loop command + rowIndex=0; + // We are going to need to reset the current + // template file position for each loop start + loopStartAfterTemplateCode=afterTemplateCode; + loopStartIndex=(*lineIndex); + // Store the template query on the stack + templateVariable.StoreQuery(rowVariable,SQLQuery); + while (templateVariable.QueryNextRow(rowVariable)&&(retVal)) + { + queryRan=true; + // Reset template position to start of loop + afterTemplateCode=loopStartAfterTemplateCode; + *lineIndex=loopStartIndex; + msg.Printf("while loop at lineIndex [%d]",*lineIndex); + + // Store current row index variable + rowIndexValue.Printf("%d",rowIndex+1); + templateVariable.StoreVariable(rowIndexVariable,rowIndexValue); + + if (afterTemplateCode.Length()==0) + { + // We need to move onto the next template line + (*lineIndex)++; + } + retVal=ProcessTemplate(allowProcessing, + templateVariable, + lineIndex, + afterTemplateCode, + &tempElseVar); + rowIndex++; + } + templateVariable.RemoveQuery(rowVariable); + if (!queryRan) + { +// StatsgenDebug("Loop query produced no results"); + // The query did not run at all (no results) - therefore we need to + // process the template inbetween with allowprocessing of false + // to skip past the useless template code + if (afterTemplateCode.Length()==0) + { + // We need to move onto the next template line + (*lineIndex)++; + } + retVal=ProcessTemplate(false, + templateVariable, + lineIndex, + afterTemplateCode, + &tempElseVar); + } + } + else + { + // Loop encountered but allow processing switched off + // Just call the loop code - but do nothing + if (afterTemplateCode.Length()==0) + { + // We need to move onto the next template line + (*lineIndex)++; + } + retVal=ProcessTemplate(allowProcessing, + templateVariable, + lineIndex, + afterTemplateCode, + &tempElseVar); + } + } + else + { + // Invalid Loop command + msg.Printf("Invalid loop statement [%s]",templateCodeText.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->LogError(msg,SeverityCaution); + } + } + else if (templateCode.CmpNoCase("endloop")==0) + { + // just need to break out of this loop and return + break; + } + else if (templateCode.CmpNoCase("procedure")==0) + { + } + else if (templateCode.CmpNoCase("return")==0) + { + } + else if (templateCode.CmpNoCase("if")==0) + { + wxString conditionString; + wxString conditionResultString; + + conditionString=templateCodeText.AfterFirst(' '); + conditionString.Trim(true); + conditionString.Trim(false); + conditionResultString=templateVariable.GetVariableValue(conditionString); + conditionResult=(conditionResultString.CmpNoCase(TRUE_STRING)==0); + if (afterTemplateCode.Length()==0) + { + // We need to move onto the next template line + (*lineIndex)++; + } + tempElseVar=false; + retVal=ProcessTemplate(conditionResult && allowProcessing, + templateVariable, + lineIndex, + afterTemplateCode, + &tempElseVar); + if (tempElseVar) + { + // We have ended on an else - so process template again with + // opposite status + if (afterTemplateCode.Length()==0) + { + // We need to move onto the next template line + (*lineIndex)++; + } + retVal=ProcessTemplate((!conditionResult) && allowProcessing, + templateVariable, + lineIndex, + afterTemplateCode, + &tempElseVar); + } + } + else if (templateCode.CmpNoCase("else")==0) + { + // just need to finish the file (indicating an "ELSE" exit) + *endedOnElse=true; + break; + } + else if (templateCode.CmpNoCase("endif")==0) + { + // just need to finish the file (indicating an "ENDIF" exit) + *endedOnElse=false; + break; + } + else + { + // This template code text is just a variable value now + if (allowProcessing) + { + wxString value; + + value=templateVariable.GetVariableValue(templateCodeText); + WriteTemplateDataToOutput(value,templateVariable); + } + } + } + if (afterTemplateCode.Length()>0) + { + // More data after the template code + // just set the template line to be the + // after bit and process round loop again + // it will be treated as a new template line + templateLine=afterTemplateCode; + } + else + { + // Finished with this line - move on to next + // if there is one + (*lineIndex)++; + if ((*lineIndex)Open(filename); + usedTemplateFiles.Add(textFile); + usedTemplateFilenames.Add(filename); + } +} + +void TemplateFile::ExportToCPP(wxString &filename,wxString &prefix) +{ + int fileCount; + int fileIndex; + wxString templatefilename; + wxTextFile outputFile; + wxString cppLine; + wxString fileLine; + int lineCount; + int lineIndex; + + outputFile.Create(filename); + cppLine="#include ";outputFile.AddLine(cppLine); + cppLine="void ExportTemplateFile(wxString &directory,wxArrayString &fileLines,char *filename);";outputFile.AddLine(cppLine); + cppLine.Printf("void ExportTemplate%s(wxString &directory)",prefix.GetData());outputFile.AddLine(cppLine); + cppLine="{";outputFile.AddLine(cppLine); + cppLine=" wxString filename;";outputFile.AddLine(cppLine); + cppLine=" wxArrayString fileLines;";outputFile.AddLine(cppLine); + cppLine=" wxString fileLine;";outputFile.AddLine(cppLine); + + fileCount=usedTemplateFiles.GetCount(); + for (fileIndex=0;fileIndexGetLineCount(); + cppLine=" fileLines.Clear();";outputFile.AddLine(cppLine); + for (lineIndex=0;lineIndexGetLine(lineIndex); + fileLine.Replace("\\","\\\\"); + fileLine.Replace("\"","\\\""); + cppLine.Printf(" fileLine=\"%s\";fileLines.Add(fileLine);",fileLine.GetData()); + outputFile.AddLine(cppLine); + } + wxFileName constructedName(templatefilename); + + cppLine.Printf(" ExportTemplateFile(directory,fileLines,\"%s\");",constructedName.GetFullName().GetData()); + outputFile.AddLine(cppLine); + } + cppLine="}";outputFile.AddLine(cppLine); + + outputFile.Write(); + outputFile.Close(); +} + +bool TemplateFile::Compile( + CompiledTemplateSection &compiledSection, + int *currentLineIndex, + wxString ¤tTemplateLine, + int *finishedType, + TemplateVariable &templateVariable) +{ + // Compiling involves creating "Compiled Lines" of code + // A compiled line is a list of CompiledStatements + // Compiled Statements are individual commands + // Such as Raw Output + // Loop / End Loop + // If / Else / End If + // and any of the other various functions + // Each can hold "sub lines" of text + // Template Variables are global throughout + wxString msg; + bool retVal=true; + wxString beforeTemplateCode; + wxString afterTemplateCode; + wxString templateCodeText; + bool lineSplitOK; + bool compileResult; + int lineCount; + wxString rawTemplateCode; + bool finished; + int compiledTemplateCommand; + int sectionStartIndex; + CompiledTemplateLinePROCEDURE *compiledLinePROCEDURE; + CompiledTemplateLineIF *compiledLineIF; + CompiledTemplateLineRaw *compiledLineRaw; + CompiledTemplateLineLOOP *compiledLineLOOP; + CompiledTemplateLineOPENFILE *compiledLineOPENFILE; + CompiledTemplateLineAPPENDFILE *compiledLineAPPENDFILE; + CompiledTemplateLineCLOSEFILE *compiledLineCLOSEFILE; + CompiledTemplateLineVARIABLE *compiledLineVARIABLE; + + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","Compile") + lineCount=templateLines.GetCount(); + + // Hack around for when we are first starting template + if ((*currentLineIndex)==-1) + { + (*currentLineIndex)++; + if ((*currentLineIndex)Update(*currentLineIndex); + + if (currentTemplateLine.Length()==0) + { + // The current template line is empty indicating we need the next + // line or we have reached the end of the file + (*currentLineIndex)++; + if ((*currentLineIndex)0) + { + // We have found some template code - any current + // rawTemplateCode needs adding to the list of compiled + // template sections + compiledLineRaw->SetRaw(rawTemplateCode); + rawTemplateCode=""; + compiledSection.Add(compiledLineRaw); + + // now we have added the raw section we can decode the template + // code bit + compiledTemplateCommand=IdentifyTemplateCode(templateCodeText); + STATSGEN_DEBUG_CODE( + msg.Printf("compiledTemplateCommand=[%d]",compiledTemplateCommand); + ) + sectionStartIndex=(*currentLineIndex); + STATSGEN_DEBUG(DEBUG_RARELY,msg) + switch (compiledTemplateCommand) + { + case TEMPLATE_COMMAND_IF: + compiledLineIF=new CompiledTemplateLineIF; + STATSGEN_DEBUG(DEBUG_RARELY,"IF") + compiledLineIF->SetTemplateCode(templateCodeText); + // Now compile again using the + // next bit of the code + // it should finish with either ELSE or ENDIF + compileResult=Compile(compiledLineIF->trueSection, + currentLineIndex, + afterTemplateCode, + finishedType, + templateVariable); + if ((*finishedType)==TEMPLATE_FINISHED_ELSE) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Finished on an else") + // Else statement - another subsection + compileResult=Compile(compiledLineIF->falseSection, + currentLineIndex, + afterTemplateCode, + finishedType, + templateVariable); + } + if ((*finishedType)==TEMPLATE_FINISHED_ENDIF) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Finished on an endif") + // success - we have finished this section + finished=false; + *finishedType=TEMPLATE_FINISHED_OK; + retVal=true; + } + else + { + msg.Printf("IF with no ENDIF [%s]", + TemplateErrorDetails( + sectionStartIndex).GetData()); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG_CODE( + msg.Printf("Finished on %d",*finishedType); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + // if not terminated by an endif + finished=true; + *finishedType=TEMPLATE_FINISHED_ERROR; + retVal=false; + } + compiledSection.Add(compiledLineIF); + break; + case TEMPLATE_COMMAND_ELSE: + STATSGEN_DEBUG(DEBUG_RARELY,"ELSE") + // Finished this section + *finishedType=TEMPLATE_FINISHED_ELSE; + finished=true; + retVal=true; + break; + case TEMPLATE_COMMAND_ENDIF: + STATSGEN_DEBUG(DEBUG_RARELY,"ENDIF") + // Finished this section + *finishedType=TEMPLATE_FINISHED_ENDIF; + finished=true; + retVal=true; + break; + case TEMPLATE_COMMAND_PROCEDURE: + compiledLinePROCEDURE=new CompiledTemplateLinePROCEDURE; + STATSGEN_DEBUG(DEBUG_RARELY,"PROCEDURE") + compiledLinePROCEDURE->SetTemplateCode(templateCodeText); + compileResult=Compile(compiledLinePROCEDURE->procedureBody, + currentLineIndex, + afterTemplateCode, + finishedType, + templateVariable); + if ((*finishedType)==TEMPLATE_FINISHED_RETURN) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Finished on RETURN") + finished=false; + *finishedType=TEMPLATE_FINISHED_OK; + retVal=true; + AddCustomProcedure(compiledLinePROCEDURE); + } + else + { + msg.Printf("PROCEDURE with no RETURN [%s]", + TemplateErrorDetails( + sectionStartIndex).GetData()); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG_CODE( + msg.Printf("Finished on %d",*finishedType); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + // if not terminated by an return + finished=true; + *finishedType=TEMPLATE_FINISHED_ERROR; + retVal=false; + } + //compiledSection.Add(compiledLinePROCEDURE); + break; + case TEMPLATE_COMMAND_RETURN: + STATSGEN_DEBUG(DEBUG_RARELY,"RETURN") + // Finished this section + *finishedType=TEMPLATE_FINISHED_RETURN; + retVal=true; + finished=true; + break; + case TEMPLATE_COMMAND_LOOP: + compiledLineLOOP=new CompiledTemplateLineLOOP; + STATSGEN_DEBUG(DEBUG_RARELY,"LOOP") + compiledLineLOOP->SetTemplateCode(templateCodeText); + // Now compile again using the + // next bit of the code + // it should finish with ENDLOOP + compileResult=Compile(compiledLineLOOP->subSection, + currentLineIndex, + afterTemplateCode, + finishedType, + templateVariable); + if ((*finishedType)==TEMPLATE_FINISHED_ENDLOOP) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Finished on ENDLOOP") + finished=false; + *finishedType=TEMPLATE_FINISHED_OK; + retVal=true; + } + else + { + msg.Printf("LOOP with no ENDLOOP [%s]", + TemplateErrorDetails( + sectionStartIndex).GetData()); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG_CODE( + msg.Printf("Finished on %d",*finishedType); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + // if not terminated by an endloop + finished=true; + *finishedType=TEMPLATE_FINISHED_ERROR; + retVal=false; + } + compiledSection.Add(compiledLineLOOP); + break; + case TEMPLATE_COMMAND_ENDLOOP: + STATSGEN_DEBUG(DEBUG_RARELY,"ENDLOOP") + // Finished this section + *finishedType=TEMPLATE_FINISHED_ENDLOOP; + retVal=true; + finished=true; + break; + case TEMPLATE_COMMAND_OPENFILE: + compiledLineOPENFILE=new CompiledTemplateLineOPENFILE; + STATSGEN_DEBUG(DEBUG_RARELY,"OPENFILE") + compiledLineOPENFILE->SetTemplateCode(templateCodeText); + compiledSection.Add(compiledLineOPENFILE); + break; + case TEMPLATE_COMMAND_APPENDFILE: + compiledLineAPPENDFILE=new CompiledTemplateLineAPPENDFILE; + STATSGEN_DEBUG(DEBUG_RARELY,"APPENDFILE") + compiledLineAPPENDFILE->SetTemplateCode(templateCodeText); + compiledSection.Add(compiledLineAPPENDFILE); + break; + case TEMPLATE_COMMAND_CLOSEFILE: + compiledLineCLOSEFILE=new CompiledTemplateLineCLOSEFILE; + STATSGEN_DEBUG(DEBUG_RARELY,"CLOSEFILE") + compiledLineCLOSEFILE->SetTemplateCode(templateCodeText); + compiledSection.Add(compiledLineCLOSEFILE); + break; + case TEMPLATE_COMMAND_VARIABLE: + compiledLineVARIABLE=new CompiledTemplateLineVARIABLE; + STATSGEN_DEBUG(DEBUG_RARELY,"VARIABLE") + compiledLineVARIABLE->SetTemplateCode(templateCodeText); + compiledSection.Add(compiledLineVARIABLE); + break; + default: + msg.Printf("Unknown Template Code [%s]", + TemplateErrorDetails( + sectionStartIndex).GetData()); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_RARELY,"Unknown Template Code") + // Unknown Template Command + finished=true; + *finishedType=TEMPLATE_FINISHED_ERROR; + retVal=false; + break; + } + + STATSGEN_DEBUG(DEBUG_RARELY,afterTemplateCode) + // now that we have sorted out the template code bit + // we can advance to the section after the template code + currentTemplateLine=afterTemplateCode; + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"no template code left - add to raw") + // No template code - so we are moving to a new line of raw data + // add in the linefeed + //rawTemplateCode+="\n"; + currentTemplateLine=""; + } + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Failed to split the template line") + // failed to split the template line - we are finished + *finishedType=TEMPLATE_FINISHED_ERROR; + currentTemplateLine=""; + finished=true; + } + } + + return (retVal); + STATSGEN_DEBUG_FUNCTION_END +} + +void TemplateFile::AddCustomProcedure(CompiledTemplateLinePROCEDURE *procedure) +{ + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","AddCustomProcedure") + CompiledTemplateLinePROCEDURE *foundProcedure; + + foundProcedure = FindCustomProcedure(procedure->procedureName); + if (foundProcedure == NULL) + { + customProcedures.Add(procedure); + } + STATSGEN_DEBUG_FUNCTION_END +} + +CompiledTemplateLinePROCEDURE *TemplateFile::FindCustomProcedure(wxString &procedureName) +{ + STATSGEN_DEBUG_FUNCTION_START("TemplateFile","FindCustomProcedure") + int procedureCount; + int procedureIndex; + wxString msg; + + CompiledTemplateLinePROCEDURE *foundProcedure=NULL; + CompiledTemplateLinePROCEDURE *currentProcedure; + + procedureCount = customProcedures.GetCount(); + for (procedureIndex = 0;procedureIndex < procedureCount;procedureIndex++) + { + STATSGEN_DEBUG_CODE(msg.Printf("checking procedure %d of %d for [%s]",procedureIndex,procedureCount,procedureName.GetData());) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + currentProcedure = (CompiledTemplateLinePROCEDURE *)customProcedures.Item(procedureIndex); + STATSGEN_DEBUG(DEBUG_RARELY,"got a procedure - checking it's name") + STATSGEN_DEBUG(DEBUG_RARELY,procedureName) + if (currentProcedure->procedureName.CmpNoCase(procedureName) == 0) + { + foundProcedure = currentProcedure; + break; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (foundProcedure); + +} + +wxString TemplateFile::TemplateErrorDetails(int lineIndex) +{ + wxString templateLine=""; + wxString lineRef=""; + wxString errorDetails; + + if (lineIndex>=0) + { + if (lineIndex=0)||(charIndexParameters>=0)); + + STATSGEN_DEBUG_CODE( + msg.Printf("charIndex=%d,%d",charIndexCode,charIndexParameters); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +CompiledTemplateLineRaw::~CompiledTemplateLineRaw() +{ +} + +void CompiledTemplateLineRaw::SetRaw(wxString &rawTextIn) +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineRaw","SetRaw") + rawText=rawTextIn; + STATSGEN_DEBUG(DEBUG_RARELY,rawText) + STATSGEN_DEBUG_FUNCTION_END +} + +bool CompiledTemplateLineRaw::ParseTemplateCode() +{ + // Nothing to parse for raw + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineRaw","ParseTemplateCode") + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +bool CompiledTemplateLineRaw::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineRaw","Process") + progress->WakeUp(); + templateFile.WriteTemplateDataToOutput(rawText,variableList); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +CompiledTemplateLineIF::~CompiledTemplateLineIF() +{ +} + +bool CompiledTemplateLineIF::ParseTemplateCode() +{ + bool retVal; + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineIF","ParseTemplateCode") + + SplitParameters(); + // If should have a parameter surrounded by ( ) + templateCodeParameters.Trim(true); + templateCodeParameters.Trim(false); + STATSGEN_DEBUG(DEBUG_RARELY,templateCodeParameters) + if (templateCodeParameters.StartsWith("(") && + templateCodeParameters.EndsWith(")")) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Appears correctly formatted") + retVal=true; + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Syntax error") + // error in syntax + retVal=false; + } + usesSubstitution=UsesSubstitution(); + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool CompiledTemplateLineIF::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + wxString conditionResultString; + bool conditionResult; + wxString conditionStatement; + bool retVal=true; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineIF","Process") + progress->WakeUp(); + if (usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Substitution required") + conditionStatement=variableList.SubstituteVariableValues(templateCodeParameters); + } + else + { + conditionStatement=templateCodeParameters; + } + STATSGEN_DEBUG(DEBUG_RARELY,conditionStatement) + conditionResultString=variableList.GetVariableValue(conditionStatement); + STATSGEN_DEBUG(DEBUG_RARELY,conditionResultString) + conditionResult=(conditionResultString.CmpNoCase(TRUE_STRING)==0); + if (conditionResult) + { + retVal=trueSection.Process(templateFile,variableList); + } + else + { + retVal=falseSection.Process(templateFile,variableList); + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +CompiledTemplateLineLOOP::~CompiledTemplateLineLOOP() +{ +} + +bool CompiledTemplateLineLOOP::ParseTemplateCode() +{ + bool retVal=true; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineLOOP","ParseTemplateCode") + SplitParameters(); + usesSubstitution=UsesSubstitution(); + + if (!usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Doesn't use substitution") + // as it does not use substitution we can extract stuff out + // straight away + retVal = SplitLoopParameters(templateCodeParameters); + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool CompiledTemplateLineLOOP::SplitLoopParameters(wxString ¶meterString) +{ + bool retVal=true; + int tokenCount; + wxString token; + int tokenIndex; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineLOOP","SplitLoopParameters") + STATSGEN_DEBUG(DEBUG_RARELY,parameterString) + // separate out the loop parameters + rowVariableName=""; + indexVariableName=""; + sql=""; + token=GetLineToken(parameterString," ",3,&tokenCount); + STATSGEN_DEBUG_CODE( + msg.Printf("tokenCount [%d], first important token [%s]",tokenCount,token.GetData()); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + if (tokenCount<7) + { + // not enough tokens + retVal=false; + } + else + { + rowVariableName=token; + token=GetLineToken(parameterString," ",6,&tokenCount); + indexVariableName=token; + } + + if (retVal) + { + for (tokenIndex=7;tokenIndex<=tokenCount;tokenIndex++) + { + token=GetLineToken(parameterString," ",tokenIndex,&tokenCount); + if (sql.Length()>0) + { + sql+=" "; + } + sql+=token; + } + STATSGEN_DEBUG(DEBUG_RARELY,rowVariableName) + STATSGEN_DEBUG(DEBUG_RARELY,indexVariableName) + STATSGEN_DEBUG(DEBUG_RARELY,sql) + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool CompiledTemplateLineLOOP::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + bool retVal=true; + bool queryRan=false; + int rowIndex=0; + wxString rowIndexValue; + wxString loopStatement; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineLOOP","Process") + // Store the template query on the stack + if (usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Substitution required") + loopStatement=variableList.SubstituteVariableValues(templateCodeParameters); + STATSGEN_DEBUG(DEBUG_RARELY,loopStatement) + SplitLoopParameters(loopStatement); + } + variableList.StoreQuery(rowVariableName,sql); + while (variableList.QueryNextRow(rowVariableName)&&(retVal)) + { + progress->WakeUp(); + queryRan=true; + + // Store current row index variable + rowIndexValue.Printf("%d",rowIndex+1); + STATSGEN_DEBUG(DEBUG_RARELY,rowIndexValue) + variableList.StoreVariable(indexVariableName,rowIndexValue); + retVal=subSection.Process(templateFile,variableList); + if (!retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"subsection failed") + break; + } + rowIndex++; + } + variableList.RemoveQuery(rowVariableName); + if (!queryRan) + { + } + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + + +CompiledTemplateLineOPENFILE::~CompiledTemplateLineOPENFILE() +{ +} + +bool CompiledTemplateLineOPENFILE::ParseTemplateCode() +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineOPENFILE","ParseTemplateCode") + SplitParameters(); + usesSubstitution=UsesSubstitution(); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +char *CompiledTemplateLineOPENFILE::Mode() +{ + return("w"); +} + +bool CompiledTemplateLineOPENFILE::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + wxString configKey; + wxString localDirectory; + bool retVal; + wxString filename; + TemplateOpenFile *openFile; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineOPENFILE","Process") + progress->WakeUp(); + configKey="/General/LocalOutput"; + globalStatistics.configData.ReadTextValue(configKey,&localDirectory,""); + + wxFileName constructedFile=wxFileName::DirName(localDirectory); + STATSGEN_DEBUG(DEBUG_RARELY,templateCodeParameters) + if (usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Substitution required") + filename=variableList.SubstituteVariableValues(templateCodeParameters); + } + else + { + filename=templateCodeParameters; + } + STATSGEN_DEBUG(DEBUG_RARELY,filename) + constructedFile.SetFullName(filename); + filename=constructedFile.GetFullPath(); + STATSGEN_DEBUG(DEBUG_RARELY,filename) + openFile=new TemplateOpenFile; + retVal=openFile->Open(filename,Mode()); + if (retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"file opened ok") + // Successfully opened file - add it to the openfile stack + variableList.openFiles.Add(openFile); + templateFile.AddCreatedFile(filename); + } + else + { + delete openFile; + msg.Printf("Failed to open output file [%s]",filename.GetData()); + STATSGEN_DEBUG(DEBUG_RARELY,msg) + progress->LogError(msg,SeverityError); + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +CompiledTemplateLineAPPENDFILE::CompiledTemplateLineAPPENDFILE() +{ +} + +CompiledTemplateLineAPPENDFILE::~CompiledTemplateLineAPPENDFILE() +{ +} + +bool CompiledTemplateLineAPPENDFILE::ParseTemplateCode() +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineAPPENDFILE","ParseTemplateCode") + SplitParameters(); + usesSubstitution=UsesSubstitution(); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +char *CompiledTemplateLineAPPENDFILE::Mode() +{ + return("a"); +} + +CompiledTemplateLineCLOSEFILE::~CompiledTemplateLineCLOSEFILE() +{ +} + +bool CompiledTemplateLineCLOSEFILE::ParseTemplateCode() +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineCLOSEFILE","CloseFile") + SplitParameters(); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +bool CompiledTemplateLineCLOSEFILE::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineAPPENDFILE","Process") + progress->WakeUp(); + templateFile.CloseFile(variableList); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +CompiledTemplateLineVARIABLE::~CompiledTemplateLineVARIABLE() +{ +} + +bool CompiledTemplateLineVARIABLE::ParseTemplateCode() +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineVARIABLE","ParseTemplateCode") + usesSubstitution=UsesSubstitution(); + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +bool CompiledTemplateLineVARIABLE::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLineVARIABLE","Process") + wxString value; + wxString variableName; + + progress->WakeUp(); + STATSGEN_DEBUG(DEBUG_RARELY,templateCode) + if (usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Substitution required") + variableName=variableList.SubstituteVariableValues(templateCode); + } + else + { + variableName=templateCode; + } + STATSGEN_DEBUG(DEBUG_RARELY,variableName) + value=variableList.GetVariableValue(variableName); + templateFile.WriteTemplateDataToOutput(value,variableList); + STATSGEN_DEBUG(DEBUG_RARELY,value) + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +CompiledTemplateSection::CompiledTemplateSection() +{ +} + + +CompiledTemplateSection::~CompiledTemplateSection() +{ + int compiledTemplateLineIndex; + CompiledTemplateLine *compiledTemplateLine; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateSection","Destructor") + + /* + for (compiledTemplateLineIndex=0; + compiledTemplateLineIndexWakeUp(); + STATSGEN_DEBUG_CODE( + msg.Printf("line index = %d",compiledTemplateLineIndex); + ) + STATSGEN_DEBUG(DEBUG_RARELY,msg) + compiledTemplateLine=(CompiledTemplateLine *)compiledTemplateLines.Item(compiledTemplateLineIndex); + retVal=compiledTemplateLine->Process(templateFile,variableList); + if (!retVal) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Failed to process compiled line") + break; + } + } + + STATSGEN_DEBUG_FUNCTION_END + return(retVal); +} + +CompiledTemplateLinePROCEDURE::~CompiledTemplateLinePROCEDURE() +{ +} + +bool CompiledTemplateLinePROCEDURE::ParseTemplateCode() +{ + bool retVal; + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLinePROCEDURE","ParseTemplateCode") + wxString parameterList; + wxString parameter; + + SplitParameters(); + // should have a parameter surrounded by ( ) and preceeded by the procedure name + templateCodeParameters.Trim(true); + templateCodeParameters.Trim(false); + STATSGEN_DEBUG(DEBUG_RARELY,templateCodeParameters) + procedureName=templateCodeParameters.BeforeFirst('('); + parameterList=templateCodeParameters.AfterFirst('('); + parameterList=parameterList.BeforeLast(')'); + STATSGEN_DEBUG(DEBUG_RARELY,procedureName); + STATSGEN_DEBUG(DEBUG_RARELY,parameterList); + if (procedureName.Length()>0) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Appears correctly formatted"); + while (parameterList.Length()>0) + { + STATSGEN_DEBUG(DEBUG_RARELY,parameterList); + parameter=parameterList.BeforeFirst(','); + STATSGEN_DEBUG(DEBUG_RARELY,parameter); + parameterList=parameterList.AfterFirst(','); + STATSGEN_DEBUG(DEBUG_RARELY,parameterList); + parameterVars.Add(parameter); + } + retVal=true; + } + else + { + STATSGEN_DEBUG(DEBUG_RARELY,"Syntax error") + // error in syntax + retVal=false; + } + usesSubstitution=false; + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +bool CompiledTemplateLinePROCEDURE::Process(TemplateFile &templateFile, + TemplateVariable &variableList) +{ + wxString parameterListValues; + bool retVal=true; + + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLinePROCEDURE","Process") + progress->WakeUp(); + /* + if (usesSubstitution) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Substitution required") + parameterListValues=variableList.SubstituteVariableValues(templateCodeParameters); + } + else + { + parameterListValues=templateCodeParameters; + } + STATSGEN_DEBUG(DEBUG_RARELY,parameterListValues) + //conditionResultString=variableList.GetVariableValue(conditionStatement); + */ + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +void CompiledTemplateLinePROCEDURE::Execute(TemplateFile *templateFile,TemplateVariable &variableList,TemplateValueList *parameterValues) +{ + STATSGEN_DEBUG_FUNCTION_START("CompiledTemplateLinePROCEDURE","Execute") + int parameterCount; + int parameterIndex; + int parameterVarCount; + wxString parameter; + wxString parameterVar; + wxString msg; + TemplateValue *parameterValue; + wxString valueString; + + parameterVarCount=parameterVars.GetCount(); + parameterCount = parameterValues->GetCount(); + + for (parameterIndex=0;(parameterIndexItem(parameterIndex); + parameter=parameterVars.Item(parameterIndex); + parameterVar.Printf("self_%s",parameter.GetData()); + STATSGEN_DEBUG(DEBUG_RARELY,parameter) + STATSGEN_DEBUG(DEBUG_RARELY,parameterVar) + STATSGEN_DEBUG(DEBUG_RARELY,parameterValue) + if (parameterValue->IsQuery()) + { + TemplateOpenQuery *clonedQuery; + + clonedQuery=new TemplateOpenQuery(); + clonedQuery->Clone(parameterValue->GetQuery()); + variableList.StoreOpenQuery(parameterVar,clonedQuery); + } + else + { + valueString = parameterValue->GetString(); + variableList.StoreVariable(parameterVar,valueString); + } + } + procedureBody.Process(*templateFile,variableList); + STATSGEN_DEBUG_FUNCTION_END +} diff --git a/TemplateFile.h b/TemplateFile.h new file mode 100644 index 0000000..bef4c00 --- /dev/null +++ b/TemplateFile.h @@ -0,0 +1,239 @@ +#ifndef __TEMPLATEFILE +#define __TEMPLATEFILE + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen Includes +#include "TemplateVariable.h" +#include "DynamicArrays.h" + +enum +{ + TEMPLATE_COMMAND_VARIABLE, + TEMPLATE_COMMAND_IF, + TEMPLATE_COMMAND_ELSE, + TEMPLATE_COMMAND_ENDIF, + TEMPLATE_COMMAND_LOOP, + TEMPLATE_COMMAND_ENDLOOP, + TEMPLATE_COMMAND_OPENFILE, + TEMPLATE_COMMAND_CLOSEFILE, + TEMPLATE_COMMAND_APPENDFILE, + TEMPLATE_COMMAND_PROCEDURE, + TEMPLATE_COMMAND_RETURN +}; +enum +{ + TEMPLATE_FINISHED_ERROR, + TEMPLATE_FINISHED_OK, + TEMPLATE_FINISHED_EOF, + TEMPLATE_FINISHED_ELSE, + TEMPLATE_FINISHED_ENDIF, + TEMPLATE_FINISHED_ENDLOOP, + TEMPLATE_FINISHED_RETURN +}; + + +class TemplateFile; +class CompiledTemplateLine +{ + public: + CompiledTemplateLine(); + virtual ~CompiledTemplateLine(); + bool SetTemplateCode(wxString &templateCodeIn); + virtual bool Process(TemplateFile &templateFile,TemplateVariable &variableList); + + protected: + virtual bool ParseTemplateCode(); + void SplitParameters(); + bool UsesSubstitution(); + + protected: + wxString templateCode; + wxString templateCodeParameters; + bool usesSubstitution; + +}; + +WX_DECLARE_OBJARRAY(CompiledTemplateLine,ArrayOfCompiledTemplateLine); +class CompiledTemplateSection +{ + public: + CompiledTemplateSection(); + virtual ~CompiledTemplateSection(); + void Add(CompiledTemplateLine *compiledTemplateLine); + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + + private: + ArrayOfPointers compiledTemplateLines; + +}; + +class CompiledTemplateLineRaw : public CompiledTemplateLine +{ + public: + void SetRaw(wxString &rawTextIn); + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineRaw(); + + protected: + virtual bool ParseTemplateCode(); + + private: + wxString rawText; +}; + +class CompiledTemplateLineIF : public CompiledTemplateLine +{ + public: + CompiledTemplateSection trueSection; + CompiledTemplateSection falseSection; + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineIF(); + + protected: + virtual bool ParseTemplateCode(); +}; + +class CompiledTemplateLinePROCEDURE : public CompiledTemplateLine +{ + public: + CompiledTemplateSection procedureBody; + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLinePROCEDURE(); + void Execute(TemplateFile *templateFile,TemplateVariable &variableList,TemplateValueList *parameterValues); + + wxString procedureName; + wxArrayString parameterVars; + + protected: + virtual bool ParseTemplateCode(); +}; + +class CompiledTemplateLineLOOP : public CompiledTemplateLine +{ + public: + CompiledTemplateSection subSection; + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineLOOP(); + protected: + virtual bool ParseTemplateCode(); + private: + bool SplitLoopParameters(wxString ¶meterString); + private: + wxString rowVariableName; + wxString indexVariableName; + wxString sql; +}; + +class CompiledTemplateLineOPENFILE : public CompiledTemplateLine +{ + public: + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineOPENFILE(); + protected: + virtual bool ParseTemplateCode(); + virtual char *Mode(); +}; + +class CompiledTemplateLineCLOSEFILE : public CompiledTemplateLine +{ + public: + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineCLOSEFILE(); + protected: + virtual bool ParseTemplateCode(); +}; + +class CompiledTemplateLineAPPENDFILE : public CompiledTemplateLineOPENFILE +{ + public: + CompiledTemplateLineAPPENDFILE(); + virtual ~CompiledTemplateLineAPPENDFILE(); + protected: + virtual char *Mode(); + virtual bool ParseTemplateCode(); +}; + +class CompiledTemplateLineVARIABLE : public CompiledTemplateLine +{ + public: + virtual bool Process(TemplateFile &templateFile, + TemplateVariable &variableList); + virtual ~CompiledTemplateLineVARIABLE(); + protected: + virtual bool ParseTemplateCode(); +}; + +class TemplateFile +{ + public: + TemplateFile(); + virtual ~TemplateFile(); + bool Compile(CompiledTemplateSection &compiledSection, + int *currentLineIndex, + wxString ¤tTemplateLine, + int *finishedType, + TemplateVariable &templateVariable); + bool Process(); + void Debug(); + bool ReadTemplate(wxString &filename); + void GetCreatedFiles(wxArrayString &filelist); + void ExportToCPP(wxString &filename,wxString &prefix); + int IdentifyTemplateCode(wxString &templateCode); + void AddCreatedFile(wxString &filename); + bool WriteTemplateDataToOutput(wxString &text, + TemplateVariable &templateVariable); + bool CloseFile(TemplateVariable &templateVariable); + void AddCustomProcedure(CompiledTemplateLinePROCEDURE *procedure); + CompiledTemplateLinePROCEDURE *FindCustomProcedure(wxString &name); + private: + void Unload(); + bool SplitTemplateLine(wxString &templateLine, + wxString *beforeTemplateCode, + wxString *templateCode, + wxString *afterTemplateCode); + bool ReadTemplateFile(wxString &filename,wxString parent); + bool ProcessTemplate(bool allowProcessing, + TemplateVariable &templateVariable, + int *lineIndex, + wxString &templateLine, + bool *endedOnElse); + bool OpenFile(wxString &templateCode, + char *mode, + TemplateVariable &templateVariable); + bool Loop(TemplateVariable &templateVariable, + wxString &templateCodeText, + wxString &rowVariable, + wxString &rowIndexVariable, + wxString &SQLQuery); + void LoadTemplateFile(wxString &filename); + void AddTemplateLine(wxString &line,wxString &lineRef); + wxString TemplateErrorDetails(int lineIndex); + wxArrayPtrVoid customProcedures; + + private: + wxArrayString templateLines; + wxArrayString templateLineRef; + wxArrayString createdFiles; + wxString currentTemplateFile; + int currentTemplateLine; + wxString originalTemplateFile; + + ArrayOfPointers usedTemplateFiles; + wxArrayString usedTemplateFilenames; + +}; + + +#endif diff --git a/TemplateOpenFile.cpp b/TemplateOpenFile.cpp new file mode 100644 index 0000000..1ca641d --- /dev/null +++ b/TemplateOpenFile.cpp @@ -0,0 +1,64 @@ +#include + +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "TemplateOpenFile.h" +#include "ErrorData.h" + +TemplateOpenFile::TemplateOpenFile() +{ + fp=NULL; +} + +TemplateOpenFile::~TemplateOpenFile() +{ + wxString msg; + +// msg.Printf("TemplateOpenFile::Destructor:Entering [%s]",filename.GetData()); +// StatsgenDebug(msg); + if (fp!=NULL) + { +// StatsgenDebug("TemplateOpenFile::Destructor:Closing file"); + fclose(fp); + fp=NULL; + } +// StatsgenDebug("TemplateOpenFile::Destructor:Leaving"); +} + +bool TemplateOpenFile::Open(wxString &filenameIn,char *mode) +{ + bool retVal=false; + wxString msg; + + filename=filenameIn; +// msg.Printf("Entering:Opening file [%s] in mode [%s]",filename.GetData(),mode); +// StatsgenDebug(msg); + fp=fopen(filename.GetData(),mode); + if (fp!=NULL) + { +// StatsgenDebug("Successfully opened"); + retVal=true; + } +// msg.Printf("Leaving:Opening file [%s] in mode [%s]",filename.GetData(),mode); +// StatsgenDebug(msg); + + return (retVal); +} + +bool TemplateOpenFile::Write(wxString &text) +{ + bool retVal=false; + wxString msg; + + if (fp!=NULL) + { + retVal=true; + fprintf(fp,"%s",text.GetData()); + } + return (retVal); +} + diff --git a/TemplateOpenFile.h b/TemplateOpenFile.h new file mode 100644 index 0000000..93ce9af --- /dev/null +++ b/TemplateOpenFile.h @@ -0,0 +1,31 @@ +#ifndef __TEMPLATEOPENFILE +#define __TEMPLATEOPENFILE + +#include +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class TemplateOpenFile; + +WX_DECLARE_OBJARRAY(TemplateOpenFile,ArrayOfTemplateOpenFile); +class TemplateOpenFile +{ + public: + TemplateOpenFile(); + virtual ~TemplateOpenFile(); + + public: + bool Open(wxString &filename,char *mode); + bool Write(wxString &text); + + private: + FILE *fp; + wxString filename; +}; + + +#endif diff --git a/TemplateOpenQuery.cpp b/TemplateOpenQuery.cpp new file mode 100644 index 0000000..5eae742 --- /dev/null +++ b/TemplateOpenQuery.cpp @@ -0,0 +1,217 @@ +// wxWindows includes +#include +#include +#include + +// standard includes +#include +#include +// Statsgen includes +#include "TemplateOpenQuery.h" +#include "GlobalStatistics.h" +#include "Progress.h" + +TemplateOpenQuery::TemplateOpenQuery() +{ + query=NULL; +} + +bool TemplateOpenQuery::Initiate(wxString &SQLIn, + sqlite3 *dbHandleIn) +{ + bool retVal=true; + wxString msg; + const char *unusedSQL; + int status; + + STATSGEN_DEBUG_FUNCTION_START("TemplateOpenQuery","Initiate") + + SQL=SQLIn; + dbHandle=dbHandleIn; + if (dbHandle!=NULL) + { + status=sqlite3_prepare(dbHandle, + SQL.GetData(), + -1, + &query, + &unusedSQL); + + if (status==SQLITE_OK) + { + int columnIndex; + const char *columnNamePtr; + wxString columnName; + + retVal=true; + columnIndex=0; + columnNamePtr=sqlite3_column_name(query,columnIndex); + while (columnNamePtr!=NULL) + { + columnName=columnNamePtr; + columnNames.Add(columnName); + columnIndex++; + columnNamePtr=sqlite3_column_name(query,columnIndex); + } + } + else + { + retVal=false; + msg.Printf("Failed to prepare [%s]",SQL.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + query=NULL; + } + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"null db handle"); + retVal=false; + query=NULL; + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +TemplateOpenQuery::~TemplateOpenQuery() +{ + if (query!=NULL) + { + // Clear down any memory used by the query and delete it + sqlite3_finalize(query); + query=NULL; + } +} + +bool TemplateOpenQuery::NextRow() +{ + bool retVal=false; + wxString msg; + int status; + int columnCount; + int columnIndex; + wxString value; + STATSGEN_DEBUG_FUNCTION_START("TemplateOpenQuery","NextRow") + + columnValues.Clear(); + if (query!=NULL) + { + status=sqlite3_step(query); + switch (status) + { + case SQLITE_ROW: + columnCount=columnNames.GetCount(); + for (columnIndex=0;columnIndex=0) && (columnIndexColumnCount(); + for (columnIndex=0;columnIndexGetColumnName(columnIndex); + columnValue=orgQuery->GetColumnValue(columnIndex); + columnNames.Add(columnName); + columnValues.Add(columnValue); + } +} + +wxString TemplateOpenQuery::GetColumnName(int index) +{ + wxString retVal=""; + + if ((index>=0)&&(index=0)&&(index +#include +#include + +// Statsgen Includes +#include "sqlite3.h" +//#include "libsqlitewrapped.h" + +class TemplateOpenQuery; + +WX_DECLARE_OBJARRAY(TemplateOpenQuery,ArrayOfTemplateOpenQuery); + +class TemplateOpenQuery +{ + public: + TemplateOpenQuery(); + virtual ~TemplateOpenQuery(); + bool NextRow(); + bool Initiate(wxString &SQLIn, + sqlite3 *dbHandleIn); + wxString RetrieveProperty(wxString &property); + + void Clone(TemplateOpenQuery *orgQuery); + wxString GetColumnName(int index); + wxString GetColumnValue(int index); + int ColumnCount(); + public: + wxString variable; + + private: + sqlite3_stmt *query; + sqlite3 *dbHandle; + wxArrayString columnNames; + wxString SQL; + wxArrayString columnValues; + +}; + + +#endif diff --git a/TemplateVariable.cpp b/TemplateVariable.cpp new file mode 100644 index 0000000..a337308 --- /dev/null +++ b/TemplateVariable.cpp @@ -0,0 +1,1271 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "TemplateVariable.h" +#include "GlobalStatistics.h" +#include "LogFileReader.h" +#include "ErrorData.h" +#include "Progress.h" +#include "StaticFunctions.h" + +TemplateVariable::TemplateVariable() +{ + templateFile = NULL; + currentProcedurePrefix=""; +} + +TemplateVariable::~TemplateVariable() +{ +} + +bool TemplateVariable::StoreVariable(wxString &variableOrg,wxString &value) +{ + bool retVal=true; + int variableCount; + int variableIndex; + TemplateVariableField variableField; + wxString variable; + + STATSGEN_DEBUG_FUNCTION_START("TemplateVariable","StoreVariable") + + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + STATSGEN_DEBUG(DEBUG_RARELY,variableOrg) + STATSGEN_DEBUG(DEBUG_RARELY,variable) + STATSGEN_DEBUG(DEBUG_RARELY,currentProcedurePrefix) + STATSGEN_DEBUG(DEBUG_RARELY,value) + // Let us find the variable first (if it exists) + variableCount=variableFields.GetCount(); + for (variableIndex=0;variableIndexvariable.Cmp(variable)==0) + { + // This variable already exists + found=true; + break; + } + else + { + // Add it back - we are not interested in it + openQueries.Add(openQuery); + } + } + + if (found) + { + // found the query - get next row from it + retVal=openQuery->NextRow(); + // now we have used it - we can add it back + openQueries.Add(openQuery); + } + else + { + msg.Printf("Could not find stored query [%s]",variable.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + progress->LogError(msg,SeverityCaution); + retVal=false; + } + + STATSGEN_DEBUG_FUNCTION_END + return (retVal); +} + +wxString TemplateVariable::SubstituteVariableValues(wxString &text) +{ + // Variables within a template code are identified by %% symbols + int charIndexStart; + int charIndexLength; + wxString variable; + wxString value; + wxString afterVarSymbols; + bool finished=false; + wxString msg; + wxString workingText; + + STATSGEN_DEBUG_FUNCTION_START("TemplateVariable","SubstituteVariableValues") + + workingText=text; + + while (!finished) + { + charIndexStart=workingText.Find("%%"); + if (charIndexStart<0) + { + finished=true; + } + else + { + // Found the first %% - need to find the end one + afterVarSymbols=workingText.Mid(charIndexStart+2); + charIndexLength=afterVarSymbols.Find("%%"); + if (charIndexLength<0) + { + msg.Printf("Closing %% missing from [%s]",workingText.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + finished=true; + } + else + { + wxString search; + wxString tempVariable; + + variable=afterVarSymbols.Left(charIndexLength); + tempVariable=variable; + value=GetVariableValue(tempVariable); + search="%%"+variable+"%%"; + workingText.Replace(search,value); + } + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (workingText); +} + +bool TemplateVariable::StoreQuery(wxString &variableOrg,wxString &SQL) +{ + bool retVal=true; + int variableCount; + int variableIndex; + TemplateOpenQuery *openQuery=NULL; + wxString msg; + wxString variable; + + + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + // Let us find the variable first (if it exists) + variableCount=openQueries.GetCount(); + for (variableIndex=0;variableIndexvariable.Cmp(variable)==0) + { + // This variable already exists - remove it - and stop + // searching - we will add it at the end + delete openQuery; + openQuery=NULL; + break; + } + else + { + // We are not interested in this query - add it back + openQueries.Add(openQuery); + } + } + + openQuery=new TemplateOpenQuery; + openQuery->variable=variable; + openQuery->Initiate(SQL, + globalStatistics.statsgenDatabase.DBHandle()); + openQueries.Add(openQuery); + + return (retVal); +} + +bool TemplateVariable::RemoveQuery(wxString &variableOrg) +{ + bool retVal=true; + int variableCount; + int variableIndex; + TemplateOpenQuery *openQuery=NULL; + wxString variable; + wxString msg; + + + // Let us find the variable first (if it exists) + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + variableCount=openQueries.GetCount(); + for (variableIndex=0;variableIndexvariable.Cmp(variable)==0) + { + // This variable already exists - remove it - and stop + // searching - we will add it at the end + delete openQuery; + openQuery=NULL; + break; + } + else + { + // not interested in this query - add it back + openQueries.Add(openQuery); + } + } + + return (retVal); +} + +wxString TemplateVariable::Hash(wxString &text) +{ + wxString retVal; + int textLength; + int charIndex; + int charValue; + wxString coded; + + retVal=""; + textLength=text.Length(); + for (charIndex=0;charIndex'f') && (charValue<='z')) + { + coded.Printf("%c",charValue); + } + else + { + coded.Printf("%02x",charValue); + } + retVal+=coded; + } + + return (retVal); +} + +wxString TemplateVariable::ColouredText2HTML(wxString &colouredText) +{ + wxString font0; + wxString font1; + wxString font2; + wxString font3; + wxString font4; + wxString font5; + wxString font6; + wxString font7; + wxString font8; + wxString font9; + + wxString configKey; + wxString replace; + wxString retVal; + + retVal=colouredText; + + configKey="/Colours/0";globalStatistics.configData.ReadTextValue(configKey,&font0,"000000"); + configKey="/Colours/1";globalStatistics.configData.ReadTextValue(configKey,&font1,"FF0000"); + configKey="/Colours/2";globalStatistics.configData.ReadTextValue(configKey,&font2,"00FF00"); + configKey="/Colours/3";globalStatistics.configData.ReadTextValue(configKey,&font3,"FFFF00"); + configKey="/Colours/4";globalStatistics.configData.ReadTextValue(configKey,&font4,"0000FF"); + configKey="/Colours/5";globalStatistics.configData.ReadTextValue(configKey,&font5,"00FFFF"); + configKey="/Colours/6";globalStatistics.configData.ReadTextValue(configKey,&font6,"FF00FF"); + configKey="/Colours/7";globalStatistics.configData.ReadTextValue(configKey,&font7,"FFFFFF"); + configKey="/Colours/8";globalStatistics.configData.ReadTextValue(configKey,&font8,"008000"); + configKey="/Colours/9";globalStatistics.configData.ReadTextValue(configKey,&font9,"808080"); + + // safetyfi - that's a good word isn't it - the html + retVal.Replace("&","&"); + retVal.Replace("\"","""); + retVal.Replace("<","<"); + retVal.Replace(">",">"); + + // Replace colours + replace.Printf("",font0.GetData());retVal.Replace("^0",replace.GetData()); + replace.Printf("",font1.GetData());retVal.Replace("^1",replace.GetData()); + replace.Printf("",font2.GetData());retVal.Replace("^2",replace.GetData()); + replace.Printf("",font3.GetData());retVal.Replace("^3",replace.GetData()); + replace.Printf("",font4.GetData());retVal.Replace("^4",replace.GetData()); + replace.Printf("",font5.GetData());retVal.Replace("^5",replace.GetData()); + replace.Printf("",font6.GetData());retVal.Replace("^6",replace.GetData()); + replace.Printf("",font7.GetData());retVal.Replace("^7",replace.GetData()); + replace.Printf("",font8.GetData());retVal.Replace("^8",replace.GetData()); + replace.Printf("",font9.GetData());retVal.Replace("^9",replace.GetData()); + + // add in close fonts + retVal.Replace("",font7.GetData()); + retVal=replace+retVal; + // Add in closing font + retVal=retVal+""; + + return (retVal); +} + +wxString TemplateVariable::GetVariableValue(wxString &templateCode) +{ + int tokenCount; + wxString variable; + TemplateOpenQuery *openQuery; + wxString value; + wxString queryProperty; + wxString msg; + wxString functionName; + wxString parameter; + wxString parameterValue; + wxString assignmentVar; + + STATSGEN_DEBUG_FUNCTION_START("TemplateVariable","GetVariableValue") + + STATSGEN_DEBUG(DEBUG_RARELY,templateCode) + if (templateCode[0]=='\"') + { + // we have found a literal e.g. "shaun" + // Skip past opening quotes + templateCode=templateCode.AfterFirst('\"'); + // parameter is before closing quote + parameterValue=templateCode.BeforeFirst('\"'); + // remaining template code is after closing quote + templateCode=templateCode.AfterFirst('\"'); + + value=parameterValue; + } + else if (templateCode[0]=='(') + { + // We have found a condition + value=EvaluateCondition(templateCode); + } + else + { + assignmentVar=""; + while ( + (templateCode.Length()>0) && + ( isalnum(templateCode[0]) || + (templateCode[0]=='.') || + (templateCode[0]=='-') || + (templateCode[0]=='_') + ) + ) + { + assignmentVar+=templateCode[0]; + templateCode=templateCode.Mid(1); + } + + if ((templateCode.Length()>0) && + (templateCode[0]=='=')) + { + // This is an assignment a=b + templateCode=templateCode.AfterFirst('='); + parameterValue=GetVariableValue(templateCode); + StoreVariable(assignmentVar,parameterValue); + // no value returned + value=""; + } + else + { + if ((templateCode.Length()>0) && + (templateCode[0]=='(')) + { + wxArrayString parameterValues; + int parameterIndex; + int parameterCount; + wxString parameterValue2; + TemplateValueList parameterValueList; + TemplateValue *parameterValueItem; + + functionName=assignmentVar; + // functions are functioname([parameter],) + // We have found an open bracket - function name before it + templateCode=templateCode.AfterFirst('('); + STATSGEN_DEBUG(DEBUG_RARELY,"Extracting parameter list") + while ((templateCode.Length()>0) && + (templateCode[0]!=')')) + { + parameterValue=GetVariableValue(templateCode); + parameterValues.Add(parameterValue); + parameterValueItem=new TemplateValue; + TemplateOpenQuery *query; + query=RetrieveQuery(templateCode); + if (query == NULL) + { + parameterValueItem->SetString(parameterValue); + } + else + { + parameterValueItem->SetQuery(query); + } + parameterValueList.Add(parameterValueItem); + STATSGEN_DEBUG(DEBUG_RARELY,templateCode) + STATSGEN_DEBUG(DEBUG_RARELY,parameterValue) + if ((templateCode.Length()>0) && + (templateCode[0]!=')')) + { + // More text in template code and it is not a close bracket + // Probably a separating comma - just skip past it + templateCode=templateCode.AfterFirst(','); + } + } + STATSGEN_DEBUG(DEBUG_RARELY,"Extracted parameter list") + // We have scanned all the template code now and are exiting + // parameter search, either because reached end of string or + // found a closing bracket + if (templateCode.Length()>0) + { + templateCode=templateCode.AfterFirst(')'); + } + parameterCount=parameterValues.GetCount(); + if (functionName.CmpNoCase("colouredtext2html")==0) + { + if (parameterCount==1) + { + parameterValue=parameterValues.Item(0); + value=ColouredText2HTML(parameterValue); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 1); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("hash")==0) + { + if (parameterCount==1) + { + parameterValue=parameterValues.Item(0); + value=Hash(parameterValue); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 1); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("formatfloat")==0) + { + if (parameterCount==2) + { + parameterValue=parameterValues.Item(0); + parameterValue2=parameterValues.Item(1); + value=FormatFloat(parameterValue,parameterValue2); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("formatinteger")==0) + { + if (parameterCount==2) + { + parameterValue=parameterValues.Item(0); + parameterValue2=parameterValues.Item(1); + value=FormatInteger(parameterValue,parameterValue2); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("updatestatus")==0) + { + value=UpdateStatus(parameterValues); + } + else if (functionName.CmpNoCase("sql")==0) + { + value=SimpleSQL(parameterValues); + } + else if (functionName.CmpNoCase("case")==0) + { + value=Case(parameterValues); + } + else if (functionName.CmpNoCase("readtemplateconfig")==0) + { + value=ReadTemplateConfig(parameterValues); + } + else if (functionName.CmpNoCase("writeconfig")==0) + { + value=WriteConfig(parameterValues); + } + else if (functionName.CmpNoCase("readconfig")==0) + { + value=ReadConfig(parameterValues); + } + else if (functionName.CmpNoCase("formatdate")==0) + { + if (parameterCount==2) + { + parameterValue=parameterValues.Item(0); + parameterValue2=parameterValues.Item(1); + value=FormatDate(parameterValue,parameterValue2); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("formatduration")==0) + { + if (parameterCount==2) + { + parameterValue=parameterValues.Item(0); + parameterValue2=parameterValues.Item(1); + value=FormatDuration(parameterValue,parameterValue2); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("uppercase")==0) + { + value=""; + for (parameterIndex=0; + parameterIndex=2) + { + parameterValue=parameterValues.Item(0); + parameterValue2=parameterValues.Item(1); + value=MessageCentre(parameterValues); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting at least %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else if (functionName.CmpNoCase("ReadStatistic")==0) + { + if (parameterCount==1) + { + parameterValue=parameterValues.Item(0); + value=ReadStatistic(parameterValue); + } + else + { + msg.Printf("function name [%s()] has %d parameters, but expecting %d", + functionName.GetData(), + parameterCount, + 2); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + } + } + else + { + /* + msg.Printf("Unknown function name [%s(%s)]",functionName.GetData(), + parameter.GetData()); + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + progress->LogError(msg,SeverityError); + */ + ExecuteCustomProcedure(functionName,¶meterValueList); + } + } + else + { + wxString rawVariable; + + rawVariable=assignmentVar; + variable=GetLineToken(rawVariable,".",1,&tokenCount); + value=""; + if (tokenCount!=1) + { + // We are after a query as there is a "." in there + openQuery=RetrieveQuery(variable); + if (openQuery!=NULL) + { + queryProperty=GetLineToken(rawVariable,".",2,&tokenCount); + value=openQuery->RetrieveProperty(queryProperty); + } + else + { +// msg.Printf("Could not find an open query for [%s]", +// rawVariable.GetData()); +// StatsgenDebug(msg); + } + } + else + { + // we are after a single variable + value=RetrieveVariableValue(variable); + } + } + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (value); +} + +TemplateOpenQuery *TemplateVariable::RetrieveQuery(wxString &variableOrg) +{ + TemplateOpenQuery *retVal=NULL; + int variableCount; + int variableIndex; + TemplateOpenQuery *openQuery=NULL; + wxString variable; + wxString msg; + + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + // Let us find the variable first (if it exists) + variableCount=openQueries.GetCount(); + for (variableIndex=0;variableIndexvariable.Cmp(variable)==0) + { + // This is the query we are after + retVal=openQuery; + break; + } + } + + return (retVal); +} + +wxString TemplateVariable::RetrieveVariableValue(wxString &variableOrg) +{ + wxString retVal=""; + int variableCount; + int variableIndex; + TemplateVariableField variableField; + wxString variable; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("TemplateVariable","RetrieveVariableValue") + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + + STATSGEN_DEBUG(DEBUG_RARELY,variableOrg) + STATSGEN_DEBUG(DEBUG_RARELY,variable) + STATSGEN_DEBUG(DEBUG_RARELY,currentProcedurePrefix) + + // Let us find the variable first (if it exists) + variableCount=variableFields.GetCount(); + for (variableIndex=0;variableIndex")==0) + { + result=(leftValue.Cmp(rightValue)>0); + if (bothDouble) + { + result=(leftDouble>rightDouble); + } + if (bothLong) + { + result=(leftLong>rightLong); + } + } + else if (operatorString.CmpNoCase("<")==0) + { + result=(leftValue.Cmp(rightValue)<0); + if (bothDouble) + { + result=(leftDouble0) + { + token=parameters.Item(0); + progress->SetStatus(token); + } + + return (retVal); +} + +wxString TemplateVariable::ReadTemplateConfig(wxArrayString ¶meters) +{ + wxString retVal=""; + int parameterCount; + wxString configKey=""; + wxString configValue=""; + wxString defaultValue=""; + wxString variableHelp=""; + wxString helpConfigKey; + + parameterCount=parameters.GetCount(); + switch (parameterCount) + { + case 0: + // no parameters supplied + break; + case 1: + configKey=parameters.Item(0); + configKey="/TemplateConfigs/"+configKey; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + break; + default: + // at least 2 + configKey=parameters.Item(0); + helpConfigKey="/TemplateConfigsHelp/"+configKey; + configKey="/TemplateConfigs/"+configKey; + defaultValue=parameters.Item(1); + globalStatistics.configData.ReadTextValue(configKey, + &configValue, + (char *)defaultValue.GetData()); + if (parameterCount == 3) + { + variableHelp=parameters.Item(2); + globalStatistics.configData.WriteTextValue(helpConfigKey,variableHelp); + } + break; + } + + retVal=configValue; + return (retVal); +} + +wxString TemplateVariable::ReadConfig(wxArrayString ¶meters) +{ + wxString retVal=""; + int parameterCount; + wxString configKey=""; + wxString configValue=""; + wxString defaultValue=""; + + parameterCount=parameters.GetCount(); + switch (parameterCount) + { + case 0: + // no parameters supplied + break; + case 1: + configKey=parameters.Item(0); + globalStatistics.configData.ReadTextValue(configKey,&configValue); + break; + default: + // at least 2 + configKey=parameters.Item(0); + defaultValue=parameters.Item(1); + globalStatistics.configData.ReadTextValue(configKey, + &configValue, + (char *)defaultValue.GetData()); + break; + } + + retVal=configValue; + return (retVal); +} + +wxString TemplateVariable::WriteConfig(wxArrayString ¶meters) +{ + wxString retVal=""; + int parameterCount; + wxString configKey=""; + wxString configValue=""; + wxString defaultValue=""; + + parameterCount=parameters.GetCount(); + switch (parameterCount) + { + case 0: + case 1: + // not enough parameters supplied + break; + default: + configKey=parameters.Item(0); + configValue=parameters.Item(1); + globalStatistics.configData.WriteTextValue(configKey,configValue); + break; + } + + retVal=""; + return (retVal); +} + +wxString TemplateVariable::SimpleSQL(wxArrayString ¶meters) +{ + wxString retVal=""; + int parameterCount; + int parameterIndex; + wxString token; + wxString SQL; + + SQL=""; + parameterCount=parameters.GetCount(); + for (parameterIndex=0;parameterIndexFindCustomProcedure(procedureName); + if (procedure != NULL) + { + STATSGEN_DEBUG(DEBUG_RARELY,"Found It"); + oldProcedurePrefix=currentProcedurePrefix; + currentProcedurePrefix.Printf("procedure%s",procedureName.GetData()); + procedure->Execute(templateFile,*this,parameterValues); + currentProcedurePrefix=oldProcedurePrefix; + } + else + { + msg.Printf("trying to execute non-existant procedure [%s]",procedureName.GetData()); + progress->LogError(msg,SeverityCaution); + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +bool TemplateVariable::StoreOpenQuery(wxString &variableOrg,TemplateOpenQuery *openQuery) +{ + wxString variable; + + variable=variableOrg; + variable.Replace("self_",currentProcedurePrefix); + openQuery->variable=variable; + openQueries.Add(openQuery); + + return (true); +} + +TemplateValue::TemplateValue() +{ + value = ""; + query = NULL; +} + +TemplateValue::~TemplateValue() +{ + Unload(); +} + +void TemplateValue::Unload() +{ + // No need to unload - all queries are links to existing ones +} + +bool TemplateValue::IsQuery() +{ + return (query!=NULL); +} + +void TemplateValue::SetQuery(TemplateOpenQuery *queryIn) +{ + query=queryIn; +} + +void TemplateValue::SetString(wxString &valueIn) +{ + value=valueIn; +} + +TemplateOpenQuery *TemplateValue::GetQuery() +{ + return (query); +} + +wxString TemplateValue::GetString() +{ + return (value); +} + +TemplateValueList::TemplateValueList() +{ +} + + +TemplateValueList::~TemplateValueList() +{ + Unload(); +} + +void TemplateValueList::Add(TemplateValue *value) +{ + values.Add(value); +} + +int TemplateValueList::GetCount() +{ + return (values.GetCount()); +} + +TemplateValue *TemplateValueList::Item(int index) +{ + TemplateValue *retVal=NULL; + if ((index >=0) && (index < GetCount())) + { + retVal=(TemplateValue *)values.Item(index); + } + + return (retVal); +} + +void TemplateValueList::Unload() +{ + TemplateValue *value; + int count; + int index; + + count=GetCount(); + for (index=0;index +#include +#include + +// Statsgen Includes +#include "TemplateOpenFile.h" +#include "TemplateOpenQuery.h" +#include "TemplateVariableField.h" + +#define TRUE_STRING "TRUE" +#define FALSE_STRING "FALSE" + +class TemplateFile; +class TemplateValue +{ + public: + TemplateValue(); + ~TemplateValue(); + bool IsQuery(); + void SetQuery(TemplateOpenQuery *queryIn); + void SetString(wxString &valueIn); + TemplateOpenQuery *GetQuery(); + wxString GetString(); + private: + void Unload(); + wxString value; + TemplateOpenQuery *query; +}; + +class TemplateValueList +{ + public: + TemplateValueList(); + ~TemplateValueList(); + void Add(TemplateValue *value); + int GetCount(); + TemplateValue *Item(int index); + private: + void Unload(); + wxArrayPtrVoid values; +}; + +class TemplateVariable +{ + public: + TemplateVariable(); + virtual ~TemplateVariable(); + bool StoreVariable(wxString &variable,wxString &value); + bool StoreQuery(wxString &variable,wxString &SQL); + bool StoreOpenQuery(wxString &variable,TemplateOpenQuery *queryIn); + bool QueryNextRow(wxString &variable); + bool RemoveQuery(wxString &variable); + wxString GetVariableValue(wxString &templateCode); + wxString SubstituteVariableValues(wxString &text); + static wxString ColouredText2HTML(wxString &colouredText); + wxString FormatDuration(wxString &format, wxString &duration); + wxString FormatDate(wxString &format, wxString &secondssince1970); + wxString FormatInteger(wxString &format, wxString &integerStr); + wxString FormatFloat(wxString &format, wxString &floatStr); + wxString EvaluateCondition(wxString &condition); + static wxString Hash(wxString &text); + wxString ReadStatistic(wxString &variable); + wxString MessageCentre(wxArrayString ¶meters); + wxString Case(wxArrayString ¶meters); + wxString UpdateStatus(wxArrayString ¶meters); + wxString SimpleSQL(wxArrayString ¶meters); + wxString ReadTemplateConfig(wxArrayString ¶meters); + wxString ReadConfig(wxArrayString ¶meters); + wxString WriteConfig(wxArrayString ¶meters); + void SetTemplateFile(TemplateFile *templateFileIn); + void ExecuteCustomProcedure(wxString &procedureName,TemplateValueList *parameterValues); + + public: + ArrayOfTemplateOpenFile openFiles; + ArrayOfTemplateOpenQuery openQueries; + ArrayOfTemplateVariableField variableFields; + + private: + TemplateOpenQuery *RetrieveQuery(wxString &variable); + wxString RetrieveVariableValue(wxString &variable); + TemplateFile *templateFile; + + wxString currentProcedurePrefix; + +}; + + +#endif diff --git a/TemplateVariableField.cpp b/TemplateVariableField.cpp new file mode 100644 index 0000000..e6e6e05 --- /dev/null +++ b/TemplateVariableField.cpp @@ -0,0 +1,15 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "TemplateVariableField.h" + +TemplateVariableField::TemplateVariableField() +{ +} + +TemplateVariableField::~TemplateVariableField() +{ +} diff --git a/TemplateVariableField.h b/TemplateVariableField.h new file mode 100644 index 0000000..ef86a5a --- /dev/null +++ b/TemplateVariableField.h @@ -0,0 +1,27 @@ +#ifndef __TEMPLATEVARIABLEFIELD +#define __TEMPLATEVARIABLEFIELD + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes +class TemplateVariableField; + +WX_DECLARE_OBJARRAY(TemplateVariableField,ArrayOfTemplateVariableField); + +class TemplateVariableField +{ + public: + TemplateVariableField(); + virtual ~TemplateVariableField(); + + public: + wxString variable; + wxString value; + +}; + + +#endif diff --git a/TextConfigItemGUI.cpp b/TextConfigItemGUI.cpp new file mode 100644 index 0000000..b52df40 --- /dev/null +++ b/TextConfigItemGUI.cpp @@ -0,0 +1,233 @@ +// Statsgen Includes +#include "TextConfigItemGUI.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(TextConfigItemGUI, wxPanel) + EVT_SIZE(TextConfigItemGUI::OnResize) + EVT_TEXT(WINDOW_ID_TEXTCTRL_CONFIGVALUE,TextConfigItemGUI::OnTextChange) +END_EVENT_TABLE() + +TextConfigItemGUI::TextConfigItemGUI() +{ + maxCharacters=-1; +} + +void TextConfigItemGUI::OnTextChange(wxCommandEvent& event) +{ + wxString key; + wxString value; + wxString keyOnly; + wxString pathOnly; + wxString weaponGroupKey; + wxArrayString weaponGroupKeys; + int keyCount; + int keyIndex; + wxString weaponGroupConfigKey; + + value=textEdit.GetValue(); + if (configKey.Length()>0) + { + keyOnly=configKey.AfterLast('/'); + pathOnly=configKey.BeforeLast('/'); + if (globalStatistics.configData.IsWeaponGroupKey(keyOnly)) + { + if (value.Length()>0) + { + weaponGroupKeys=globalStatistics.configData.WeaponGroupKeys(keyOnly); + keyCount=weaponGroupKeys.GetCount(); + for (keyIndex=0;keyIndexAddPendingEvent(newEvent); + } +} + +TextConfigItemGUI::~TextConfigItemGUI() +{ +} + +void TextConfigItemGUI::SetConfigKey(wxString &configKeyIn) +{ + wxString value; + wxString keyOnly; + wxString pathOnly; + wxString weaponGroupKey; + wxArrayString weaponGroupKeys; + int keyCount; + int keyIndex; + wxString weaponGroupConfigKey; + wxString weaponGroupValue; + wxString msg; + + configKey=configKeyIn; + if (configKey.Length()>0) + { + keyOnly=configKey.AfterLast('/'); + pathOnly=configKey.BeforeLast('/'); + value=""; + if (globalStatistics.configData.IsWeaponGroupKey(keyOnly)) + { +//msg.Printf("SetConfigKey::%s:%s:%s",configKeyIn.GetData(),pathOnly.GetData(),keyOnly.GetData());wxMessageBox(msg); + weaponGroupKeys=globalStatistics.configData.WeaponGroupKeys(keyOnly); + keyCount=weaponGroupKeys.GetCount(); + for (keyIndex=0;keyIndex0) + { + // We have an overriding field width + if (fixedWidth +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "BaseConfigItemGUI.h" + +class TextConfigItemGUI : public BaseConfigItemGUI +{ + public: + TextConfigItemGUI(); + virtual ~TextConfigItemGUI(); + void OnTextChange(wxCommandEvent& event); + + void SetConfigKey(wxString &configKeyIn); + void SetLabelWidth(int width); + int GetLabelWidth(); + void Set(wxString &configKeyIn, + wxString &labelText, + wxString &defaultValueIn, + int maxCharactersIn); + void OnResize(wxSizeEvent &event); + + wxString GetValue(); + protected: + + private: + wxTextCtrl textEdit; + wxStaticText label; + bool maxCharactersSet; + int maxCharacters; + wxString labelText; + wxString defaultValue; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/TextListDialog.cpp b/TextListDialog.cpp new file mode 100644 index 0000000..9f9f0c5 --- /dev/null +++ b/TextListDialog.cpp @@ -0,0 +1,138 @@ +// Statsgen Includes +#include "TextListDialog.h" +#include "GenericOKCancelDialog.h" +#include "GlobalStatistics.h" +#include "LogFileReader.h" + +BEGIN_EVENT_TABLE(TextListDialog,GenericOKCancelDialog) + EVT_SIZE(TextListDialog::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,TextListDialog::OnNew) +END_EVENT_TABLE() + +TextListDialog::TextListDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + const char *groupIn) : GenericOKCancelDialog + (parent, + id, + title, + pos, + size, + style, + name) +{ + wxArrayString textItems; + + group=groupIn; + singleWords=true; + + newButton.Create(this, + WINDOW_ID_BUTTON_NEW, + _T(WINDOW_ID_BUTTON_NEW_TEXT), + wxDefaultPosition); + globalStatistics.configData.ReadList(group,textItems); + panel=new TextListEditorPanel(); + panel->SetList(textItems); + panel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize + ); +} + +bool TextListDialog::DisplayDialog() +{ + return (GenericOKCancelDialog::DisplayDialog((wxPanel *)panel)); +} + +TextListDialog::~TextListDialog() +{ +} + +void TextListDialog::OnSave(wxCommandEvent &event) +{ + wxString msg; + wxArrayString textItems; + + panel->GetList(textItems); + // Write the TextList List to disk + + globalStatistics.configData.WriteList(group,textItems); + globalStatistics.configData.CommitChanges(); + // Do any standard Save + GenericOKCancelDialog::OnSave(event); +} + +void TextListDialog::OnQuit(wxCommandEvent &event) +{ + wxString msg; + + // Do any standard Save + GenericOKCancelDialog::OnQuit(event); +} + +void TextListDialog::OnNew(wxCommandEvent &event) +{ + wxString message="Enter New"; + wxString caption="Enter New"; + wxString newEntry; + wxString userEntry; + int tokenCount; + int tokenIndex; + + userEntry=wxGetTextFromUser(message,caption); + if (userEntry.Length()>0) + { + if (singleWords) + { + GetLineToken(userEntry," ",1,&tokenCount); + for (tokenIndex=1;tokenIndex<=tokenCount;tokenIndex++) + { + newEntry=GetLineToken(userEntry," ",tokenIndex,&tokenCount); + panel->Add(newEntry); + } + } + else + { + panel->Add(userEntry); + } + } +} + +void TextListDialog::OnResize(wxSizeEvent &event) +{ + int newX; + int newWidth; + int newHeight; + int quitX; + int quitY; + int quitWidth; + wxSize itemSize; + wxPoint itemPos; + GenericOKCancelDialog::OnResize(event); + + itemPos=quitButton.GetPosition(); + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitX=itemPos.x; + quitY=itemPos.y; + + newX=quitX+quitWidth; + itemSize=newButton.GetSize(); + newWidth=itemSize.GetWidth(); + newHeight=itemSize.GetHeight(); + newButton.SetSize(newX,quitY,newWidth,newHeight); +} + +void TextListDialog::SortOn(bool value) +{ + panel->SortOn(value); +} +void TextListDialog::SingleWords(bool value) +{ + singleWords=value; +} diff --git a/TextListDialog.h b/TextListDialog.h new file mode 100644 index 0000000..00b3501 --- /dev/null +++ b/TextListDialog.h @@ -0,0 +1,45 @@ +#ifndef __TEXTLISTDIALOG +#define __TEXTLISTDIALOG + +#include +#include + +// Statsgen Includes +#include "GenericOKCancelDialog.h" +#include "TextListEditorPanel.h" +#include "WindowIDs.h" + +class TextListDialog : public GenericOKCancelDialog +{ + public: + TextListDialog(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name, + const char *group + ); + + virtual ~TextListDialog(); + + virtual void OnSave(wxCommandEvent& event); + virtual void OnQuit(wxCommandEvent& event); + virtual void OnNew(wxCommandEvent& event); + virtual void OnResize(wxSizeEvent &event); + virtual bool DisplayDialog(); + virtual void SortOn(bool value); + virtual void SingleWords(bool value); + wxButton newButton; + + protected: + + private: + TextListEditorPanel *panel; + wxString group; + bool singleWords; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/TextListEditorPanel.cpp b/TextListEditorPanel.cpp new file mode 100644 index 0000000..13f042e --- /dev/null +++ b/TextListEditorPanel.cpp @@ -0,0 +1,216 @@ +// wx includes +#include +#include +#include +#include + +// Statsgen Includes +#include "TextListEditorPanel.h" +#include "GlobalStatistics.h" +#include "StaticFunctions.h" +#include "ErrorData.h" + +BEGIN_EVENT_TABLE(TextListEditorPanel, wxPanel) + EVT_SIZE(TextListEditorPanel::OnResize) + EVT_LIST_ITEM_RIGHT_CLICK(WINDOW_ID_TEXTLIST, + TextListEditorPanel::OnTextListRightClick) + EVT_MENU(TEXTLIST_POPUP_DELETE,TextListEditorPanel::OnPopupMenu) + EVT_LIST_END_LABEL_EDIT(WINDOW_ID_TEXTLIST,TextListEditorPanel::OnLabelEdit) +END_EVENT_TABLE() + +void TextListEditorPanel::SetList(wxArrayString &textListIn) +{ + textList=textListIn; +} + +TextListEditorPanel::TextListEditorPanel() +{ + textListList=NULL; + sortList=true; +} + +void TextListEditorPanel::SortOn(bool value) +{ + sortList=value; +} + +bool TextListEditorPanel::Create(wxWindow *parent, + wxWindowID id, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) +{ + + wxPanel::Create( parent, id, + pos, + size, + style, + name); + + textListList=new wxListCtrl(this, + WINDOW_ID_TEXTLIST, + wxDefaultPosition, + wxDefaultSize, + wxLC_REPORT| + wxLC_EDIT_LABELS); + RefreshTextListTree(); + + wxSizeEvent dummyEvent; + OnResize(dummyEvent); + return (true); +} + +void TextListEditorPanel::OnResize(wxSizeEvent &event) +{ + wxSize itemSize; + int panelWidth; + int panelHeight; + int textListWidth; + int textListHeight; + wxString msg; + + + if (textListList!=NULL) + { + itemSize=GetSize(); + panelWidth=itemSize.GetWidth(); + panelHeight=itemSize.GetHeight(); + + textListWidth=panelWidth; + textListHeight=panelHeight; + + textListList->SetSize(0,0,textListWidth,textListHeight); + } +} + +void TextListEditorPanel::AddTextListEntry(int index,wxString &entry) +{ + long itemIndex; + long listIndex; + long rowNumber; + + rowNumber=index; + itemIndex=index; + + listIndex=textListList->InsertItem(rowNumber,entry); + textListList->SetItemData(listIndex,itemIndex); +} + +void TextListEditorPanel::RefreshTextListTree() +{ + wxString textListEntry; + wxListItem listColumn; + int textListCount; + int textListIndex; + + STATSGEN_DEBUG_FUNCTION_START("TextListEditorPanel","RefreshTextListTree") + if (sortList) + { + textList.Sort(); + } + textListList->Hide(); + + textListList->DeleteAllColumns(); + textListList->DeleteAllItems(); + listColumn.SetText("Word"); + textListList->InsertColumn(0,listColumn); + + textListCount=textList.GetCount(); + for (textListIndex=0;textListIndexSetColumnWidth(0,wxLIST_AUTOSIZE); + textListList->Show(); + STATSGEN_DEBUG_FUNCTION_END +} + +void TextListEditorPanel::OnTextListRightClick(wxListEvent &event) +{ + wxString msg; + wxMenu popupMenu(_T("")); + wxString menuItem; + + // What have we right clicked on - parent or child? + menuItem="Delete"; popupMenu.Append(TEXTLIST_POPUP_DELETE,menuItem); + + popupMenu.AppendSeparator(); + popupMenu.Append(TEXTLIST_POPUP_CANCEL,_T("Cancel")); + PopupMenu(&popupMenu); +} + +void TextListEditorPanel::OnPopupMenu(wxCommandEvent &event) +{ + wxString msg; + int id; + int selectedItem=-1; + int listIndex; + + STATSGEN_DEBUG_FUNCTION_START("TextListEditorPanel","OnPopupMenu") + id=event.GetId(); + + switch (id) + { + case TEXTLIST_POPUP_DELETE: + selectedItem=textListList->GetNextItem(selectedItem, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + STATSGEN_DEBUG_CODE(msg.Printf("Deleting selected index %d",selectedItem);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + while (selectedItem!=-1) + { + listIndex=(int)textListList->GetItemData(selectedItem); + STATSGEN_DEBUG_CODE(msg.Printf("Deleting list index %d",listIndex);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + textList.RemoveAt(listIndex); + selectedItem=-1; + } + RefreshTextListTree(); + break; + } + STATSGEN_DEBUG_FUNCTION_END +} + +void TextListEditorPanel::OnLabelEdit(wxListEvent &event) +{ + wxString msg; + wxString menuItem; + wxMenu popupMenu(_T("")); + long index; + wxString textListEntry; + + STATSGEN_DEBUG_FUNCTION_START("TextListEditorPanel","OnLabelEdit") + index=event.GetIndex(); + + STATSGEN_DEBUG_CODE(msg.Printf("Index edited %d",index);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg); + if (index>=0) + { + textListEntry=textList.Item(index); + STATSGEN_DEBUG(DEBUG_ALWAYS,textListEntry); + textList.RemoveAt(index); + STATSGEN_DEBUG(DEBUG_ALWAYS,event.GetText()); + textList.Add(event.GetText()); + } + + event.Veto(); + RefreshTextListTree(); + STATSGEN_DEBUG_FUNCTION_END +} + +void TextListEditorPanel::GetList(wxArrayString &textListOut) +{ + textListOut=textList; +} + +void TextListEditorPanel::Add(wxString &entry) +{ + textList.Add(entry); + + RefreshTextListTree(); +} + diff --git a/TextListEditorPanel.h b/TextListEditorPanel.h new file mode 100644 index 0000000..754f950 --- /dev/null +++ b/TextListEditorPanel.h @@ -0,0 +1,48 @@ +#ifndef __TEXTLISTEDITORPANEL +#define __TEXTLISTEDITORPANEL + +#include +#include + +// Statsgen Includes +#include "GroupedConfigItemsPanel.h" +#include "WindowIDs.h" + +class TextListEditorPanel : public wxPanel +{ + public: + TextListEditorPanel(); + void SetList(wxArrayString &textListIn); + virtual bool Create(wxWindow *parent, + wxWindowID id=-1, + const wxPoint &pos=wxDefaultPosition, + const wxSize &size=wxDefaultSize, + long style=wxTAB_TRAVERSAL, + const wxString &name="panel"); + void OnResize(wxSizeEvent &event); + void OnTextListRightClick(wxListEvent &event); + void OnLabelEdit(wxListEvent &event); + void OnPopupMenu(wxCommandEvent &event); + void RefreshTextListTree(); + void GetList(wxArrayString &textList); + void Add(wxString &entry); + void SortOn(bool value); + + protected: + + + private: + void AddTextListEntry(int index,wxString &listEntry); + enum + { + TEXTLIST_POPUP_CANCEL=1000, + TEXTLIST_POPUP_DELETE + }; + + wxListCtrl *textListList; + wxArrayString textList; + bool sortList; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/Version.h b/Version.h new file mode 100644 index 0000000..ac9d036 --- /dev/null +++ b/Version.h @@ -0,0 +1,8 @@ +#ifndef __VERSION +#define __VERSION + +#define PROGRAM_VERSION "1.9.3" +#define DATABASE_VERSION 2 +#define TEMPLATE_VERSION 4 +#define CONFIG_VERSION 12 +#endif diff --git a/WeaponGroupDialog.cpp b/WeaponGroupDialog.cpp new file mode 100644 index 0000000..e5e4fe6 --- /dev/null +++ b/WeaponGroupDialog.cpp @@ -0,0 +1,234 @@ +// Statsgen Includes +#include "WeaponGroupDialog.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(WeaponGroupDialog, wxDialog) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,WeaponGroupDialog::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,WeaponGroupDialog::OnQuit) + EVT_BUTTON(WINDOW_ID_BUTTON_NEW,WeaponGroupDialog::OnNew) + EVT_BUTTON(WINDOW_ID_BUTTON_DELETE,WeaponGroupDialog::OnDelete) + EVT_CHECKLISTBOX(WINDOW_ID_SELECTION_CONFIGVALUE,WeaponGroupDialog::OnWeaponSelected) + EVT_LISTBOX(WINDOW_ID_LISTBOX_CONFIGITEMS,WeaponGroupDialog::OnWeaponGroupSelected) +END_EVENT_TABLE() + +WeaponGroupDialog::WeaponGroupDialog( + wxWindow *parent, + wxWindowID id, + wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name) : + wxDialog(parent, + id, + title, + pos, + size, + style, + name) +{ + currentWeaponGroup=""; + CreateScreen(); +} + +void WeaponGroupDialog::CreateScreen() +{ + newButton =new wxButton(this, + WINDOW_ID_BUTTON_NEW, + _T(WINDOW_ID_BUTTON_NEW_TEXT)); + + deleteButton =new wxButton(this, + WINDOW_ID_BUTTON_DELETE, + _T(WINDOW_ID_BUTTON_DELETE_TEXT)); + + saveButton =new wxButton(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT)); + + quitButton =new wxButton(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT)); + + weaponGroupsList=new wxListBox(this,WINDOW_ID_LISTBOX_CONFIGITEMS); + weaponKeysList=new wxCheckListBox(this,WINDOW_ID_SELECTION_CONFIGVALUE); + + buttonSizer=new wxBoxSizer(wxHORIZONTAL); + displaySizer=new wxBoxSizer(wxHORIZONTAL); + mainSizer=new wxBoxSizer(wxVERTICAL); + + buttonSizer->Add(newButton); + buttonSizer->Add(deleteButton); + buttonSizer->Add(saveButton); + buttonSizer->Add(quitButton); + + displaySizer->Add(weaponGroupsList,1,wxEXPAND); + displaySizer->Add(weaponKeysList,1,wxEXPAND); + + displaySizer->SetMinSize(wxSize(640,480)); + mainSizer->Add(displaySizer,1,wxEXPAND); + mainSizer->Add(buttonSizer); + + SetSizer(mainSizer); + mainSizer->SetSizeHints(this); + + PopulateGroupsList(); + PopulateKeysList(); +} + +WeaponGroupDialog::~WeaponGroupDialog() +{ + STATSGEN_DEBUG_FUNCTION_START("WeaponGroupDialog","Destructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void WeaponGroupDialog::PopulateGroupsList() +{ + STATSGEN_DEBUG_FUNCTION_START("WeaponGroupDialog","PopulateGroupsList") + wxArrayString weaponGroups; + + weaponGroups = globalStatistics.configData.ReadWeaponGroups(); + + weaponGroupsList->Clear(); + weaponGroupsList->Append(weaponGroups); + + STATSGEN_DEBUG_FUNCTION_END +} + +void WeaponGroupDialog::CheckKeysList() +{ + STATSGEN_DEBUG_FUNCTION_START("WeaponGroupDialog","CheckKeysList") + wxArrayString currentWeapons; + wxString weaponKey; + wxArrayString weaponGroupKeys; + int weaponGroupIndex; + int weaponKeyIndex; + int weaponKeyCount; + + if (currentWeaponGroup.Length()>0) + { + weaponGroupKeys=globalStatistics.configData.ReadWeaponGroup(currentWeaponGroup); + weaponKeyIndex=weaponKeysList->GetCount(); + for (weaponKeyIndex=0;weaponKeyIndexGetString(weaponKeyIndex); + weaponGroupIndex=weaponGroupKeys.Index(weaponKey); + weaponKeysList->Check(weaponKeyIndex, + (weaponGroupIndex!=wxNOT_FOUND)); + } + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void WeaponGroupDialog::PopulateKeysList() +{ + STATSGEN_DEBUG_FUNCTION_START("WeaponGroupDialog","PopulateKeysList") + wxArrayString keys; + wxArrayString values; + wxString group; + + group="LogEntriesWeapon"; + + weaponKeysList->Clear(); + keys=globalStatistics.configData.ReadWeaponGroups(); + weaponKeysList->Append(keys); + globalStatistics.configData.ReadGroup(group,keys,values); + weaponKeysList->Append(keys); + STATSGEN_DEBUG_FUNCTION_END +} + +void WeaponGroupDialog::WriteCurrentWeaponGroup() +{ + wxArrayString weaponKeys; + int weaponKeyCount; + wxString weaponKey; + int weaponKeyIndex; + wxString configKey; + + if (currentWeaponGroup.Length()>0) + { + weaponKeys=weaponKeysList->GetStrings(); + weaponKeyCount=weaponKeys.GetCount(); + globalStatistics.configData.DeleteGroup(currentWeaponGroup); + globalStatistics.configData.CommitChanges(); + for (weaponKeyIndex=0;weaponKeyIndexIsChecked(weaponKeyIndex)) + { + configKey.Printf("/%s/%s", + currentWeaponGroup.GetData(), + weaponKey.GetData()); + globalStatistics.configData.WriteTextValue(configKey,""); + } + } + globalStatistics.configData.CommitChanges(); + } +} + +void WeaponGroupDialog::OnWeaponSelected(wxCommandEvent &event) +{ +} + +void WeaponGroupDialog::OnWeaponGroupSelected(wxCommandEvent &event) +{ + WriteCurrentWeaponGroup(); + currentWeaponGroup=weaponGroupsList->GetStringSelection(); + CheckKeysList(); +} + +void WeaponGroupDialog::OnSave(wxCommandEvent &event) +{ + WriteCurrentWeaponGroup(); + globalStatistics.configData.CommitChanges(); + EndModal(true); +} + +void WeaponGroupDialog::OnQuit(wxCommandEvent &event) +{ + globalStatistics.configData.RollbackChanges(); + EndModal(false); +} + +void WeaponGroupDialog::OnNew(wxCommandEvent &event) +{ + wxString message="New Weapon Group Identifier"; + wxString caption="Weapon Group"; + wxString weaponGroup; + wxString configKey; + wxString configValue; + + weaponGroup=wxGetTextFromUser(message,caption); + + if (weaponGroup.Length()>0) + { + WriteCurrentWeaponGroup(); + weaponGroup=weaponGroup.Lower(); + if (!globalStatistics.configData.IsWeaponGroupKey(weaponGroup)) + { + weaponGroup=CONFIG_WEAPON_GROUP_PREFIX+weaponGroup; + } + currentWeaponGroup=weaponGroup; + CheckKeysList(); + weaponGroupsList->Append(currentWeaponGroup); + weaponGroupsList->SetStringSelection(currentWeaponGroup); + } +} + +void WeaponGroupDialog::OnDelete(wxCommandEvent &event) +{ + if (currentWeaponGroup.Length()>0) + { + globalStatistics.configData.DeleteGroup(currentWeaponGroup); + globalStatistics.configData.CommitChanges(); + PopulateGroupsList(); + PopulateKeysList(); + } +} + +void WeaponGroupDialog::DisplayDialog() +{ + bool result; + + result=ShowModal(); +} diff --git a/WeaponGroupDialog.h b/WeaponGroupDialog.h new file mode 100644 index 0000000..5006005 --- /dev/null +++ b/WeaponGroupDialog.h @@ -0,0 +1,53 @@ +#ifndef __WEAPONGROUPDIALOG +#define __WEAPONGROUPDIALOG + +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" + +class WeaponGroupDialog : public wxDialog +{ + public: + WeaponGroupDialog(wxWindow *parent, + wxWindowID id, + wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~WeaponGroupDialog(); + void OnWeaponSelected(wxCommandEvent &event); + void OnWeaponGroupSelected(wxCommandEvent &event); + void OnSave(wxCommandEvent &event); + void OnQuit(wxCommandEvent &event); + void OnNew(wxCommandEvent &event); + void OnDelete(wxCommandEvent &event); + void CreateScreen(); + void PopulateGroupsList(); + void PopulateKeysList(); + void CheckKeysList(); + void DisplayDialog(); + void WriteCurrentWeaponGroup(); + + protected: + + private: + wxListBox *weaponGroupsList; + wxCheckListBox *weaponKeysList; + wxButton *newButton; + wxButton *deleteButton; + wxButton *saveButton; + wxButton *quitButton; + wxString currentWeaponGroup; + wxArrayString weaponKeys; + wxArrayString weaponNames; + wxBoxSizer *mainSizer; + wxBoxSizer *buttonSizer; + wxBoxSizer *displaySizer; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/WebFile.cpp b/WebFile.cpp new file mode 100644 index 0000000..0d817bb --- /dev/null +++ b/WebFile.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include "WebFile.h" + +WebFile::WebFile(wxString &hostnameIn,wxString &filenameIn) +{ + hostname = hostnameIn; + filename = filenameIn; +} + +WebFile::~WebFile() +{ +} + +wxInputStream * WebFile::GetInputStream() +{ + wxHTTP http; + wxInputStream *inputStream=NULL; + + if (http.Connect(hostname)) + { + inputStream=http.GetInputStream(filename); + } + + return (inputStream); +} + +bool WebFile::Get(wxString &localFile) +{ + bool retVal; + wxHTTP http; + wxInputStream *inputStream; + wxString msg; + + retVal=true; + if (http.Connect(hostname)) + { + inputStream=http.GetInputStream(filename); + if (inputStream!=NULL) + { + wxFileOutputStream outputStream(localFile); + outputStream.Write(*inputStream); + delete inputStream; + } + else + { + retVal=false; + msg.Printf("Can't get input stream for %s",filename.GetData()); + wxMessageBox(msg); + } + } + else + { + wxMessageBox("Can't connect"); + retVal=false; + } + if (!retVal) + { + } + return (retVal); +} diff --git a/WebFile.h b/WebFile.h new file mode 100644 index 0000000..b4a44cf --- /dev/null +++ b/WebFile.h @@ -0,0 +1,21 @@ +#ifndef _WEBFILE_H +#define _WEBFILE_H + +#include +#include +#include + +class WebFile +{ + public: + WebFile(wxString &hostname,wxString &filename); + virtual ~WebFile(); + + bool Get(wxString &localFile); + wxInputStream *GetInputStream(); + private: + wxString hostname; + wxString filename; +}; + +#endif diff --git a/WebServer.cpp b/WebServer.cpp new file mode 100644 index 0000000..b376ec7 --- /dev/null +++ b/WebServer.cpp @@ -0,0 +1,167 @@ +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "GlobalStatistics.h" +#include "WebServer.h" +#include "WindowIDs.h" +#include "WebServerRequestHandler.h" + +BEGIN_EVENT_TABLE(WebServer,wxEvtHandler) + + EVT_SOCKET(SOCKET_ID_WEB_SERVER,WebServer::OnServerEvent) + +END_EVENT_TABLE() + +WebServer::WebServer() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServer","Constructor"); + listenServer=NULL; + STATSGEN_DEBUG_FUNCTION_END +} + +WebServer::~WebServer() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServer","Destructor"); + StopServer(); + STATSGEN_DEBUG_FUNCTION_END +} + +wxString WebServer::ConfigKeyBase() +{ + wxString configKey="WebServer"; + + return (configKey); +} + +wxString WebServer::ConfigKeyEnabled() +{ + wxString configKey; + + configKey.Printf("/%s/Enabled",ConfigKeyBase().GetData()); + return (configKey); +} + +wxString WebServer::ConfigKeyPort() +{ + wxString configKey; + + configKey.Printf("/%s/Port",ConfigKeyBase().GetData()); + return (configKey); +} + +wxString WebServer::ConfigKeyAdminUser() +{ + wxString configKey; + + configKey.Printf("/%s/AdminUser",ConfigKeyBase().GetData()); + return (configKey); +} + +wxString WebServer::ConfigKeyAdminPassword() +{ + wxString configKey; + + configKey.Printf("/%s/AdminPassword",ConfigKeyBase().GetData()); + return (configKey); +} + +void WebServer::UpdateFromConfig() +{ + wxString configKey; + wxString configValue; + + STATSGEN_DEBUG_FUNCTION_START("WebServer","UpdateFromConfig") + configKey=ConfigKeyEnabled(); + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + enabled=(configValue.CmpNoCase("y")==0); + + configKey=ConfigKeyPort(); + globalStatistics.configData.ReadTextValue(configKey,&listenPort,"9000"); + + configKey=ConfigKeyAdminUser(); + globalStatistics.configData.ReadTextValue(configKey,&adminUser,""); + + configKey=ConfigKeyAdminPassword(); + globalStatistics.configData.ReadTextValue(configKey,&adminPassword,""); + + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServer::OnServerEvent(wxSocketEvent &event) +{ + wxSocketBase *client; + WebServerRequestHandler *requestHandler; + int clientFlags=wxSOCKET_WAITALL; + + STATSGEN_DEBUG_FUNCTION_START("WebServer","OnServerEvent") + if (listenServer!=NULL) + { + client=listenServer->Accept(true); + client->SetTimeout(0); + client->SetFlags(clientFlags); + + requestHandler=new WebServerRequestHandler(client); + } + STATSGEN_DEBUG_FUNCTION_END +} + +bool WebServer::IsListening() +{ + bool retVal=false; + + if (listenServer!=NULL) + { + if (listenServer->Ok()) + { + retVal=true; + } + } + + return (retVal); +} + +void WebServer::StartServer() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServer","StartServer") + int serverFlags=wxSOCKET_NOWAIT; + // First stop the server if one is already started + UpdateFromConfig(); + StopServer(); + if (enabled) + { + wxIPV4address addr; + addr.Service(atoi(listenPort.GetData())); + listenServer=new wxSocketServer(addr,serverFlags); + if (listenServer->Ok()) + { + listenServer->SetEventHandler(*this,SOCKET_ID_WEB_SERVER); + listenServer->SetNotify(wxSOCKET_CONNECTION_FLAG); + listenServer->Notify(true); + } + else + { + // Not listening??? + StopServer(); + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServer::StopServer() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServer","StopServer") + if (listenServer!=NULL) + { + listenServer->Destroy(); + delete listenServer; + listenServer=NULL; + } + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/WebServer.h b/WebServer.h new file mode 100644 index 0000000..9b74655 --- /dev/null +++ b/WebServer.h @@ -0,0 +1,46 @@ +#ifndef __WEBSERVER +#define __WEBSERVER + +// wxWindows includes +#include +#include +#include +#include +#include +#include + +// statsgen includes +#include "ErrorData.h" + +class WebServer : public wxEvtHandler +{ + public: + WebServer(); + virtual ~WebServer(); + wxString ConfigKeyBase(); + wxString ConfigKeyEnabled(); + wxString ConfigKeyPort(); + wxString ConfigKeyAdminUser(); + wxString ConfigKeyAdminPassword(); + + void UpdateFromConfig(); + void StopServer(); + void StartServer(); + + void OnServerEvent(wxSocketEvent &event); + + bool IsListening(); + + public: + wxString listenPort; + wxString adminUser; + wxString adminPassword; + bool enabled; + + private: + wxSocketServer *listenServer; + + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/WebServerRequestHandler.cpp b/WebServerRequestHandler.cpp new file mode 100644 index 0000000..ad0af44 --- /dev/null +++ b/WebServerRequestHandler.cpp @@ -0,0 +1,422 @@ +#include +#include +#include +#include +#include +#include +#include "WebServerRequestHandler.h" +#include "StaticFunctions.h" +#include "ErrorData.h" +#include "ContentTypes.h" +#include "GlobalStatistics.h" + + +WebServerRequestHandler::WebServerRequestHandler(wxSocketBase *clientIn) +{ + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","Constructor") + client=clientIn; + + Create(); + Run(); + STATSGEN_DEBUG_FUNCTION_END +} + +WebServerRequestHandler::~WebServerRequestHandler() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","Destructor") + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServerRequestHandler::WriteErrorResponse(int errorCode,char *response) +{ + wxString responseStr; + + responseStr.Printf("HTTP/1.1 %ld %s\r\nserver: statsgen\r\n" + "content-type: text/plain\r\n" + "content-length: %ld\r\n" + "\r\n" + "%s", + errorCode, + response, + strlen(response), + response); + WriteBufferToClient(responseStr.GetData(),responseStr.Length()); +} + +void WebServerRequestHandler::WriteBufferToClient( + const char *buffer, + long bufferSize) +{ + long bytesWritten; + long bytesRemaining; + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","WriteBufferToClient") + if (client==NULL) + { + return; + } + bytesWritten=0; + bytesRemaining=bufferSize; + while (bytesRemaining>0) + { + client->Write(buffer, bytesRemaining); + bytesWritten=client->LastCount(); + if (bytesWritten>=0) + { + buffer+=bytesWritten; + bytesRemaining-=bytesWritten; + } + else + { + break; + } + } + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServerRequestHandler::WriteStandardResponse( + int responseCode, + wxString &contentType, + const char *responseBuffer, + long bufferSize) +{ + wxString responseHeader; + + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","WriteStandardResponse") + responseHeader.Printf("HTTP/1.1 %d 0K\r\n" + "server: statsgen\r\n" + "content=type: %s\r\n" + "content-length: %ld\r\n" + "\r\n", + responseCode, + contentType.GetData(), + bufferSize); + WriteBufferToClient(responseHeader.GetData(),responseHeader.Length()); + WriteBufferToClient(responseBuffer,bufferSize); + STATSGEN_DEBUG_FUNCTION_END +} + +wxXmlDocument WebServerRequestHandler::ServerTypeListToXML() +{ + wxArrayString rootPropertyKeys; + wxArrayString rootPropertyValues; + wxString rootPropertyKey; + wxString rootPropertyValue; + wxArrayString keys; + wxArrayString values; + int index; + + rootPropertyKey="id"; + rootPropertyValue="servertypelist"; + rootPropertyKeys.Add(rootPropertyKey); + rootPropertyValues.Add(rootPropertyValue); + + for (index=0;indexAddProperty(rootPropertyKey,rootPropertyValue); + } + xmlResponse.SetRoot(root); + keyCount=keys.GetCount(); + for (keyIndex=0;keyIndexAddChild(keyNodeValue); + valueNode->AddChild(valueNodeValue); + + configItemNode->AddChild(keyNode); + keyNode->SetNext(valueNode); + + if (lastConfigItem==NULL) + { + root->AddChild(configItemNode); + } + else + { + lastConfigItem->SetNext(configItemNode); + } + lastConfigItem=configItemNode; + } + + return (xmlResponse); +} + +void WebServerRequestHandler::HandleXMLRequest(wxFileName &xmlRequest) +{ + wxString xmlFilename; + wxXmlDocument xmlResponse; + wxMemoryOutputStream xmlBufferStream; + long xmlSize; + char *xmlBuffer; + wxString ext="xml"; + + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","HandleXMLRequest") + xmlFilename=xmlRequest.GetName().Lower(); + if (xmlFilename.StartsWith(XML_REQUEST_CONFIG_GROUP)) + { + wxString configGroup=""; + + configGroup=xmlFilename.Mid(strlen(XML_REQUEST_CONFIG_GROUP)); + xmlResponse=ConfigGroupToXML(configGroup); + } + else + if (xmlFilename.StartsWith(XML_REQUEST_STAT_TYPE_LIST)) + { + xmlResponse=StatTypeListToXML(); + } + else + if (xmlFilename.StartsWith(XML_REQUEST_SERVER_TYPE_LIST)) + { + xmlResponse=ServerTypeListToXML(); + } + xmlResponse.Save(xmlFilename); + xmlResponse.Save(xmlBufferStream); + xmlSize=xmlBufferStream.GetSize(); + xmlBuffer=(char *)malloc(xmlSize); + if (xmlBuffer!=NULL) + { + wxString contentType; + xmlBufferStream.CopyTo(xmlBuffer,xmlSize); + + ContentTypes contentTypes; + contentType=contentTypes.GetContentType(ext); + WriteStandardResponse(200,contentType,xmlBuffer,xmlSize); + free(xmlBuffer); + } + + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServerRequestHandler::HandleURL(wxString &url) +{ + wxFileName urlFileName; + wxString msg; + wxString contentType; + wxString ext; + + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","HandleURL") + STATSGEN_DEBUG(DEBUG_ALWAYS,url) + url=url.AfterFirst('/'); + urlFileName=BaseDirectoryFileName(url.GetData()); + ext=urlFileName.GetExt().Lower(); + if (ext.CmpNoCase("xml")==0) + { + // xml response - this is data + HandleXMLRequest(urlFileName); + } + else + { + if (urlFileName.FileExists()) + { + ContentTypes contentTypes; + contentType=contentTypes.GetContentType(ext); + wxFile responseFile; + + if (responseFile.Open(urlFileName.GetFullPath(),wxFile::read)) + { + long fileSize=responseFile.Length(); + wxString responseHeader; + char *responseBuffer; + + responseBuffer=new char[fileSize]; + responseFile.Read(responseBuffer,fileSize); + WriteStandardResponse(200,contentType,responseBuffer,fileSize); + if (responseBuffer!=NULL) + { + delete responseBuffer; + } + } + else + { + // File exists but could not open + msg.Printf("url=[%s] Could Not Be Opened",url.GetData()); + WriteErrorResponse(404,(char *)msg.GetData()); + } + } + else + { + STATSGEN_DEBUG(DEBUG_ALWAYS,"NOT FOUND") + msg.Printf("url=[%s] Not Found",url.GetData()); + WriteErrorResponse(404,(char *)msg.GetData()); + } + } + if (client!=NULL) + { + client->Destroy(); + } + STATSGEN_DEBUG_FUNCTION_END +} + +void WebServerRequestHandler::HandleRequest(wxString &method,wxString &url) +{ + wxString msg; + url=url.Lower(); + HandleURL(url); +} + +void *WebServerRequestHandler::Entry() +{ + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","Entry") + while (client!=NULL && client->IsConnected()) + { + ReceiveDataFromClient(); + client->Close(); + } + STATSGEN_DEBUG_FUNCTION_END + return NULL; +} + +void WebServerRequestHandler::ReceiveDataFromClient() +{ + char receiveBuffer[5000]; + int receivedBytes; + wxString responseLine; + wxString method; + wxString url; + wxString version; + wxString msg; + + STATSGEN_DEBUG_FUNCTION_START("WebServerRequestHandler","ReceiveDataFromClient") + try + { + receiveBuffer[0]=0; + client->Read(receiveBuffer,sizeof(receiveBuffer)); + receivedBytes=client->LastCount(); + // Received a response + // decode the response details + responseLine=receiveBuffer; + responseLine=responseLine.BeforeFirst('\r'); + method=responseLine.BeforeFirst(' '); + responseLine=responseLine.AfterFirst(' '); + url=responseLine.BeforeFirst(' '); + version=responseLine.AfterFirst(' '); + if ((method.Length()==0) || + (url.Length()==0) || + (version.Length()==0) || + (!url.StartsWith("/"))) + { + + msg.Printf("Bad Request: Method=[%s], URL=[%s], Version=[%s]", + method.GetData(), + url.GetData(), + version.GetData()); + WriteErrorResponse(400,(char *)msg.GetData()); + return; + } + else + { + HandleRequest(method,url); + return; + } + } + catch (int e) + { + WriteErrorResponse(500,"Server Error"); + return; + // Server Error (500) + } + STATSGEN_DEBUG_FUNCTION_END +} + diff --git a/WebServerRequestHandler.h b/WebServerRequestHandler.h new file mode 100644 index 0000000..734fdc5 --- /dev/null +++ b/WebServerRequestHandler.h @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include + +#ifndef __WEBSERVERREQUESTHANDLER +#define __WEBSERVERREQUESTHANDLER + +#define XML_REQUEST_CONFIG_GROUP "configgroup" +#define XML_REQUEST_STAT_TYPE_LIST "stattypelist" +#define XML_REQUEST_SERVER_TYPE_LIST "servertypelist" + +class WebServerRequestHandler : public wxThread +{ + public: + WebServerRequestHandler(wxSocketBase *clientIn); + ~WebServerRequestHandler(); + + virtual void *Entry(); + + + private: + wxXmlDocument ConfigGroupToXML(wxString &groupID); + wxXmlDocument StatTypeListToXML(); + wxXmlDocument ServerTypeListToXML(); + wxXmlDocument KeyListToXML( + wxArrayString &rootPropertyKeys, + wxArrayString &rootPropertyValues, + wxArrayString &keys, + wxArrayString &values); + void WriteBufferToClient(const char *buffer,long bufferSize); + void WriteStandardResponse(int responseCode, + wxString &contentType, + const char *responseBuffer, + long bufferSize); + void HandleRequest(wxString &method,wxString &url); + void HandleURL(wxString &url); + void HandleXMLRequest(wxFileName &xmlRequest); + void WriteErrorResponse(int code,char *response); + void ReceiveDataFromClient(); + wxSocketBase *client; +}; + +#endif diff --git a/Website.cpp b/Website.cpp new file mode 100644 index 0000000..c3b03fa --- /dev/null +++ b/Website.cpp @@ -0,0 +1,248 @@ +// wx includes +#include +#include + +// Statsgen Includes +#include "Website.h" +#include "GlobalStatistics.h" +#include "RemoteMachine.h" +#include "Progress.h" + +void Website::LoadConfig() +{ + wxString configKey; + wxString configValue; + wxString configBaseKey; + + configGroup="Website"; + configBaseKey="/"+configGroup+"/"; + + configKey=configBaseKey+"FTPEnabled"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,"n"); + FTPEnabled=(configValue.CmpNoCase("y")==0); + + configKey=configBaseKey+"FTPRemoteDirectory"; + globalStatistics.configData.ReadTextValue(configKey,&configValue,""); + FTPRemoteDirectory=configValue; +} +Website::Website() +{ + LoadConfig(); +} + +Website::~Website() +{ +} + +bool Website::UploadZipContents(wxString &localFile) +{ + bool retVal; + wxString imagename; + long fileSize; + long totalSize; + wxString msg; + RemoteMachine remoteMachine(configGroup); + wxString directory; + wxString newDirectory; + + totalSize=0; + + if (FTPEnabled) + { + wxFileInputStream inputStream(localFile); + wxZipInputStream zipStream(inputStream); + wxZipEntry *zipEntry; + zipEntry=zipStream.GetNextEntry(); + while (zipEntry!=NULL) + { + fileSize=zipStream.GetLength(); + totalSize+=fileSize; + zipEntry=zipStream.GetNextEntry(); + } + } + + if (FTPEnabled) + { + wxFileInputStream inputStream(localFile); + wxZipInputStream zipStream(inputStream); + wxZipEntry *zipEntry; + wxString configGroup="WEBSITE"; + RemoteMachine website(configGroup); + + progress->Initiate(totalSize, + "kb", + 1024, + "kb", + 1024); + zipEntry=zipStream.GetNextEntry(); + while (zipEntry!=NULL) + { + directory=FTPRemoteDirectory; + progress->SetOffset(progress->CurrentValue()); + imagename=zipEntry->GetName(); + while (imagename.Contains('\\')) + { + newDirectory=imagename.BeforeFirst('\\'); + imagename=imagename.AfterFirst('\\'); + remoteMachine.MakeDir(directory,newDirectory); + directory+="/"; + directory+=newDirectory; + } + progress->SetStatus(imagename); + if (imagename.Length()>0) + { + remoteMachine.PutFile(directory, + imagename, + (wxInputStream *)&zipStream, + imagename, + SeverityError); + } + //wxMessageBox(imagename); + zipEntry=zipStream.GetNextEntry(); + } + progress->Finalise(); + } + + return (true); +} + +bool Website::TransferFiles(wxArrayString &filelist) +{ + wxString localFilename; + int fileCount; + int fileIndex; + bool allOK; + RemoteMachine remoteMachine(configGroup); + wxString msg; + long totalFileSize; + long fileSize; + + STATSGEN_DEBUG_FUNCTION_START("Website","TransferFiles") + if (FTPEnabled) + { + fileCount=filelist.GetCount(); + STATSGEN_DEBUG_CODE(msg.Printf("Transferring %d files to website",fileCount);) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + totalFileSize=0; + msg="Getting File Sizes"; + progress->SetStatus(msg); + for (fileIndex=0;fileIndexInitiate(totalFileSize, + "kb", + 1024, + "kb", + 1024); + for (fileIndex=0;fileIndexSetOffset(progress->CurrentValue()); + localFilename=filelist.Item(fileIndex); + wxFileName fname(localFilename); + wxString filenameonly; + filenameonly=fname.GetFullName(); + progress->SetStatus(filenameonly); + STATSGEN_DEBUG_CODE(msg.Printf("Transferring %d of %d [%s] to [%s]", + fileIndex+1, + fileCount, + localFilename.GetData(), + FTPRemoteDirectory.GetData());) + STATSGEN_DEBUG(DEBUG_ALWAYS,msg) + allOK=remoteMachine.PutFile(FTPRemoteDirectory,localFilename); + if (allOK) + { + STATSGEN_DEBUG(DEBUG_RARELY,"File Transferred OK") + } + else + { + msg.Printf("Failed to transfer %s to website",localFilename.GetData()); + progress->LogError(msg,SeverityError); + STATSGEN_DEBUG(DEBUG_ALWAYS,"File Transferred FAIL") + } + } + } + + STATSGEN_DEBUG_FUNCTION_END + return (true); +} + +bool Website::UploadZipTemplateContents(wxString &localFile,wxString &templateFilename) +{ + bool retVal; + wxString imagename; + long fileSize; + long totalSize; + wxString msg; + wxString directory; + wxString newDirectory; + wxString fullTemplateFilename; + + totalSize=0; + + { + wxFileInputStream inputStream(localFile); + wxZipInputStream zipStream(inputStream); + wxZipEntry *zipEntry; + zipEntry=zipStream.GetNextEntry(); + while (zipEntry!=NULL) + { + fileSize=zipStream.GetLength(); + totalSize+=fileSize; + zipEntry=zipStream.GetNextEntry(); + } + } + + { + wxFileInputStream inputStream(localFile); + wxZipInputStream zipStream(inputStream); + wxZipEntry *zipEntry; + + progress->Initiate(totalSize, + "kb", + 1024, + "kb", + 1024); + zipEntry=zipStream.GetNextEntry(); + while (zipEntry!=NULL) + { + wxString configKey; + wxString configValue; + + configKey="/Template/FullRun"; + globalStatistics.configData.ReadTextValue(configKey,&configValue); + wxFileName templateEntryFile(configValue); + + progress->SetOffset(progress->CurrentValue()); + imagename=zipEntry->GetName(); + progress->SetStatus(imagename); + if (imagename.Length()>0) + { + templateEntryFile.SetFullName(imagename); + wxFileOutputStream outputStream(templateEntryFile.GetFullPath()); + unsigned char buffer[1024]; + + while (!zipStream.Eof()) + { + zipStream.Read(buffer,sizeof(buffer)); + if (zipStream.LastRead()>0) + { + outputStream.Write(buffer,zipStream.LastRead()); + } + } + } + //wxMessageBox(imagename); + zipEntry=zipStream.GetNextEntry(); + templateEntryFile.SetFullName(templateFilename); + fullTemplateFilename=templateEntryFile.GetFullPath(); + globalStatistics.configData.WriteTextValue(configKey,fullTemplateFilename); + } + progress->Finalise(); + } + + return (true); +} + diff --git a/Website.h b/Website.h new file mode 100644 index 0000000..634cc1a --- /dev/null +++ b/Website.h @@ -0,0 +1,24 @@ +#ifndef __WEBSITE +#define __WEBSITE + +#include +#include + +// Statsgen Includes + +class Website +{ + public: + Website(); + ~Website(); + void LoadConfig(); + bool TransferFiles(wxArrayString &filelist); + bool UploadZipContents(wxString &zipfile); + bool UploadZipTemplateContents(wxString &zipfile,wxString &templateFilename); + private: + wxString configGroup; + wxString FTPRemoteDirectory; + bool FTPEnabled; +}; + +#endif diff --git a/WebsiteConfigGUI.cpp b/WebsiteConfigGUI.cpp new file mode 100644 index 0000000..1feb7bc --- /dev/null +++ b/WebsiteConfigGUI.cpp @@ -0,0 +1,167 @@ +// Statsgen Includes +#include "WebsiteConfigGUI.h" +#include "GlobalStatistics.h" + +BEGIN_EVENT_TABLE(WebsiteConfigGUI, wxDialog) + EVT_SIZE(WebsiteConfigGUI::OnResize) + EVT_BUTTON(WINDOW_ID_BUTTON_SAVE,WebsiteConfigGUI::OnSave) + EVT_BUTTON(WINDOW_ID_BUTTON_QUIT,WebsiteConfigGUI::OnQuit) +END_EVENT_TABLE() + +WebsiteConfigGUI::WebsiteConfigGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name): + wxDialog(parent, + id, + title, + pos, + size, + style, + name) + +{ +} + +void WebsiteConfigGUI::OnQuit(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +void WebsiteConfigGUI::OnSave(wxCommandEvent& event) +{ + EndModal(event.GetId()); +} + +WebsiteConfigGUI::~WebsiteConfigGUI() +{ +} + +void WebsiteConfigGUI::CreateDialog() +{ + wxString label="Website Configuration"; + wxString defaultValue=""; + wxString configKey; + wxSizeEvent event; + GroupedConfigItemsPanel *configPanel; + + wxPoint configItemsPosition=wxDefaultPosition; + wxSize configItemsSize=wxDefaultSize; + + + saveButton.Create(this, + WINDOW_ID_BUTTON_SAVE, + _T(WINDOW_ID_BUTTON_SAVE_TEXT), + wxDefaultPosition); + quitButton.Create(this, + WINDOW_ID_BUTTON_QUIT, + _T(WINDOW_ID_BUTTON_QUIT_TEXT), + wxDefaultPosition); + + configPanel=new GroupedConfigItemsPanel("FTP Connection Settings"); + configPanel->Create(this, + -1, + wxDefaultPosition, + wxDefaultSize); + + configKey="/website/IPAddress"; + configPanel->Add("Hostname",configKey,"",-1); + configKey="/website/FTPUsername"; + configPanel->Add("Username",configKey,"",-1); + configKey="/website/FTPPassword"; + configPanel->Add("Password",configKey,"",-1); + configKey="/website/FTPPort"; + configPanel->Add("Port",configKey,"21",5); + configKey="/website/FTPEnabled"; + configPanel->Add("Enabled",configKey,"n",1); + configKey="/website/FTPPassive"; + configPanel->Add("Passive",configKey,"y",1); + + configItems.Add((void *)configPanel); + + OnResize(event); +} + +void WebsiteConfigGUI::DisplayDialog() +{ + int dialogRetVal; + + // Called when we want to pop the dialog box + // into existance for the first time + + // First we want to create all the items in the dialog box + CreateDialog(); + + // Now we can resize every item in the dialog to fit nicely + + // Then we pop it into existance + dialogRetVal=ShowModal(); + + // Now we do what is necessary dependent on the return code + switch (dialogRetVal) + { + case WINDOW_ID_BUTTON_SAVE: + // We have been asked to save the changes + // just commit the config changes + globalStatistics.configData.CommitChanges(); + break; + case WINDOW_ID_BUTTON_QUIT: + default: + // We have been asked to quit without saving + // rollback the config changes + globalStatistics.configData.RollbackChanges(); + break; + } +} + +void WebsiteConfigGUI::OnResize(wxSizeEvent &event) +{ + wxString msg; + + int dialogWidth; + int dialogHeight; + int quitWidth; + int quitHeight; + int saveWidth; + int saveHeight; + wxSize itemSize; + wxPoint itemPosition; + int configPanelHeight; + int configPanelWidth; + GroupedConfigItemsPanel *configPanel; + + itemSize=GetSize(); + dialogWidth=itemSize.GetWidth(); + dialogHeight=itemSize.GetHeight(); + + // Quit and Save buttons are at the bottom of the screen + itemSize=quitButton.GetSize(); + quitWidth=itemSize.GetWidth(); + quitHeight=itemSize.GetHeight(); + + itemSize=saveButton.GetSize(); + saveWidth=itemSize.GetWidth(); + saveHeight=itemSize.GetHeight(); + + configPanelHeight=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + configPanelWidth=dialogWidth; + + // Config Panel + configPanel=(GroupedConfigItemsPanel *)configItems.Item(0); + configPanel->SetSize(0,0,configPanelWidth,configPanelHeight); + + // Save button + itemPosition.x=BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-saveHeight-DIALOG_BOTTOM_BORDER_SIZE; + saveButton.SetPosition(itemPosition); + + // Quit button + itemPosition.x=saveWidth+BUTTON_WIDTH_GAP+BUTTON_WIDTH_GAP; + itemPosition.y=dialogHeight-quitHeight-DIALOG_BOTTOM_BORDER_SIZE; + quitButton.SetPosition(itemPosition); + +} + diff --git a/WebsiteConfigGUI.h b/WebsiteConfigGUI.h new file mode 100644 index 0000000..0bdeccf --- /dev/null +++ b/WebsiteConfigGUI.h @@ -0,0 +1,41 @@ +#ifndef __WEBSITECONFIGGUI +#define __WEBSITECONFIGGUI + +#include +#include +#include + +// Statsgen Includes +#include "WindowIDs.h" +#include "GroupedConfigItemsPanel.h" + +class WebsiteConfigGUI : public wxDialog +{ + public: + WebsiteConfigGUI(wxWindow *parent, + wxWindowID id, + const wxString &title, + const wxPoint &pos, + const wxSize &size, + long style, + const wxString &name); + virtual ~WebsiteConfigGUI(); + + void OnQuit(wxCommandEvent& event); + void OnSave(wxCommandEvent& event); + void OnResize(wxSizeEvent& event); + + void DisplayDialog(); + + protected: + void CreateDialog(); + + private: + //GroupedConfigItemsPanel *configItems; + ArrayOfPointers configItems; + wxButton saveButton; + wxButton quitButton; + DECLARE_EVENT_TABLE() +}; + +#endif diff --git a/WeightList.cpp b/WeightList.cpp new file mode 100644 index 0000000..ecbc09c --- /dev/null +++ b/WeightList.cpp @@ -0,0 +1,134 @@ +// wxWindows includes +#include + +// Statsgen includes +#include "WeightListEntry.h" +#include "GlobalStatistics.h" + +WeightList::WeightList() +{ +} + +void WeightList::Initiate(const char *prefixIn) +{ + Clear(); + prefix=prefixIn; +} + +WeightList::~WeightList() +{ +} + +float WeightList::Weight(wxString &key,float defaultValue) +{ + WeightListEntry weightListEntry; + int weightListCount; + int weightListIndex; + float retVal=0.0; + bool found; + + weightListCount=weightList.GetCount(); + found=false; + for (weightListIndex=0; + weightListIndex +#include +#include + +// Statsgen Includes +#include "WeightListEntry.h" + +class WeightList +{ + public: + WeightList(); + void Initiate(const char *prefixIn); + ~WeightList(); + void Clear(); + + float Weight(wxString &key,float defaultValue); + void CreateDatabase(); + void WriteToDatabase(); + void ReadFromDatabase(); + void EmptyDatabase(); + + ArrayOfWeightListEntry weightList; + wxString prefix; +}; + + +#endif diff --git a/WeightListEntry.cpp b/WeightListEntry.cpp new file mode 100644 index 0000000..9c179e3 --- /dev/null +++ b/WeightListEntry.cpp @@ -0,0 +1,32 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "WeightListEntry.h" +#include "GlobalStatistics.h" + +WeightListEntry::WeightListEntry() +{ +} + +WeightListEntry::~WeightListEntry() +{ +} + +void WeightListEntry::UpdateWeighting(wxString &prefix) +{ + wxString configKey; + wxString configValue; + wxString defaultString; + + configKey="/"+prefix+"/"+key; + defaultString.Printf("%f",defaultValue); + globalStatistics.configData.ReadTextValue(configKey, + &configValue, + (char *)defaultString.GetData()); + + weight=atof(configValue.GetData()); +} + diff --git a/WeightListEntry.h b/WeightListEntry.h new file mode 100644 index 0000000..4412300 --- /dev/null +++ b/WeightListEntry.h @@ -0,0 +1,27 @@ +#ifndef __WEIGHTLISTENTRY +#define __WEIGHTLISTENTRY + +// wxWindows includes +#include +#include +#include +#include + +// Statsgen Includes + +class WeightListEntry; + +WX_DECLARE_OBJARRAY(WeightListEntry,ArrayOfWeightListEntry); +class WeightListEntry +{ + public: + WeightListEntry(); + ~WeightListEntry(); + void UpdateWeighting(wxString &prefix); + wxString key; + float weight; + float defaultValue; +}; + + +#endif diff --git a/WindowIDs.h b/WindowIDs.h new file mode 100644 index 0000000..f7c47e4 --- /dev/null +++ b/WindowIDs.h @@ -0,0 +1,140 @@ +#ifndef __WINDOWIDS +#define __WINDOWIDS + +// wxWindows includes +#include + +enum WindowIDs +{ + WINDOW_ID_MENU_ABOUT = wxID_ABOUT, + WINDOW_ID_MENU_QUIT = wxID_EXIT, + WINDOW_ID_MENU_SCORE_WEIGHTS = wxID_HIGHEST, + WINDOW_ID_MENU_SKILL_WEIGHTS, + WINDOW_ID_MENU_REAL_NAMES, + WINDOW_ID_MENU_ADVANCED, + WINDOW_ID_MENU_IMAGEPACKS, + WINDOW_ID_MENU_TEMPLATEPACKS, + WINDOW_ID_MENU_FULL_CONFIG, + WINDOW_ID_MENU_GO, + WINDOW_ID_MENU_RESET_RECOVERY, + WINDOW_ID_MENU_STORE_PROGRESS, + WINDOW_ID_MENU_EMPTY_DATABASE, + WINDOW_ID_MENU_IMAGES, + WINDOW_ID_MENU_WEBSITE, + WINDOW_ID_MENU_BAD_WORDS, + WINDOW_ID_MENU_WEB_SERVER, + WINDOW_ID_MENU_CUSTOM_MESSAGES, + WINDOW_ID_MENU_OUTPUT, + WINDOW_ID_MENU_EXTERNAL_DATABASE, + WINDOW_ID_MENU_WEAPON_GROUPS, + WINDOW_ID_MENU_TEMPLATE_CONFIG, + WINDOW_ID_MENU_SERVER, + WINDOW_ID_MENU_CLAN, + WINDOW_ID_MENU_ALIAS, + WINDOW_ID_MENU_DROPLIST, + WINDOW_ID_MENU_PLAYERDATAAVATAR, + WINDOW_ID_MENU_PLAYERDATAPICTURE, + WINDOW_ID_MENU_PLAYERDATAWEBSITE, + WINDOW_ID_MENU_PLAYERDATACLANROLE, + WINDOW_ID_MENU_PLAYERDATAXFIRE, + WINDOW_ID_MENU_PLAYERDATAREALNAME, + WINDOW_ID_MENU_PLAYERDATAMISC1, + WINDOW_ID_MENU_PLAYERDATAMISC2, + WINDOW_ID_MENU_AWARD, + WINDOW_ID_MENU_DEBUG, + WINDOW_ID_MENU_EXPORT_TEMPLATE, + WINDOW_ID_MENU_EXPORT_UPGRADE, + WINDOW_ID_MENU_EXPORT_BUILD_INI, + WINDOW_ID_MENU_PERFORM_UPGRADE, + WINDOW_ID_MENU_RCON_CONFIG, + WINDOW_ID_MENU_MESSAGE_FORMATS, + WINDOW_ID_MENU_LOG_SUBSTITUTE_GAMETYPE, + WINDOW_ID_MENU_LOG_SUBSTITUTE_MAP, + WINDOW_ID_MENU_LOG_SUBSTITUTE_CLASS, + WINDOW_ID_MENU_LOG_SUBSTITUTE_TEAM, + WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPON, + WINDOW_ID_MENU_LOG_SUBSTITUTE_AMMO, + WINDOW_ID_MENU_LOG_SUBSTITUTE_WEAPONAMMO, + WINDOW_ID_MENU_LOG_SUBSTITUTE_LOCATION, + WINDOW_ID_MENU_LOG_SUBSTITUTE_ACTION, + WINDOW_ID_MENU_THREAD, + WINDOW_ID_MENU_HELP, + WINDOW_ID_LISTBOX_CONFIGITEMS, + WINDOW_ID_TEXTCTRL_CONFIGVALUE, + WINDOW_ID_SELECTION_CONFIGVALUE, + WINDOW_ID_BOXED_DROPDOWN_FILTER1, + WINDOW_ID_BOXED_DROPDOWN_FILTER2, + WINDOW_ID_PLAYERCACHE, + WINDOW_ID_ALIASTREE, + WINDOW_ID_DROPLIST, + WINDOW_ID_TEXTLIST, + WINDOW_ID_WEAPONLIST, + WINDOW_ID_ACTIONLIST, + WINDOW_ID_LOCATIONLIST, + WINDOW_ID_MISCAWARDLIST, + WINDOW_ID_XPAWARDLIST, + WINDOW_ID_AWARDDEFINITIONPANEL, + WINDOW_ID_AWARDCHOICESPANEL, + WINDOW_ID_BUTTON_SAVE, + WINDOW_ID_BUTTON_AUTO, + WINDOW_ID_BUTTON_NEW, + WINDOW_ID_BUTTON_DELETE, + WINDOW_ID_BUTTON_QUIT, + WINDOW_ID_ERROR_BUTTON, + WINDOW_ID_CONFIG_BUTTON, + WINDOW_ID_CONFIG_FULL_PRIORITY, + WINDOW_ID_CONFIG_QUICK_PRIORITY, + AWARD_DEFINITION_DELETE_COMPONENT, + AWARD_CHOICES_ADD_POSITIVE, + AWARD_CHOICES_ADD_NEGATIVE, + AWARD_CHOICES_ADD_KILL_POSITIVE, + AWARD_CHOICES_ADD_KILL_NEGATIVE, + AWARD_CHOICES_ADD_DEATH_POSITIVE, + AWARD_CHOICES_ADD_DEATH_NEGATIVE, + AWARD_CHOICES_ADD_TK_POSITIVE, + AWARD_CHOICES_ADD_TK_NEGATIVE, + AWARD_CHOICES_ADD_KILL_AND_DEATH, + WINDOW_ID_PROGRESS_PANEL_GENERAL, + WINDOW_ID_PROGRESS_PANEL_CREATE_DATABASE, + WINDOW_ID_PROGRESS_PANEL_APPLY_ALIASES, + WINDOW_ID_PROGRESS_PANEL_DOWNLOAD_LOGS, + WINDOW_ID_PROGRESS_PANEL_DATABASE_READ_STATIC, + WINDOW_ID_PROGRESS_PANEL_EMPTY_DATABASE, + WINDOW_ID_PROGRESS_PANEL_PROCESS_LOGS, + WINDOW_ID_PROGRESS_PANEL_DATABASE_LOCATE_EXISTING_PLAYERS, + WINDOW_ID_PROGRESS_PANEL_DROPPING_PLAYERS, + WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES1, + WINDOW_ID_PROGRESS_PANEL_CALCULATING_SCORES2, + WINDOW_ID_PROGRESS_PANEL_WRITE_DATABASE, + WINDOW_ID_PROGRESS_PANEL_READ_TEMPLATE, + WINDOW_ID_PROGRESS_PANEL_PROCESS_TEMPLATE, + WINDOW_ID_PROGRESS_PANEL_TRANSFER_DATABASE, + WINDOW_ID_PROGRESS_PANEL_WEBSITE, + WINDOW_ID_PROGRESS_PANEL_MAX, + WINDOW_ID_PROGRESS_PANEL_DYNAMIC, + EVENT_ID_PROGRESS_STATUS_TEXT, + EVENT_ID_PROGRESS_BUTTON, + SOCKET_ID_WEB_SERVER, + WINDOW_ID_WIZARD, + POPUP_CANCEL +}; + +#define WINDOW_ID_BUTTON_SAVE_TEXT "&Save" +#define WINDOW_ID_BUTTON_QUIT_TEXT "&Quit" +#define WINDOW_ID_BUTTON_NEW_TEXT "&New" +#define WINDOW_ID_BUTTON_DELETE_TEXT "&Delete" +#define WINDOW_ID_BUTTON_AUTO_TEXT "&Auto" + +#define BUTTON_WIDTH_GAP 5 +#define BUTTON_HEIGHT_GAP 5 +#define DIALOG_BOTTOM_BORDER_SIZE 30 + +#define STATIC_BOX_TOP_GAP 20 +#define STATIC_BOX_BOTTOM_GAP 10 +#define STATIC_BOX_LEFT_GAP 10 +#define STATIC_BOX_RIGHT_GAP 10 + +#define FONT_CHAR_WIDTH 8 +#define FONT_TEXT_CTRL_GAP 8 + +#endif diff --git a/XPPoints.cpp b/XPPoints.cpp new file mode 100644 index 0000000..2e7eb6f --- /dev/null +++ b/XPPoints.cpp @@ -0,0 +1,98 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "XPPoints.h" +#include "GlobalStatistics.h" + +XPPoints::XPPoints() +{ +} + +XPPoints::~XPPoints() +{ +} + +wxString XPPoints::SQLTableName() +{ + wxString tableName="xppoints"; + + return (tableName); +} + +wxString XPPoints::SQLCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "roundindex integer," + "playerindex integer," + "pointsindex integer," + "points float" + ")", + SQLTableName().GetData()); + + return SQL; +} + +bool XPPoints::WriteToDatabase(int roundIndex) +{ + wxString SQL; + bool retVal=true; + Player player; + + player=globalStatistics.playerList.Item(playerIndex); + + SQL.Printf("Insert into %s" + "(roundindex,playerindex,pointsindex,points)" + "values('%d','%d','%d','%f')", + SQLTableName().GetData(), + roundIndex, + player.actualPlayerIndex, + pointsIndex, + points); + + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} +wxString XPPoints::SQLTotalTableName() +{ + wxString tableName="xptotalpoints"; + + return (tableName); +} + +wxString XPPoints::SQLTotalCreateTable() +{ + wxString SQL; + + SQL.Printf("create table %s" + "(" + "playerindex integer," + "pointsindex integer," + "points float" + ")", + SQLTotalTableName().GetData()); + + return SQL; +} + +bool XPPoints::WriteTotalToDatabase() +{ + wxString SQL; + bool retVal=true; + + SQL.Printf("Insert into %s" + "(playerindex,pointsindex,points)" + "values('%d','%d','%f')", + SQLTotalTableName().GetData(), + playerIndex, + pointsIndex, + points); + + globalStatistics.statsgenDatabase.SimpleExecute(SQL); + return retVal; +} diff --git a/XPPoints.h b/XPPoints.h new file mode 100644 index 0000000..41d4d32 --- /dev/null +++ b/XPPoints.h @@ -0,0 +1,35 @@ +#ifndef __XPPOINTS +#define __XPPOINTS + +// wxWindows includes +#include +#include +#include + +// Statsgen Includes + +class XPPoints; + +WX_DECLARE_OBJARRAY(XPPoints,ArrayOfXPPoints); +class XPPoints +{ + public: + XPPoints(); + virtual ~XPPoints(); + static wxString SQLCreateTable(); + static wxString SQLTableName(); + static wxString SQLTotalCreateTable(); + static wxString SQLTotalTableName(); + bool WriteToDatabase(int roundIndex); + bool WriteTotalToDatabase(); + + public: + int playerIndex; + int pointsIndex; + float points; + + +}; + + +#endif diff --git a/XPTotals.cpp b/XPTotals.cpp new file mode 100644 index 0000000..5ab4a9a --- /dev/null +++ b/XPTotals.cpp @@ -0,0 +1,64 @@ +// wxWindows includes +#include +#include +#include + +// Statsgen includes +#include "XPTotals.h" +#include "XPPoints.h" +#include "GlobalStatistics.h" + +XPTotals::XPTotals() +{ +} + +XPTotals::~XPTotals() +{ +} + +void XPTotals::Add(XPPoints &xp) +{ + int xpCount; + int xpIndex; + XPPoints xpFound; + XPPoints newXP; + + newXP=xp; + xpCount=xpPoints.GetCount(); + for (xpIndex=0;xpIndex +#include +#include + +#include "XPPoints.h" +// Statsgen Includes + +class XPTotals +{ + public: + XPTotals(); + virtual ~XPTotals(); + void Add(XPPoints &points); + bool WriteToDatabase(); + void Clear(); + public: + ArrayOfXPPoints xpPoints; + + +}; + + +#endif diff --git a/bitmaps.rc b/bitmaps.rc new file mode 100644 index 0000000..ec123e6 --- /dev/null +++ b/bitmaps.rc @@ -0,0 +1,2 @@ +CLOCK_ICON ICON "clock.ico" + diff --git a/clock.ico b/clock.ico new file mode 100644 index 0000000..ece61a4 Binary files /dev/null and b/clock.ico differ diff --git a/help.zip b/help.zip new file mode 100644 index 0000000..4518a9c Binary files /dev/null and b/help.zip differ diff --git a/libmySQL.dll b/libmySQL.dll new file mode 100644 index 0000000..5eeefa5 Binary files /dev/null and b/libmySQL.dll differ diff --git a/statsgen2.ico b/statsgen2.ico new file mode 100644 index 0000000..a6d4e70 Binary files /dev/null and b/statsgen2.ico differ diff --git a/statsgen2.ini b/statsgen2.ini new file mode 100644 index 0000000..624d618 --- /dev/null +++ b/statsgen2.ini @@ -0,0 +1,7882 @@ +[General] +BuildVersion=12 +DatabaseVersion=2 +TemplateVersion=4 +AllowNegativeSkill=n +FirstTimeRun=y +[Colours] +0=000000 +1=FF0000 +2=00FF00 +3=FFFF00 +4=0000FF +5=00FFFF +6=FF00FF +7=FFFFFF +8=008000 +9=808080 +[DEATHMATCH] +LISTCOUNT=6 +LISTITEM001=COD1_dm +LISTITEM002=COD2_dm +LISTITEM003=MOHAA_dm +LISTITEM004=MOHAA_Free-For-All +LISTITEM005=COD4_dm +LISTITEM006=cod5_dm +[TEAMSWAP] +LISTCOUNT=4 +LISTITEM001=COD1_MOD_SUICIDE +LISTITEM002=COD2_MOD_SUICIDE +LISTITEM003=COD4_MOD_SUICIDE +LISTITEM004=cod5_MOD_SUICIDE +[LINEIDMOHAA] +LISTCOUNT=63 +LISTITEM001=R,Server: $$GAMETYPE$$/$$MAP$$ +LISTITEM002=R,Cvar_Set2: g_gametypestring $$GAMETYPE$$ +LISTITEM003=R,Cvar_Set2: mapname .*/$$MAP$$ +LISTITEM004=-,^SV.* +LISTITEM005=-,^Rcon.* +LISTITEM006=-,^Cvar_Set2:.* +LISTITEM007=-,^set.* +LISTITEM008=-,^serverinfo.* +LISTITEM009=-,^status.* +LISTITEM010=-,^Going.* +LISTITEM011=-,^Version.* +LISTITEM012=-,^Client .* +LISTITEM013=-,^FST_.* +LISTITEM014=J,^clientCommand: $$PLAYERNAME$$ : (.+) : join_team $$PLAYERTEAM$$ +LISTITEM015=S,^CHAT: (team) $$PLAYERNAME$$: $$SPEECH$$ +LISTITEM016=S,^CHAT: (dead) $$PLAYERNAME$$: $$SPEECH$$ +LISTITEM017=S,^CHAT: $$PLAYERNAME$$: $$SPEECH$$ +LISTITEM018=S,^clientCommand: $$PLAYERNAME$$ : (.+) : dmmessage (.+) $$SPEECH$$ +LISTITEM019=A,$$PLAYERNAME$$ MEF MELT .*$$ACTION=FreezeTagMelt$$ +LISTITEM020=A,$$PLAYERNAME$$ MEF CAPTURE .*$$ACTION=FreezeTagCapture$$ +LISTITEM021=A,$$PLAYERNAME$$ MEF SAVE .*$$ACTION=FreezeTagSave$$ +LISTITEM022=A,$$PLAYERNAME$$ MEF POST .*$$ACTION=FreezeTagPost$$ +LISTITEM023=A,$$PLAYERNAME$$ MEF PICKUP .*$$ACTION=FreezeTagPickup$$ +LISTITEM024=A,$$PLAYERNAME$$ MEF RETURN .*$$ACTION=FreezeTagReturn$$ +LISTITEM025=A,$$PLAYERNAME$$ MEF DROP .*$$ACTION=FreezeTagDrop$$ +LISTITEM026=A,$$PLAYERNAME$$ MEF PLANT .*$$ACTION=FreezeTagPlant$$ +LISTITEM027=A,$$PLAYERNAME$$ MEF DEFUSE .*$$ACTION=FreezeTagDefuse$$ +LISTITEM028=A,$$PLAYERNAME$$ MEF $$ACTION$$ .* +LISTITEM029=K,$$TARGETNAME$$ was clubbed by $$PLAYERNAME$$$$PLAYERWEAPON=clubbed$$ +LISTITEM030=K,$$TARGETNAME$$ was bashed by $$PLAYERNAME$$$$PLAYERWEAPON=clubbed$$ +LISTITEM031=K,$$TARGETNAME$$ was gunned down by $$PLAYERNAME$$ HEADSHOT$$PLAYERWEAPON=pistol$$ +LISTITEM032=K,$$TARGETNAME$$ was gunned down by $$PLAYERNAME$$ in $$TARGETLOCATION$$$$PLAYERWEAPON=pistol$$ +LISTITEM033=K,$$TARGETNAME$$ was gunned down by $$PLAYERNAME$$$$PLAYERWEAPON=pistol$$ +LISTITEM034=K,$$TARGETNAME$$ was sniped by $$PLAYERNAME$$ HEADSHOT$$PLAYERWEAPON=sniper$$ +LISTITEM035=K,$$TARGETNAME$$ was sniped by $$PLAYERNAME$$ in $$TARGETLOCATION$$$$PLAYERWEAPON=sniper$$ +LISTITEM036=K,$$TARGETNAME$$ was sniped by $$PLAYERNAME$$$$PLAYERWEAPON=sniper$$ +LISTITEM037=K,$$TARGETNAME$$ was perforated by $$PLAYERNAME$$'s SMG HEADSHOT$$PLAYERWEAPON=smg$$ +LISTITEM038=K,$$TARGETNAME$$ was perforated by $$PLAYERNAME$$'s SMG in $$TARGETLOCATION$$$$PLAYERWEAPON=smg$$ +LISTITEM039=K,$$TARGETNAME$$ was perforated by $$PLAYERNAME$$'s SMG$$PLAYERWEAPON=smg$$ +LISTITEM040=K,$$TARGETNAME$$ was machine-gunned by $$PLAYERNAME$$ HEADSHOT$$PLAYERWEAPON=mg$$ +LISTITEM041=K,$$TARGETNAME$$ was machine-gunned by $$PLAYERNAME$$ in $$TARGETLOCATION$$$$PLAYERWEAPON=mg$$ +LISTITEM042=K,$$TARGETNAME$$ was machine-gunned by $$PLAYERNAME$$$$PLAYERWEAPON=mg$$ +LISTITEM043=K,$$TARGETNAME$$ took $$PLAYERNAME$$'s rocket in the face$$PLAYERWEAPON=rocket$$ +LISTITEM044=K,$$TARGETNAME$$ took $$PLAYERNAME$$'s rocket right in the kisser$$PLAYERWEAPON=rocket$$ +LISTITEM045=K,$$TARGETNAME$$ was blown away by $$PLAYERNAME$$$$PLAYERWEAPON=rocket$$ +LISTITEM046=K,$$TARGETNAME$$ blew himself up$$PLAYERWEAPON=rocket$$ +LISTITEM047=K,$$TARGETNAME$$ was hunted down by $$PLAYERNAME$$$$PLAYERWEAPON=shotgun$$ +LISTITEM048=K,$$TARGETNAME$$ was pumped full of buckshot by $$PLAYERNAME$$$$PLAYERWEAPON=shotgun$$ +LISTITEM049=K,$$TARGETNAME$$ was rifled by $$PLAYERNAME$$ HEADSHOT$$PLAYERWEAPON=rifle$$ +LISTITEM050=K,$$TARGETNAME$$ was rifled by $$PLAYERNAME$$ in $$TARGETLOCATION$$$$PLAYERWEAPON=rifle$$ +LISTITEM051=K,$$TARGETNAME$$ was rifled by $$PLAYERNAME$$$$PLAYERWEAPON=rifle$$ +LISTITEM052=K,$$TARGETNAME$$ was shot by $$PLAYERNAME$$$$PLAYERWEAPON=rifle$$ +LISTITEM053=K,$$TARGETNAME$$ is picking $$PLAYERNAME$$'s shrapnel out of his teeth$$PLAYERWEAPON=grenade$$ +LISTITEM054=K,$$TARGETNAME$$ tripped on $$PLAYERNAME$$'s grenade$$PLAYERWEAPON=grenade$$ +LISTITEM055=K,$$TARGETNAME$$ tripped on his own grenade$$PLAYERWEAPON=grenade$$ +LISTITEM056=K,$$TARGETNAME$$ played catch with himself$$PLAYERWEAPON=grenade$$ +LISTITEM057=K,$$TARGETNAME$$ cratered$$WORLD$$$$PLAYERWEAPON=cratered$$ +LISTITEM058=K,$$TARGETNAME$$ took himself out of commision$$PLAYERWEAPON=suicide$$ +LISTITEM059=K,$$TARGETNAME$$ blew up$$PLAYERWEAPON=mine$$ +LISTITEM060=K,$$TARGETNAME$$ stepped on $$PLAYERNAMES$$'s landmine$$PLAYERWEAPON=mine$$ +LISTITEM061=K,$$TARGETNAME$$ died$$PLAYERWEAPON=explode$$ +LISTITEM062=K,$$TARGETNAME$$ was $$PLAYERWEAPON$$ by $$PLAYERNAME$$ in $$TARGETLOCATION$$ +LISTITEM063=K,$$TARGETNAME$$ was $$PLAYERWEAPON$$ by $$PLAYERNAME$$ +[LINEIDWOLFENSTEIN] +LISTCOUNT=10 +LISTITEM001=A,^TNT: $$PLAYERROUNDID$$: $$PLAYER$$ destroyed an objective$$$ACTION=TNT$$ +LISTITEM002=A,^Dynamite_Diffuse: $$PLAYERROUNDID$$$$ACTION=Dynamite_Defuse$$ +LISTITEM003=A,^Revive: $$PLAYERROUNDID$$ [0-9]+: $$PLAYER$$ revived .+$$$ACTION=Medic_Revive$$ +LISTITEM004=A,^Medic_Revive: $$PLAYERROUNDID$$ [0-9]+$$$ACTION=Medic_Revive$$ +LISTITEM005=A,^REPAIR: $$PLAYERROUNDID$$: $$PLAYER$$ repaired an .+$$$ACTION=Repair$$ +LISTITEM006=A,^Unfreeze: $$PLAYERROUNDID$$: [0-9]+: $$PLAYER$$ unfroze .+$$$ACTION=Unfreeze$$ +LISTITEM007=A,^Dynamite_Plant: $$PLAYERROUNDID$$$$ACTION=Dynamite_Plant$$ +LISTITEM008=K,^Kill: [0-9]+ [0-9]+ [0-9]+: $$PLAYERNAME$$ killed $$TARGETNAME$$ by $$PLAYERWEAPON$$ +LISTITEM009=S,^say: $$PLAYERNAME$$: $$SPEECH$$ +LISTITEM010=S,^sayteam: $$PLAYERNAME$$: $$SPEECH$$ +[AutoAliasBlockedGUIDS] +LISTCOUNT=4 +LISTITEM001=COD2_0 +LISTITEM002=MOHAA_ +LISTITEM003=WOLFENSTEIN_ +LISTITEM004=QUAKEWARS_0 +[ScoreWeights] +action_COD1_bas_attacked=0.1 +action_COD1_bas_breached=0.2 +action_COD1_bas_defend=0.1 +action_COD1_bas_defused=1.0 +action_COD1_bas_destroyed=2.0 +action_COD1_bas_planted=1.0 +action_COD1_bel_alive_tick=0.1 +action_COD1_bomb_defuse=1.0 +action_COD1_bomb_plant=1.0 +action_COD1_cnq_objective=1.0 +action_COD1_ctf_assist=1.0 +action_COD1_ctf_captured=1.0 +action_COD1_ctf_defended=1.0 +action_COD1_ctf_pickup=1.0 +action_COD1_ctf_returned=1.0 +action_COD1_ctf_score=1.0 +action_COD1_ctf_stole=1.0 +action_COD1_ctf_take=1.0 +action_COD1_dom_captured=1.0 +action_COD1_re_capture=1.0 +action_COD1_re_pickup=1.0 +action_COD2_bomb_defuse=1.0 +action_COD2_bomb_plant=1.0 +action_COD2_ctf_assist=0.2 +action_COD2_ctf_captured=1.0 +action_COD2_ctf_defended=0.5 +action_COD2_ctf_pickup=0.5 +action_COD2_ctf_returned=2.0 +action_COD2_ctf_take=0.0 +action_COD2_Exploit_abuser_was_suicided_by_server=-3.0 +action_COD2_heal=0.2 +action_COD2_hq_capture=0.5 +action_COD2_hq_defend=0.1 +action_COD2_hq_destroy=1.0 +action_COD2_htf_scored=1.000000 +action_COD2_htf_stole=1.000000 +action_COD2_sd_defend=1.000000 +action_COD4_bomb_defused=1.000000 +action_COD4_bomb_planted=1.000000 +action_COD4_kill_assist=0.1 +action_cod5_bd=1.0 +action_cod5_bp=1.5 +action_cod5_fc=1.0 +action_cod5_fr=0.2 +action_cod5_ft=0.5 +action_cod5_rc=0.1 +action_cod5_rd=0.1 +action_MOHAA_FreezeTagCapture=1.0 +action_MOHAA_FreezeTagDrop=-0.2 +action_MOHAA_FreezeTagMelt=0.0 +action_MOHAA_FreezeTagPickup=0.2 +action_MOHAA_FreezeTagPost=1.0 +action_MOHAA_FreezeTagReturn=1.0 +action_MOHAA_FreezeTagSave=1.0 +action_WOLFENSTEIN_Dynamite_Defuse=1.0 +action_WOLFENSTEIN_Dynamite_Plant=1.0 +Death=-1.0 +gametype_COD1_dm=1.000000 +gametype_COD1_re=1.000000 +gametype_COD1_sd=1.000000 +gametype_COD1_tdm=1.000000 +gametype_COD2_ctf=1.000000 +gametype_COD2_dm=1.000000 +gametype_COD2_esd=1.000000 +gametype_COD2_hq=1.000000 +gametype_COD2_htf=1.000000 +gametype_COD2_sd=1.000000 +gametype_COD2_tdm=1.000000 +gametype_COD4_dm=1.000000 +gametype_COD4_dom=1.000000 +gametype_COD4_koth=1.000000 +gametype_COD4_sab=1.000000 +gametype_COD4_sd=1.000000 +gametype_COD4_war=1.000000 +gametype_COD5_ctf=0.2 +gametype_COD5_dm=0.1 +gametype_COD5_dom=0.2 +gametype_COD5_koth=0.5 +gametype_COD5_sab=0.2 +gametype_COD5_sd=1.0 +gametype_COD5_sur=1.0 +gametype_COD5_tdm=0.2 +gametype_COD5_twar=0.2 +Kill=1.0 +Suicide=-3.0 +TeamKill=-2.0 +TeamLoss=-0.5 +TeamSwap=0.0 +TeamWin=0.5 +xp_QUAKEWARS_battlesense=0.000000 +xp_QUAKEWARS_covertops=0.000000 +xp_QUAKEWARS_engineer=0.000000 +xp_QUAKEWARS_fieldops=0.000000 +xp_QUAKEWARS_medic=0.000000 +xp_QUAKEWARS_soldier=0.000000 +xp_QUAKEWARS_vehicle=0.000000 +xp_QUAKEWARS_weapon_handling=0.000000 +[RealNames] +action_COD1_bas_attacked=Call Of Duty 1: BAS - Base Attacked +action_COD1_bas_breached=Call Of Duty 1: BAS - Base Breached +action_COD1_bas_defend=Call Of Duty 1: BAS - Base Defended +action_COD1_bas_defused=Call Of Duty 1: BAS - Base Bomb Defused +action_COD1_bas_destroyed=Call Of Duty 1: BAS - Base Destroyed +action_COD1_bas_planted=Call Of Duty 1: BAS - Base Bomb Planted +action_COD1_bel_alive_tick=Call Of Duty 1: Behind Enemy Lines - Stay Alive +action_COD1_bomb_defuse=Call Of Duty 1: Bomb Defuse +action_COD1_bomb_plant=Call Of Duty 1: Bomb Plant +action_COD1_cnq_objective=Call Of Duty 1: Conquest TDM Objective +action_COD1_ctf_assist=Call Of Duty 1: CTF Flag Capture Assist +action_COD1_ctf_captured=Call Of Duty 1: CTF Flag Captured +action_COD1_ctf_defended=Call Of Duty 1: CTF Flag Defended +action_COD1_ctf_pickup=Call Of Duty 1: CTF Flag Pickup +action_COD1_ctf_returned=Call Of Duty 1: CTF Flag Returned +action_COD1_ctf_score=Call Of Duty 1: CTF Flag Score +action_COD1_ctf_stole=Call Of Duty 1: CTF Flag Stolen +action_COD1_ctf_take=Call Of Duty 1: CTF Flag Taken +action_COD1_dom_captured=Call Of Duty 1: Domination Capture +action_COD1_re_capture=Call Of Duty 1: Retrieval Capture +action_COD1_re_pickup=Call Of Duty 1: Retrieval Pickup +action_COD2_bas_attacked=Call Of Duty 2: Base Attacked +action_COD2_bas_breached=Call Of Duty 2: Base Breached +action_COD2_bas_defend=Call Of Duty 2: Base Defended +action_COD2_bas_defused=Call Of Duty 2: Base Bomb Defused +action_COD2_bas_destroyed=Call Of Duty 2: Base Destroyed +action_COD2_bas_planted=Call Of Duty 2: Base Bomb Planted +action_COD2_bel_alive_tick=Call Of Duty 2: Alive Behind Enemy Lines +action_COD2_bomb_defuse=Call Of Duty 2: Bomb Defuse +action_COD2_bomb_plant=Call Of Duty 2: Bomb Plant +action_COD2_ctf_assist=Call Of Duty 2: CTF Assist +action_COD2_ctf_captured=Call Of Duty 2: CTF Captured +action_COD2_ctf_defended=Call Of Duty 2: CTF Defend +action_COD2_ctf_pickup=Call Of Duty 2: CTF Pickup +action_COD2_ctf_returned=Call Of Duty 2: CTF Returned +action_COD2_ctf_take=Call Of Duty 2: CTF Taken +action_COD2_Exploit abuser was suicided by server=Call Of Duty 2: Exploit Abuser +action_COD2_Exploit_abuser_was_suicided_by_server=Call Of Duty 2: Exploit Abuser +action_COD2_heal=Call Of Duty 2: Heal +action_COD2_hq_capture=Call Of Duty 2: HQ Capture +action_COD2_hq_defend=Call Of Duty 2: HQ Defend +action_COD2_hq_destroy=Call Of Duty 2: HQ Destroyed +action_COD2_htf_scored=Call Of Duty 2: HTF Score +action_COD2_htf_stole=Call Of Duty 2: HTF Stolen +action_COD2_sd_defend=Call Of Duty 2: S&D Defend +action_COD4_bomb_defused=Call Of Duty 4: Bomb Defused +action_COD4_bomb_planted=Call Of Duty 4: Bomb Planted +action_COD4_kill_assist=Call Of Duty 4: Kill Assist +action_cod5_bd=Call Of Duty 5: Bomb Defuse +action_cod5_bp=Call Of Duty 5: Bomb Planted +action_cod5_fc=Call Of Duty 5: Flag Captured +action_cod5_fr=Call Of Duty 5: Flag Returned +action_cod5_ft=Call Of Duty 5: Flag Taken +action_cod5_rc=Call Of Duty 5: Region Captured +action_cod5_rd=Call Of Duty 5: Region Defended +action_MOHAA_FreezeTagCapture=MOHAA: Freeze Tag Capture +action_MOHAA_FreezeTagDrop=MOHAA: Freeze Tag Drop +action_MOHAA_FreezeTagMelt=MOHAA: Freeze Tag Melt +action_MOHAA_FreezeTagPickup=MOHAA: Freeze Tag Pickup +action_MOHAA_FreezeTagPost=MOHAA: Freeze Tag Post +action_MOHAA_FreezeTagReturn=MOHAA: Freeze Tag Return +action_MOHAA_FreezeTagSave=MOHAA: Freeze Tag Save +action_WOLFENSTEIN_Dynamite_Defuse=Wolfenstein ET: Dynamite Defuse +action_WOLFENSTEIN_Dynamite_Plant=Wolfenstein ET: Dynamite Plant +ammo_COD1_BASH=COD1_BASH +ammo_COD1_binoculars_mp=COD1_binoculars_mp +ammo_COD1_MOD_ARTILLERY=COD1_MOD_ARTILLERY +ammo_COD1_MOD_ARTILLERY_SPLASH=COD1_MOD_ARTILLERY_SPLASH +ammo_COD1_MOD_CRUSH_JEEP=Call Of Duty 1: MOD_CRUSH_JEEP +ammo_COD1_MOD_CRUSH_TANK=Call Of Duty 1: MOD_CRUSH_TANK +ammo_COD1_MOD_EXPLOSIVE=Call Of Duty 1: MOD_EXPLOSIVE +ammo_COD1_MOD_FALLING=Call Of Duty 1: MOD_FALLING +ammo_COD1_MOD_FLAME=Call Of Duty 1: MOD_FLAME +ammo_COD1_MOD_GRENADE=COD1_MOD_GRENADE +ammo_COD1_MOD_GRENADE_SPLASH=Call Of Duty 1: MOD_GRENADE_SPLASH +ammo_COD1_MOD_HEAD_SHOT=Call Of Duty 1: MOD_HEAD_SHOT +ammo_COD1_MOD_MELEE=Call Of Duty 1: MOD_MELEE +ammo_COD1_MOD_MELEE_BINOCULARS=Call Of Duty 1: MOD_MELEE_BINOCULARS +ammo_COD1_MOD_PISTOL_BULLET=Call Of Duty 1: MOD_PISTOL_BULLET +ammo_COD1_MOD_PROJECTILE=Call Of Duty 1: MOD_PROJECTILE +ammo_COD1_MOD_PROJECTILE_SPLASH=Call Of Duty 1: MOD_PROJECTILE_SPLASH +ammo_COD1_MOD_RIFLE_BULLET=Call Of Duty 1: MOD_RIFLE_BULLET +ammo_COD1_MOD_SUICIDE=Call Of Duty 1: MOD_SUICIDE +ammo_COD1_MOD_TRIGGER_HURT=Call Of Duty 1: MOD_TRIGGER_HURT +ammo_COD1_MOD_WATER=Call Of Duty 1: MOD_WATER +ammo_COD2_BASH=COD2_BASH +ammo_COD2_MOD_EXPLOSIVE=Call Of Duty 2: MOD_EXPLOSIVE +ammo_COD2_MOD_FALLING=Call Of Duty 2: MOD_FALLING +ammo_COD2_MOD_GRENADE=COD2_MOD_GRENADE +ammo_COD2_MOD_GRENADE_SPLASH=Call Of Duty 2: MOD_GRENADE_SPLASH +ammo_COD2_MOD_HEAD_SHOT=Call Of Duty 2: MOD_HEAD_SHOT +ammo_COD2_MOD_MELEE=Call Of Duty 2: MOD_MELEE +ammo_COD2_MOD_PISTOL_BULLET=Call Of Duty 2: MOD_PISTOL_BULLET +ammo_COD2_MOD_PROJECTILE=COD2_MOD_PROJECTILE +ammo_COD2_MOD_PROJECTILE_SPLASH=COD2_MOD_PROJECTILE_SPLASH +ammo_COD2_MOD_RIFLE_BULLET=Call Of Duty 2: MOD_RIFLE_BULLET +ammo_COD2_MOD_SUICIDE=Call Of Duty 2: MOD_SUICIDE +ammo_COD2_MOD_TRIGGER_HURT=COD2_MOD_TRIGGER_HURT +ammo_COD4_BASH=COD4_BASH +ammo_COD4_MOD_EXPLOSIVE=COD4_MOD_EXPLOSIVE +ammo_COD4_MOD_FALLING=COD4_MOD_FALLING +ammo_COD4_MOD_GRENADE=COD4_MOD_GRENADE +ammo_COD4_MOD_GRENADE_SPLASH=COD4_MOD_GRENADE_SPLASH +ammo_COD4_MOD_HEAD_SHOT=COD4_MOD_HEAD_SHOT +ammo_COD4_MOD_IMPACT=COD4_MOD_IMPACT +ammo_COD4_MOD_MELEE=COD4_MOD_MELEE +ammo_COD4_MOD_PISTOL_BULLET=COD4_MOD_PISTOL_BULLET +ammo_COD4_MOD_PROJECTILE=COD4_MOD_PROJECTILE +ammo_COD4_MOD_PROJECTILE_SPLASH=COD4_MOD_PROJECTILE_SPLASH +ammo_COD4_MOD_RIFLE_BULLET=COD4_MOD_RIFLE_BULLET +ammo_COD4_MOD_SUICIDE=COD4_MOD_SUICIDE +ammo_COD4_MOD_TRIGGER_HURT=COD4_MOD_TRIGGER_HURT +ammo_cod5_bash=cod5_bash +ammo_cod5_bayonet=cod5_bayonet +ammo_cod5_mod_bayonet=cod5_mod_bayonet +ammo_cod5_mod_burned=cod5_mod_burned +ammo_cod5_mod_crush=cod5_mod_crush +ammo_cod5_mod_explosive=cod5_mod_explosive +ammo_cod5_mod_falling=cod5_mod_falling +ammo_cod5_mod_grenade=cod5_mod_grenade +ammo_cod5_mod_grenade_splash=cod5_mod_grenade_splash +ammo_cod5_mod_head_shot=cod5_mod_head_shot +ammo_cod5_mod_impact=cod5_mod_impact +ammo_cod5_mod_melee=cod5_mod_melee +ammo_cod5_mod_pistol_bullet=cod5_mod_pistol_bullet +ammo_cod5_mod_projectile=cod5_mod_projectile +ammo_cod5_mod_projectile_splash=cod5_mod_projectile_splash +ammo_cod5_mod_rifle_bullet=cod5_mod_rifle_bullet +ammo_cod5_mod_suicide=cod5_mod_suicide +ammo_cod5_mod_trigger_hurt=cod5_mod_trigger_hurt +ammo_cod5_mod_unknown=cod5_mod_unknown +ammo_MOHAA_=MOHAA_ +ammo_QUAKEWARS_none=QUAKEWARS_none +ammo_WOLFENSTEIN_=WOLFENSTEIN_ +class_COD1_=Call Of Duty 1: Class? +class_COD1_Soldier=Call Of Duty 1: Soldier +class_COD2_=Call Of Duty 2: Class +class_COD2_Soldier=Call Of Duty 2: Soldier +class_COD4_=Call Of Duty 4: Soldier +class_COD4_soldier=Call Of Duty 4: Soldier +class_cod5_=cod5_ +class_cod5_soldier=Call Of Duty 5: Soldier +class_MOHAA_=MOHAA: Class +class_MOHAA_Soldier=MOHAA: Soldier +class_QUAKEWARS_=QUAKEWARS_ +class_QUAKEWARS_aggressor=Quake Wars: Aggressor +class_QUAKEWARS_constructor=Quake Wars: Constructor +class_QUAKEWARS_covertops=Quake Wars: Covert Ops +class_QUAKEWARS_engineer=Quake Wars: Engineer +class_QUAKEWARS_fieldops=Quake Wars: Field Ops +class_QUAKEWARS_infiltrator=Quake Wars: Infiltrator +class_QUAKEWARS_medic=Quake Wars: Medic +class_QUAKEWARS_none=Quake Wars: Unknown +class_QUAKEWARS_oppressor=Quake Wars: Oppressor +class_QUAKEWARS_soldier=Quake Wars: Soldier +class_QUAKEWARS_statsgenworldclass=World +class_QUAKEWARS_technician=Quake Wars: Technician +class_WOLFENSTEIN_=Wolfenstein ET: Class Unknown +class_WOLFENSTEIN_0=Wolfenstein ET: Soldier +class_WOLFENSTEIN_1=Wolfenstein ET: Medic +class_WOLFENSTEIN_2=Wolfenstein ET: Engineer +class_WOLFENSTEIN_3=Wolfenstein ET: Field Ops +class_WOLFENSTEIN_4=Wolfenstein ET: Covert Ops +class_WOLFENSTEIN_7=Wolfenstein ET: Lieutenant +class_WOLFENSTEIN_Soldier=Wolfenstein ET: World +Death=Death +gametype_COD1_actf=Call Of Duty 1: actf +gametype_COD1_bas=Call Of Duty 1: Base Assault +gametype_COD1_bel=Call Of Duty 1: Behind Enemy Lines +gametype_COD1_cnq=Call Of Duty 1: Conquest TDM +gametype_COD1_ctf=Call Of Duty 1: Capture The Flag +gametype_COD1_dem=Call Of Duty 1: Demolition +gametype_COD1_dm=Call Of Duty 1: Deathmatch +gametype_COD1_dom=Call Of Duty 1: Domination +gametype_COD1_hq=Call Of Duty 1: Headquarters +gametype_COD1_lts=Call Of Duty 1: LTS +gametype_COD1_re=Call Of Duty 1: Retrieval +gametype_COD1_rsd=Call Of Duty 1: Reinforced Search And Destroy +gametype_COD1_sd=Call Of Duty 1: Search And Destroy +gametype_COD1_tdm=Call Of Duty 1: Team Death Match +gametype_COD2_csd=Call Of Duty 2: Counter Strike S&D +gametype_COD2_ctb=Call Of Duty 2: Capture The Bottle +gametype_COD2_ctf=Call Of Duty 2: Capture The Flag +gametype_COD2_ctfb=Call Of Duty 2: CTF Back +gametype_COD2_dm=Call Of Duty 2: Deathmatch +gametype_COD2_dom=Call Of Duty 2: Domination +gametype_COD2_ein=Call Of Duty 2: Einstein +gametype_COD2_esd=Call Of Duty 2: Enhanced S&D +gametype_COD2_hq=Call Of Duty 2: Headquarters +gametype_COD2_hq2=Call Of Duty 2: Headquarters 2 +gametype_COD2_htf=Call Of Duty 2: Hold The Flag +gametype_COD2_mm=Call Of Duty 2: Multiplayer Mission +gametype_COD2_noz=Call Of Duty 2: Night Of The Zombies +gametype_COD2_sd=Call Of Duty 2: Search And Destroy +gametype_COD2_sdr=Call Of Duty 2: Search & Destroy Respawn +gametype_COD2_tdm=Call Of Duty 2: Team Death Match +gametype_COD4_dm=Call Of Duty 4: Deathmatch +gametype_COD4_dom=Call Of Duty 4: Domination +gametype_COD4_koth=Call Of Duty 4: Headquarters +gametype_COD4_sab=Call Of Duty 4: Saboteur +gametype_COD4_sd=Call Of Duty 4: Search & Destroy +gametype_COD4_war=Call Of Duty 4: Team Deathmatch +gametype_COD5_ctf=Call Of Duty 5: Capture The Flag +gametype_COD5_dm=Call Of Duty 5: Deathmatch +gametype_COD5_dom=Call Of Duty 5: Domination +gametype_COD5_koth=Call Of Duty 5: Headquarters +gametype_COD5_sab=Call Of Duty 5: Sabotage +gametype_COD5_sd=Call Of Duty 5: Search & Destroy +gametype_COD5_sur=Call Of Duty 5: Survival +gametype_COD5_tdm=Call Of Duty 5: Team Death Match +gametype_COD5_twar=Call Of Duty 5: War +gametype_MOHAA_Capture-The-Flag=MOHAA: Capture The Flag +gametype_MOHAA_dm=MOHAA: Deathmatch +gametype_MOHAA_Free-For-All=MOHAA: Free For All +gametype_MOHAA_Freeze-Tag-CTF=MOHAA: Freeze Tag CTF +gametype_MOHAA_obj=MOHAA: Objective +gametype_MOHAA_Objective-Match=MOHAA: Objective Match +gametype_MOHAA_Round-Based-Match=MOHAA: Round Based Match +gametype_QUAKEWARS_sdgamerulescampaign=Quake Wars: Campaign +gametype_QUAKEWARS_sdgamerulesstopwatch=Quake Wars: Stop Watch +gametype_WOLFENSTEIN_2=Wolfenstein ET: Objective +gametype_WOLFENSTEIN_3=Wolfenstein ET: Stopwatch +gametype_WOLFENSTEIN_4=Wolfenstein ET: Campaign +gametype_WOLFENSTEIN_5=Wolfenstein ET: Last Man Standing +gametype_WOLFENSTEIN_6=Wolfenstein ET: Game Type 6 +gametype_WOLFENSTEIN_7=Wolfenstein ET: Game Type 7 +Kill=Kill +location_COD1_head=Call Of Duty 1: Head +location_COD1_helmet=Call Of Duty 1: Helmet +location_COD1_left_arm_lower=Call Of Duty 1: Left Forearm +location_COD1_left_arm_upper=Call Of Duty 1: Left Bicep +location_COD1_left_foot=Call Of Duty 1: Left Foot +location_COD1_left_hand=Call Of Duty 1: Left Hand +location_COD1_left_leg_lower=Call Of Duty 1: Left Calf +location_COD1_left_leg_upper=Call Of Duty 1: Left Thigh +location_COD1_neck=Call Of Duty 1: Neck +location_COD1_none=Call Of Duty 1: All Over +location_COD1_right_arm_lower=Call Of Duty 1: Right Forearm +location_COD1_right_arm_upper=Call Of Duty 1: Right Bicep +location_COD1_right_foot=Call Of Duty 1: Right Foot +location_COD1_right_hand=Call Of Duty 1: Right Hand +location_COD1_right_leg_lower=Call Of Duty 1: Right Calf +location_COD1_right_leg_upper=Call Of Duty 1: Right Thigh +location_COD1_torso_lower=Call Of Duty 1: Stomach +location_COD1_torso_upper=Call Of Duty 1: Chest +location_COD2_head=Call Of Duty 2: Head +location_COD2_helmet=Call Of Duty 2: Helmet +location_COD2_left_arm_lower=Call Of Duty 2: Left Forearm +location_COD2_left_arm_upper=Call Of Duty 2: Left Bicep +location_COD2_left_foot=Call Of Duty 2: Left Foot +location_COD2_left_hand=Call Of Duty 2: Left Hand +location_COD2_left_leg_lower=Call Of Duty 2: Left Calf +location_COD2_left_leg_upper=Call Of Duty 2: Left Thigh +location_COD2_neck=Call Of Duty 2: Neck +location_COD2_none=Call Of Duty 2: Whole Body +location_COD2_right_arm_lower=Call Of Duty 2: Right Forearm +location_COD2_right_arm_upper=Call Of Duty 2: Right Bicep +location_COD2_right_foot=Call Of Duty 2: Right Foot +location_COD2_right_hand=Call Of Duty 2: Right Hand +location_COD2_right_leg_lower=Call Of Duty 2: Right Calf +location_COD2_right_leg_upper=Call Of Duty 2: Right Thigh +location_COD2_torso_lower=Call Of Duty 2: Stomach +location_COD2_torso_upper=Call Of Duty 2: Chest +location_COD4_head=Call Of Duty 4: Head +location_COD4_left_arm_lower=Call Of Duty 4: Left Forearm +location_COD4_left_arm_upper=Call Of Duty 4: Left Bicep +location_COD4_left_foot=Call Of Duty 4: Left Foot +location_COD4_left_hand=Call Of Duty 4: Left Hand +location_COD4_left_leg_lower=Call Of Duty 4: Left Calf +location_COD4_left_leg_upper=Call Of Duty 4: Left Thigh +location_COD4_neck=Call Of Duty 4: Neck +location_COD4_none=Call Of Duty 4: All Over +location_COD4_right_arm_lower=Call Of Duty 4: Right Forearm +location_COD4_right_arm_upper=Call Of Duty 4: Right Bicep +location_COD4_right_foot=Call Of Duty 4: Right Foot +location_COD4_right_hand=Call Of Duty 4: Right Hand +location_COD4_right_leg_lower=Call Of Duty 4: Right Calf +location_COD4_right_leg_upper=Call Of Duty 4: Right Thigh +location_COD4_torso_lower=Call Of Duty 4: Stomach +location_COD4_torso_upper=Call Of Duty 4: Chest +location_cod5_head=Call Of Duty 5: Head +location_cod5_left_arm_lower=Call Of Duty 5: Left Forearm +location_cod5_left_arm_upper=Call Of Duty 5: Left Bicep +location_cod5_left_foot=Call Of Duty 5: Left Foot +location_cod5_left_hand=Call Of Duty 5: Left Hand +location_cod5_left_leg_lower=Call Of Duty 5: Left Calf +location_cod5_left_leg_upper=Call Of Duty 5: Left Thigh +location_cod5_neck=Call Of Duty 5: Neck +location_cod5_none=Call Of Duty 5: All Over +location_cod5_right_arm_lower=Call Of Duty 5: Right Forearm +location_cod5_right_arm_upper=Call Of Duty 5: Right Bicep +location_cod5_right_foot=Call Of Duty 5: Right Foot +location_cod5_right_hand=Call Of Duty 5: Right Hand +location_cod5_right_leg_lower=Call Of Duty 5: Right Calf +location_cod5_right_leg_upper=Call Of Duty 5: Right Thigh +location_cod5_torso_lower=Call Of Duty 5: Stomach +location_cod5_torso_upper=Call Of Duty 5: Chest +location_MOHAA_=MOHAA: Unknown +location_QUAKEWARS_=Quake Wars: Unknown +location_QUAKEWARS_gdf=Quake Wars: GDF +location_QUAKEWARS_strogg=Quake Wars: Strogg +location_WOLFENSTEIN_=Wolfenstein ET: Unknown +map_COD1_716id_sturmgrenadiere=Call Of Duty 1: 716id_sturmgrenadiere +map_COD1_alpestra=Call Of Duty 1: alpestra +map_COD1_arcville=Call Of Duty 1: arcville +map_COD1_arkov=Call Of Duty 1: arkov +map_COD1_boneyard_sd=Call Of Duty 1: boneyard_sd +map_COD1_brecourt_winter=Call Of Duty 1: brecourt_winter +map_COD1_d-day+7=Call Of Duty 1: d-day+7 +map_COD1_dm701=Call Of Duty 1: dm701 +map_COD1_dniprov=Call Of Duty 1: dniprov +map_COD1_entrenchments=Call Of Duty 1: entrenchments +map_COD1_german_town=Call Of Duty 1: german_town +map_COD1_gfm_amfreville=Call Of Duty 1: GFM amfreville +map_COD1_gfm_cauquigny=Call Of Duty 1: GFM cauquigny +map_COD1_gfm_merderet=Call Of Duty 1: GFM merderet +map_COD1_gfm_offensive=Call Of Duty 1: GFM offensive +map_COD1_gfm_saintlo=Call Of Duty 1: GFM saintlo +map_COD1_gunassault_v1.1=Call Of Duty 1: gunassault_v1.1 +map_COD1_kiel=Call Of Duty 1: Kiel +map_COD1_mice=Call Of Duty 1: mice +map_COD1_mice_v2=Call Of Duty 1: mice_v2 +map_COD1_mogadishu=Call Of Duty 1: mogadishu +map_COD1_moosebunker=Call Of Duty 1: moosebunker +map_COD1_mp_abbey=Call Of Duty 1: Abbey +map_COD1_mp_adlerstein=Call Of Duty 1: Adlerstein +map_COD1_mp_amberville=Call Of Duty 1: Amberville +map_COD1_mp_arnhem=Call Of Duty 1: Arnhem +map_COD1_mp_arnhem2=Call Of Duty 1: arnhem 2 +map_COD1_mp_bazolles_final=Call Of Duty 1: Bazolles Final +map_COD1_mp_bellicourt_night=Call Of Duty 1: Bellicourt Night +map_COD1_mp_bellicourt_night_fix=Call Of Duty 1: Bellicourt Night Fix +map_COD1_mp_bellicourt_v1_1=Call Of Duty 1: Bellicourt v1.1 +map_COD1_mp_berlin=Call Of Duty 1: Berlin +map_COD1_mp_bocage=Call Of Duty 1: Bocage +map_COD1_mp_brecourt=Call Of Duty 1: Brecourt +map_COD1_mp_carentan=Call Of Duty 1: Carentan +map_COD1_mp_cassino=Call Of Duty 1: Cassino +map_COD1_mp_chateau=Call Of Duty 1: Chateau +map_COD1_mp_dawnville=Call Of Duty 1: Dawnville +map_COD1_mp_depot=Call Of Duty 1: Depot +map_COD1_mp_falaisevilla=Call Of Duty 1: Falaise Villa +map_COD1_mp_foy=Call Of Duty 1: Foy +map_COD1_mp_harbor=Call Of Duty 1: Harbour +map_COD1_mp_hurtgen=Call Of Duty 1: Hurtgen +map_COD1_mp_hurtgen-autumn=Call Of Duty 1: Hurtgen Autumn +map_COD1_mp_italy=Call Of Duty 1: Italy +map_COD1_mp_junobeach_final=Call Of Duty 1: Juno Beach Final +map_COD1_mp_kharkov=Call Of Duty 1: Kharkov +map_COD1_mp_kursk=Call Of Duty 1: Kursk +map_COD1_mp_moosebunker=Call Of Duty 1: mp_moosebunker +map_COD1_mp_moosebunker_v1=Call Of Duty 1: mp_moosebunker_v1 +map_COD1_mp_neuville=Call Of Duty 1: Neuville +map_COD1_mp_omahabeach=Call Of Duty 1: Omaha Beach +map_COD1_mp_panzermine=Call Of Duty 1: Panzermine +map_COD1_mp_pavlov=Call Of Duty 1: Pavlov +map_COD1_mp_peaks=Call Of Duty 1: Peaks +map_COD1_mp_pegasusday=Call Of Duty 1: Pegasus Day +map_COD1_mp_pegasusnight=Call Of Duty 1: Pegasus Night +map_COD1_mp_ponyri=Call Of Duty 1: Ponyri +map_COD1_mp_powcamp=Call Of Duty 1: POW Camp +map_COD1_mp_race=Call Of Duty 1: Race +map_COD1_mp_railyard=Call Of Duty 1: Railyard +map_COD1_mp_rhinevalley=Call Of Duty 1: Rhine Valley +map_COD1_mp_rocket=Call Of Duty 1: Rocket +map_COD1_mp_ship=Call Of Duty 1: Ship +map_COD1_mp_sicily=Call Of Duty 1: Sicily +map_COD1_mp_stalingrad=Call Of Duty 1: Stalingrad +map_COD1_mp_stcomedumont=Call Of Duty 1: St. Come Dumont +map_COD1_mp_streets=Call Of Duty 1: Streets +map_COD1_mp_streetwar=Call Of Duty 1: Street War +map_COD1_mp_tigertown=Call Of Duty 1: Tigertown +map_COD1_mp_uo_borisovka=Call Of Duty 1: Borisovka (UO) +map_COD1_mp_uo_carentan=Call Of Duty 1: Carentan (UO) +map_COD1_mp_uo_dawnville=Call Of Duty 1: Dawnville (UO) +map_COD1_mp_uo_depot=Call Of Duty 1: Depot (UO) +map_COD1_mp_uo_harbor=Call Of Duty 1: Harbour (UO) +map_COD1_mp_uo_hollenberg=Call Of Duty 1: Hollenberg (UO) +map_COD1_mp_uo_hurtgen=Call Of Duty 1: Hurtgen (UO) +map_COD1_mp_uo_powcamp=Call Of Duty 1: POW Camp (UO) +map_COD1_mp_uo_stanjel=Call Of Duty 1: Stanjel (UO) +map_COD1_mp_uo_vaddhe=Call Of Duty 1: Vaddhe (UO) +map_COD1_mp_uo_varaville=Call Of Duty 1: Varaville (UO) +map_COD1_mp_valley_night_v3=Call Of Duty 1: mp_valley_night_v3 +map_COD1_mp_valley_v2=Call Of Duty 1: mp_valley_v2 +map_COD1_mp_varaville=Call Of Duty 1: Varaville +map_COD1_mp_windmills=Call Of Duty 1: Windmills +map_COD1_mp_wolfsquare_final=Call Of Duty 1: Wolfsquare Final +map_COD1_normandy=Call Of Duty 1: normandy +map_COD1_nuenen=Call Of Duty 1: Nuenen +map_COD1_second_coming=Call Of Duty 1: second_coming +map_COD1_snipers_canyon=Call Of Duty 1: snipers_canyon +map_COD1_stalingrad_line_of_fire_v1.1=Call Of Duty 1: stalingrad_line_of_fire_v1.1 +map_COD1_stcomedumont_beta=Call Of Duty 1: stcomedumont_beta +map_COD1_tenements=Call Of Duty 1: tenements +map_COD1_the_bridge=Call Of Duty 1: the_bridge +map_COD1_vieuxville=Call Of Duty 1: vieuxville +map_COD1_vikings_omaha=Call Of Duty 1: vikings_omaha +map_COD1_wolfsschanze_day=Call Of Duty 1: wolfsschanze_day +map_COD2_hall_of_glory=Call Of Duty 2: Hall Of Glory +map_COD2_mp_africorps=Call Of Duty 2: Africorps +map_COD2_mp_alger=Call Of Duty 2: Alger +map_COD2_mp_argentan_france=COD2_mp_argentan_france +map_COD2_mp_bastogne=Call Of Duty 2: Bastogne +map_COD2_mp_belltown=Call Of Duty 2: Belltown +map_COD2_mp_berlin1=Call Of Duty 2: Berlin1 +map_COD2_mp_borisovka=Call Of Duty 2: Borisovka +map_COD2_mp_breakout=Call Of Duty 2: Breakout +map_COD2_mp_brecourt=Call Of Duty 2: Brecourt +map_COD2_mp_breslau=Call Of Duty 2: Breslau +map_COD2_mp_bridge=Call Of Duty 2: The Bridge +map_COD2_mp_buhlert=Call Of Duty 2: Buhlert +map_COD2_mp_burgundy=Call Of Duty 2: Burgundy +map_COD2_mp_canal_final=Call Of Duty 2: Canal Final +map_COD2_mp_carentan=Call Of Duty 2: Carentan +map_COD2_mp_cargotown=Call Of Duty 2: Cargo Town +map_COD2_mp_cassino=Call Of Duty 2: Cassino +map_COD2_mp_chateau=Call Of Duty 2: Chateau +map_COD2_mp_chateauday=COD2_mp_chateauday +map_COD2_mp_cr_kasserine=COD2_mp_cr_kasserine +map_COD2_mp_craville=Call Of Duty 2: Craville +map_COD2_mp_dark_forrest_rain_v2=Call Of Duty 2: Dark Forrest Rain V2 +map_COD2_mp_dark_forrest_v2=Call Of Duty 2: Dark Forrest V2 +map_COD2_mp_dasschlumpfdorf=COD2_mp_dasschlumpfdorf +map_COD2_mp_dawnville=Call Of Duty 2: Dawnville +map_COD2_mp_dawnville_cl_final=Call Of Duty 2: Dawnville CL Final +map_COD2_mp_decoy=Call Of Duty 2: Decoy +map_COD2_mp_depot=Call Of Duty 2: Depot +map_COD2_mp_devils_den_beta=Call Of Duty 2: Devils Den Beta +map_COD2_mp_dock_assault=Call Of Duty 2: Dock Assault +map_COD2_mp_downtown=Call Of Duty 2: Downtown +map_COD2_mp_farmhouse=Call Of Duty 2: Farmhouse +map_COD2_mp_flakbatterie_v1_0=Call Of Duty 2: Flak Batterie V1 +map_COD2_mp_frantic2=Call Of Duty 2: Frantic 2 +map_COD2_mp_gothic=Call Of Duty 2: Gothic +map_COD2_mp_harbor=Call Of Duty 2: Harbour +map_COD2_mp_hawk=COD2_mp_hawk +map_COD2_mp_heat_final=Call Of Duty 2: Heat Final +map_COD2_mp_highside=COD2_mp_highside +map_COD2_mp_industry=Call Of Duty 2: Industry +map_COD2_mp_junobeach=Call Of Duty 2: Junobeach +map_COD2_mp_kalsingrad=Call Of Duty 2: Kalsingrad +map_COD2_mp_kalstle_v2=Call Of Duty 2: Kalstle V2 +map_COD2_mp_karkand=Call Of Duty 2: Karkand +map_COD2_mp_leningrad=Call Of Duty 2: Leningrad +map_COD2_mp_lflnchateau=COD2_mp_lflnchateau +map_COD2_mp_maaloy_cod2=Call Of Duty 2: Maaloy +map_COD2_mp_maaloy_cod2_final=COD2_mp_maaloy_cod2_final +map_COD2_mp_matmata=Call Of Duty 2: Matmata +map_COD2_mp_mazza=COD2_mp_mazza +map_COD2_mp_moelingen_fixed=Call Of Duty 2: Moelingen Fixed +map_COD2_mp_montebourg=Call Of Duty 2: Montebourg +map_COD2_mp_muppet=Call Of Duty 2: Muppet +map_COD2_mp_neilos=Call Of Duty 2: Neilos +map_COD2_mp_neilos_night=Call Of Duty 2: Neilos Night +map_COD2_mp_neuville=Call Of Duty 2: Neuville +map_COD2_mp_otara=Call Of Duty 2: Otara +map_COD2_mp_pecs=Call Of Duty 2: Pecs +map_COD2_mp_port=Call Of Duty 2: Port +map_COD2_mp_provence2=Call Of Duty 2: Provence 2 +map_COD2_mp_railyard=Call Of Duty 2: Railyard +map_COD2_mp_rhine=Call Of Duty 2: Rhine +map_COD2_mp_rts=Call Of Duty 2: RTS +map_COD2_mp_russiantown=Call Of Duty 2: Russian Town +map_COD2_mp_slatmata=Call Of Duty 2: Slatmata +map_COD2_mp_stanjel=Call Of Duty 2: Stanjel +map_COD2_mp_stlo=Call Of Duty 2: St. Lo +map_COD2_mp_streets=Call Of Duty 2: Streets +map_COD2_mp_stuttgart=Call Of Duty 2: Stuttgart +map_COD2_mp_the_tomb=Call Of Duty 2: The Tomb +map_COD2_mp_tigertown_v2=Call Of Duty 2: Tiger Town V2 +map_COD2_mp_tobruk_pam=Call Of Duty 2: Tobruk PAM +map_COD2_mp_toujane=Call Of Duty 2: Toujane +map_COD2_mp_trainstation=Call Of Duty 2: Trainstation +map_COD2_mp_tunis=Call Of Duty 2: Tunis +map_COD2_mp_tunisia_dawn=COD2_mp_tunisia_dawn +map_COD2_mp_vik1=Call Of Duty 2: VIK1 +map_COD2_mp_villageraid=COD2_mp_villageraid +map_COD2_mp_vossennack=Call Of Duty 2: Vossennack +map_COD2_mp_xfire_bay=COD2_mp_xfire_bay +map_COD2_mtl_raiders=Call Of Duty 2: MTL Raiders +map_COD2_mtl_rocknite=Call Of Duty 2: MTL Rocknite +map_COD4_mp_backlot=Call Of Duty 4: Back Lot +map_COD4_mp_bloc=Call Of Duty 4: Bloc +map_COD4_mp_bog=Call Of Duty 4: Bog +map_COD4_mp_broadcast=Call Of Duty 4: Broadcast +map_COD4_mp_carentan=Call Of Duty 4: China Town +map_COD4_mp_cargoship=Call Of Duty 4: Cargo Ship +map_COD4_mp_citystreets=Call Of Duty 4: City Streets +map_COD4_mp_convoy=Call Of Duty 4: Convoy +map_COD4_mp_countdown=Call Of Duty 4: Countdown +map_COD4_mp_crash=Call Of Duty 4: Crash +map_COD4_mp_crash_snow=Call Of Duty 4: Crash Snow +map_COD4_mp_creek=Call Of Duty 4: Creek +map_COD4_mp_crossfire=Call Of Duty 4: Crossfire +map_COD4_mp_dusk=Call Of Duty 4: Dusk +map_COD4_mp_farm=Call Of Duty 4: Downpour +map_COD4_mp_hill=Call Of Duty 4: The Hill +map_COD4_mp_killhouse=COD4_mp_killhouse +map_COD4_mp_overgrown=Call Of Duty 4: Overgrown +map_COD4_mp_pipeline=Call Of Duty 4: Pipeline +map_COD4_mp_shipment=Call Of Duty 4: Shipment +map_COD4_mp_showdown=Call Of Duty 4: Showdown +map_COD4_mp_strike=Call Of Duty 4: Strike +map_COD4_mp_vacant=Call Of Duty 4: Vacant +map_COD5_mp_airfield=Call Of Duty 5: Airfield +map_COD5_mp_asylum=Call Of Duty 5: Asylum +map_COD5_mp_castle=Call Of Duty 5: Castle +map_COD5_mp_cliffside=Call Of Duty 5: Cliffside +map_COD5_mp_courtyard=Call Of Duty 5: Courtyard +map_COD5_mp_dome=Call Of Duty 5: Dome +map_COD5_mp_downfall=Call Of Duty 5: Downfall +map_COD5_mp_hangar=Call Of Duty 5: Hangar +map_COD5_mp_kneedeep=Call Of Duty 5: Kneedeep +map_COD5_mp_makin=Call Of Duty 5: Makin +map_COD5_mp_makin_day=Call Of Duty 5: Makin Day +map_COD5_mp_nachtfeuer=Call Of Duty 5: Nachtfeuer +map_COD5_mp_outskirts=Call Of Duty 5: Outskirts +map_COD5_mp_roundhouse=Call Of Duty 5: Round House +map_COD5_mp_seelow=Call Of Duty 5: Seelow +map_COD5_mp_shrine=Call Of Duty 5: Cliffside +map_COD5_mp_suburban=Call Of Duty 5: Suburban +map_COD5_mp_subway=Call Of Duty 5: Station +map_COD5_mp_upheaval=Call Of Duty 5: Suburban +map_COD5_mp_bgate=Call Of Duty 5: Breach +map_COD5_mp_docks=Call Of Duty 5: Sub Pens +map_COD5_mp_drum=Call Of Duty 5: Battery +map_COD5_mp_kwai=Call Of Duty 5: Banzai +map_COD5_mp_stalingrad=Call Of Duty 5: Station +map_COD5_mp_vodka=Call Of Duty 5: Revolution +map_MOHAA_=MOHAA_ +map_MOHAA_mohdm1=MOHAA: Southern France +map_MOHAA_mohdm2=MOHAA: Destroyed France +map_MOHAA_mohdm3=MOHAA: Remagen +map_MOHAA_mohdm4=MOHAA: The Crossroads +map_MOHAA_mohdm6=MOHAA: Stalingrad +map_MOHAA_mohdm7=MOHAA: Deathmatch 7 +map_MOHAA_mp_bahnhof_dm=MOHAA: Bahnhof +map_MOHAA_MP_Bazaar_DM=MOHAA: Bazaar +map_MOHAA_mp_brest_dm=MOHAA: Brest +map_MOHAA_MP_Flughafen_TOW=MOHAA: Flughafen +map_MOHAA_MP_Stadt_DM=MOHAA: Stadt +map_MOHAA_MP_Verschneit_DM=MOHAA: Verschneit +map_MOHAA_Navarone=MOHAA: Navarone +map_MOHAA_obj_team1=MOHAA: The Hunt +map_MOHAA_obj_team2=MOHAA: V2 Rocket +map_MOHAA_obj_team3=MOHAA: Omaha Beach +map_MOHAA_obj_team4=MOHAA: The Bridge +map_MOHAA_stlo=MOHAA: St. Lo +map_QUAKEWARS_area22=Quake Wars: Area 22 +map_QUAKEWARS_ark=Quake Wars: Ark +map_QUAKEWARS_canyon=Quake Wars: Canyon +map_QUAKEWARS_island=Quake Wars: Island +map_QUAKEWARS_outskirts=Quake Wars: Outskirts +map_QUAKEWARS_quarry=Quake Wars: Quarry +map_QUAKEWARS_refinery=Quake Wars: Refinery +map_QUAKEWARS_salvage=Quake Wars: Salvage +map_QUAKEWARS_sewer=Quake Wars: Sewer +map_QUAKEWARS_slipgate=Quake Wars: Slipgate +map_QUAKEWARS_valley=Quake Wars: Valley +map_QUAKEWARS_volcano=Quake Wars: Valley +map_WOLFENSTEIN_baserace_beta2=Wolfenstein ET: Base Race Beta 2 +map_WOLFENSTEIN_battery=Wolfenstein ET: Battery +map_WOLFENSTEIN_braundorf_b3=Wolfenstein ET: Braundorf Beta 3 +map_WOLFENSTEIN_ctf_multi=Wolfenstein ET: CTF Multiplayer +map_WOLFENSTEIN_dubrovnik_b1=Wolfenstein ET: Dubrovnik Beta 1 +map_WOLFENSTEIN_dubrovnik_final=Wolfenstein ET: Dubrovnik Final +map_WOLFENSTEIN_et_ice=Wolfenstein ET: Ice +map_WOLFENSTEIN_frostbite=Wolfenstein ET: Frostbite +map_WOLFENSTEIN_fueldump=Wolfenstein ET: Fuel Dump +map_WOLFENSTEIN_goldrush=Wolfenstein ET: Goldrush +map_WOLFENSTEIN_infamy=Wolfenstein ET: Infamy +map_WOLFENSTEIN_kungfugrip=Wolfenstein ET: Kung Fu Grip +map_WOLFENSTEIN_mp_ameland_final=Wolfenstein ET: Ameland Final +map_WOLFENSTEIN_MP_ASSAULT=Wolfenstein ET: Assault +map_WOLFENSTEIN_mp_bankraid_final=Wolfenstein ET: Bank Raid Final +map_WOLFENSTEIN_mp_base=Wolfenstein ET: Base +map_WOLFENSTEIN_mp_beach=Wolfenstein ET: Beach +map_WOLFENSTEIN_MP_BRIDGE=Wolfenstein ET: Bridge +map_WOLFENSTEIN_MP_CASTLE=Wolfenstein ET: Castle +map_WOLFENSTEIN_mp_castle_siege=Wolfenstein ET: Castle Siege +map_WOLFENSTEIN_mp_checkpoint=Wolfenstein ET: Checkpoint +map_WOLFENSTEIN_mp_church=Wolfenstein ET: Church +map_WOLFENSTEIN_mp_destruction=Wolfenstein ET: Destruction +map_WOLFENSTEIN_mp_ice=Wolfenstein ET: Ice +map_WOLFENSTEIN_mp_island=Wolfenstein ET: Island +map_WOLFENSTEIN_MP_MURDERHILL=Wolfenstein ET: Murder Hill +map_WOLFENSTEIN_MP_RESURRECTION=Wolfenstein ET: Resurrection +map_WOLFENSTEIN_mp_schwalbe=Wolfenstein ET: Schwalbe +map_WOLFENSTEIN_mp_sub=Wolfenstein ET: Sub +map_WOLFENSTEIN_mp_toxicity=Wolfenstein ET: Toxic City +map_WOLFENSTEIN_mp_tram=Wolfenstein ET: Tram +map_WOLFENSTEIN_mp_trenchtoast=Wolfenstein ET: Trench Toast +map_WOLFENSTEIN_MP_VILLAGE=Wolfenstein ET: Village +map_WOLFENSTEIN_northpole=Wolfenstein ET: North Pole +map_WOLFENSTEIN_oasis=Wolfenstein ET: Oasis +map_WOLFENSTEIN_radar=Wolfenstein ET: Radar +map_WOLFENSTEIN_railgun=Wolfenstein ET: Railgun +map_WOLFENSTEIN_raw_b3=Wolfenstein ET: Raw Beta 3 +map_WOLFENSTEIN_rommel_b2=Wolfenstein ET: Rommel Beta 2 +map_WOLFENSTEIN_rommel_final=Wolfenstein ET: Rommel Final +map_WOLFENSTEIN_Stalingrad=Wolfenstein ET: Stalingrad +map_WOLFENSTEIN_supplydepot2=Wolfenstein ET: Supply Depot 2 +map_WOLFENSTEIN_tc_base=Wolfenstein ET: TC Base +map_WOLFENSTEIN_te_frostbite=Wolfenstein ET: TE Frostbite +map_WOLFENSTEIN_te_tundrab2=Wolfenstein ET: TE Tundra Beta 2 +map_WOLFENSTEIN_te_ufo=Wolfenstein ET: TE UFO +map_WOLFENSTEIN_toxic_speedball=Wolfenstein ET: Toxic Speedball +map_WOLFENSTEIN_tundra_rush_beta=Wolfenstein ET: Tundra Rush Beta +map_WOLFENSTEIN_uboot=Wolfenstein ET: U Boot +map_WOLFENSTEIN_vengeance_te_b4=Wolfenstein ET: Vengeance TE Beta 4 +Suicide=Suicide +team_COD1_=Call Of Duty 1: Team? +team_COD1_allies=Call Of Duty 1: Allies +team_COD1_axis=Call Of Duty 1: Axis +team_COD1_playerteam=COD1_playerteam +team_COD1_spectator=Call Of Duty 1: Spectator +team_COD1_targetteam=COD1_targetteam +team_COD2_=Call Of Duty 2: Team? +team_COD2_allies=Call Of Duty 2: Allies +team_COD2_axis=Call Of Duty 2: Axis +team_COD2_playerteam=Call Of Duty 2: Player Team +team_COD2_spectator=Call Of Duty 2: Spectator +team_COD2_targetteam=Call Of Duty 2: Target Team +team_COD4_=Call Of Duty 4: Unknown Team +team_COD4_allies=Call Of Duty 4: Allies +team_COD4_axis=Call Of Duty 4: Terrorists +team_COD4_playerteam=Call Of Duty 4: Player Team +team_COD4_targetteam=Call Of Duty 4: Target Team +team_cod5_=COD5_ +team_COD5_allies=Call Of Duty 5: Allies +team_COD5_axis=Call Of Duty 5: Axis +team_COD5_playerteam=Call Of Duty 5: Unknown +team_COD5_spectator=COD5_spectator +team_COD5_targetteam=Call Of Duty 5: Unknown +team_MOHAA_allies=MOHAA: Allies +team_MOHAA_axis=MOHAA: Axis +team_MOHAA_PlayerTeam=MOHAA: Unknown Team +team_MOHAA_TargetTeam=MOHAA: Unknown Team +team_QUAKEWARS_=Quake Wars: Unknown +team_QUAKEWARS_gdf=Quake Wars: GDF +team_QUAKEWARS_spectators=Quake Wars: Spectator +team_QUAKEWARS_statsgenworldteam=World +team_QUAKEWARS_strogg=Quake Wars: Strogg +team_STATSGENWORLDTEAM=World +team_WOLFENSTEIN_1=Wolfenstein ET: Allies +team_WOLFENSTEIN_2=Wolfenstein ET: Axis +team_WOLFENSTEIN_3=Wolfenstein ET: Spectator +TeamKill=TeamKill +TeamLoss=TeamLoss +TeamSwap=TeamSwap +TeamWin=TeamWin +TopclassCOD1_Soldier=TopclassCOD1_Soldier +TopclassCOD2_Soldier=TopclassCOD2_Soldier +TopclassCOD4_soldier=TopclassCOD4_soldier +TopclassMOHAA_=TopclassMOHAA_ +TopclassMOHAA_Soldier=TopclassMOHAA_Soldier +TopclassQUAKEWARS_=TopclassQUAKEWARS_ +TopclassQUAKEWARS_aggressor=TopclassQUAKEWARS_aggressor +TopclassQUAKEWARS_constructor=TopclassQUAKEWARS_constructor +TopclassQUAKEWARS_covertops=TopclassQUAKEWARS_covertops +TopclassQUAKEWARS_engineer=TopclassQUAKEWARS_engineer +TopclassQUAKEWARS_fieldops=TopclassQUAKEWARS_fieldops +TopclassQUAKEWARS_infiltrator=TopclassQUAKEWARS_infiltrator +TopclassQUAKEWARS_medic=TopclassQUAKEWARS_medic +TopclassQUAKEWARS_none=TopclassQUAKEWARS_none +TopclassQUAKEWARS_oppressor=TopclassQUAKEWARS_oppressor +TopclassQUAKEWARS_soldier=TopclassQUAKEWARS_soldier +TopclassQUAKEWARS_statsgenworldclass=TopclassQUAKEWARS_statsgenworldclass +TopclassQUAKEWARS_technician=TopclassQUAKEWARS_technician +TopclassWOLFENSTEIN_=TopclassWOLFENSTEIN_ +TopclassWOLFENSTEIN_0=TopclassWOLFENSTEIN_0 +TopclassWOLFENSTEIN_1=TopclassWOLFENSTEIN_1 +TopclassWOLFENSTEIN_2=TopclassWOLFENSTEIN_2 +TopclassWOLFENSTEIN_3=TopclassWOLFENSTEIN_3 +TopclassWOLFENSTEIN_4=TopclassWOLFENSTEIN_4 +TopclassWOLFENSTEIN_7=TopclassWOLFENSTEIN_7 +TopDeaths=TopDeaths +TopDeathStreak=TopDeathStreak +TopgametypeCOD1_actf=TopgametypeCOD1_actf +TopgametypeCOD1_bas=TopgametypeCOD1_bas +TopgametypeCOD1_bel=TopgametypeCOD1_bel +TopgametypeCOD1_cnq=TopgametypeCOD1_cnq +TopgametypeCOD1_ctf=TopgametypeCOD1_ctf +TopgametypeCOD1_dm=TopgametypeCOD1_dm +TopgametypeCOD1_dom=TopgametypeCOD1_dom +TopgametypeCOD1_hq=TopgametypeCOD1_hq +TopgametypeCOD1_lts=TopgametypeCOD1_lts +TopgametypeCOD1_re=TopgametypeCOD1_re +TopgametypeCOD1_rsd=TopgametypeCOD1_rsd +TopgametypeCOD1_sd=TopgametypeCOD1_sd +TopgametypeCOD1_tdm=TopgametypeCOD1_tdm +TopgametypeCOD2_csd=TopgametypeCOD2_csd +TopgametypeCOD2_ctb=TopgametypeCOD2_ctb +TopgametypeCOD2_ctf=TopgametypeCOD2_ctf +TopgametypeCOD2_ctfb=TopgametypeCOD2_ctfb +TopgametypeCOD2_dm=TopgametypeCOD2_dm +TopgametypeCOD2_dom=TopgametypeCOD2_dom +TopgametypeCOD2_ein=TopgametypeCOD2_ein +TopgametypeCOD2_esd=TopgametypeCOD2_esd +TopgametypeCOD2_hq=TopgametypeCOD2_hq +TopgametypeCOD2_hq2=TopgametypeCOD2_hq2 +TopgametypeCOD2_htf=TopgametypeCOD2_htf +TopgametypeCOD2_mm=TopgametypeCOD2_mm +TopgametypeCOD2_noz=TopgametypeCOD2_noz +TopgametypeCOD2_sd=TopgametypeCOD2_sd +TopgametypeCOD2_sdr=TopgametypeCOD2_sdr +TopgametypeCOD2_tdm=TopgametypeCOD2_tdm +TopgametypeCOD4_dom=TopgametypeCOD4_dom +TopgametypeCOD4_koth=TopgametypeCOD4_koth +TopgametypeCOD4_sab=TopgametypeCOD4_sab +TopgametypeCOD4_sd=TopgametypeCOD4_sd +TopgametypeCOD4_war=TopgametypeCOD4_war +TopgametypeMOHAA_Capture-The-Flag=TopgametypeMOHAA_Capture-The-Flag +TopgametypeMOHAA_dm=TopgametypeMOHAA_dm +TopgametypeMOHAA_Free-For-All=TopgametypeMOHAA_Free-For-All +TopgametypeMOHAA_Freeze-Tag-CTF=TopgametypeMOHAA_Freeze-Tag-CTF +TopgametypeMOHAA_obj=TopgametypeMOHAA_obj +TopgametypeMOHAA_Objective-Match=TopgametypeMOHAA_Objective-Match +TopgametypeQUAKEWARS_sdgamerulescampaign=TopgametypeQUAKEWARS_sdgamerulescampaign +TopgametypeWOLFENSTEIN_2=TopgametypeWOLFENSTEIN_2 +TopgametypeWOLFENSTEIN_3=TopgametypeWOLFENSTEIN_3 +TopgametypeWOLFENSTEIN_4=TopgametypeWOLFENSTEIN_4 +TopgametypeWOLFENSTEIN_5=TopgametypeWOLFENSTEIN_5 +TopgametypeWOLFENSTEIN_6=TopgametypeWOLFENSTEIN_6 +TopgametypeWOLFENSTEIN_7=TopgametypeWOLFENSTEIN_7 +TopKillDeathRatio=TopKillDeathRatio +TopKills=TopKills +TopKillStreak=TopKillStreak +ToplocationCOD1_head=ToplocationCOD1_head +ToplocationCOD1_helmet=ToplocationCOD1_helmet +ToplocationCOD1_left_arm_lower=ToplocationCOD1_left_arm_lower +ToplocationCOD1_left_arm_upper=ToplocationCOD1_left_arm_upper +ToplocationCOD1_left_foot=ToplocationCOD1_left_foot +ToplocationCOD1_left_hand=ToplocationCOD1_left_hand +ToplocationCOD1_left_leg_lower=ToplocationCOD1_left_leg_lower +ToplocationCOD1_left_leg_upper=ToplocationCOD1_left_leg_upper +ToplocationCOD1_neck=ToplocationCOD1_neck +ToplocationCOD1_none=ToplocationCOD1_none +ToplocationCOD1_right_arm_lower=ToplocationCOD1_right_arm_lower +ToplocationCOD1_right_arm_upper=ToplocationCOD1_right_arm_upper +ToplocationCOD1_right_foot=ToplocationCOD1_right_foot +ToplocationCOD1_right_hand=ToplocationCOD1_right_hand +ToplocationCOD1_right_leg_lower=ToplocationCOD1_right_leg_lower +ToplocationCOD1_right_leg_upper=ToplocationCOD1_right_leg_upper +ToplocationCOD1_torso_lower=ToplocationCOD1_torso_lower +ToplocationCOD1_torso_upper=ToplocationCOD1_torso_upper +ToplocationCOD2_head=ToplocationCOD2_head +ToplocationCOD2_helmet=ToplocationCOD2_helmet +ToplocationCOD2_left_arm_lower=ToplocationCOD2_left_arm_lower +ToplocationCOD2_left_arm_upper=ToplocationCOD2_left_arm_upper +ToplocationCOD2_left_foot=ToplocationCOD2_left_foot +ToplocationCOD2_left_hand=ToplocationCOD2_left_hand +ToplocationCOD2_left_leg_lower=ToplocationCOD2_left_leg_lower +ToplocationCOD2_left_leg_upper=ToplocationCOD2_left_leg_upper +ToplocationCOD2_neck=ToplocationCOD2_neck +ToplocationCOD2_none=ToplocationCOD2_none +ToplocationCOD2_right_arm_lower=ToplocationCOD2_right_arm_lower +ToplocationCOD2_right_arm_upper=ToplocationCOD2_right_arm_upper +ToplocationCOD2_right_foot=ToplocationCOD2_right_foot +ToplocationCOD2_right_hand=ToplocationCOD2_right_hand +ToplocationCOD2_right_leg_lower=ToplocationCOD2_right_leg_lower +ToplocationCOD2_right_leg_upper=ToplocationCOD2_right_leg_upper +ToplocationCOD2_torso_lower=ToplocationCOD2_torso_lower +ToplocationCOD2_torso_upper=ToplocationCOD2_torso_upper +ToplocationCOD4_head=ToplocationCOD4_head +ToplocationCOD4_left_arm_lower=ToplocationCOD4_left_arm_lower +ToplocationCOD4_left_arm_upper=ToplocationCOD4_left_arm_upper +ToplocationCOD4_left_foot=ToplocationCOD4_left_foot +ToplocationCOD4_left_hand=ToplocationCOD4_left_hand +ToplocationCOD4_left_leg_lower=ToplocationCOD4_left_leg_lower +ToplocationCOD4_left_leg_upper=ToplocationCOD4_left_leg_upper +ToplocationCOD4_neck=ToplocationCOD4_neck +ToplocationCOD4_none=ToplocationCOD4_none +ToplocationCOD4_right_arm_lower=ToplocationCOD4_right_arm_lower +ToplocationCOD4_right_arm_upper=ToplocationCOD4_right_arm_upper +ToplocationCOD4_right_foot=ToplocationCOD4_right_foot +ToplocationCOD4_right_hand=ToplocationCOD4_right_hand +ToplocationCOD4_right_leg_lower=ToplocationCOD4_right_leg_lower +ToplocationCOD4_right_leg_upper=ToplocationCOD4_right_leg_upper +ToplocationCOD4_torso_lower=ToplocationCOD4_torso_lower +ToplocationCOD4_torso_upper=ToplocationCOD4_torso_upper +ToplocationMOHAA_=ToplocationMOHAA_ +ToplocationQUAKEWARS_gdf=ToplocationQUAKEWARS_gdf +ToplocationQUAKEWARS_strogg=ToplocationQUAKEWARS_strogg +ToplocationWOLFENSTEIN_=ToplocationWOLFENSTEIN_ +TopmapCOD1_716id_sturmgrenadiere=TopmapCOD1_716id_sturmgrenadiere +TopmapCOD1_alpestra=TopmapCOD1_alpestra +TopmapCOD1_arcville=TopmapCOD1_arcville +TopmapCOD1_arkov=TopmapCOD1_arkov +TopmapCOD1_boneyard_sd=TopmapCOD1_boneyard_sd +TopmapCOD1_brecourt_winter=TopmapCOD1_brecourt_winter +TopmapCOD1_d-day+7=TopmapCOD1_d-day+7 +TopmapCOD1_dm701=TopmapCOD1_dm701 +TopmapCOD1_dniprov=TopmapCOD1_dniprov +TopmapCOD1_entrenchments=TopmapCOD1_entrenchments +TopmapCOD1_german_town=TopmapCOD1_german_town +TopmapCOD1_gfm_cauquigny=TopmapCOD1_gfm_cauquigny +TopmapCOD1_gfm_merderet=TopmapCOD1_gfm_merderet +TopmapCOD1_gfm_saintlo=TopmapCOD1_gfm_saintlo +TopmapCOD1_gunassault_v1.1=TopmapCOD1_gunassault_v1.1 +TopmapCOD1_kiel=TopmapCOD1_kiel +TopmapCOD1_mice=TopmapCOD1_mice +TopmapCOD1_mice_v2=TopmapCOD1_mice_v2 +TopmapCOD1_mogadishu=TopmapCOD1_mogadishu +TopmapCOD1_moosebunker=TopmapCOD1_moosebunker +TopmapCOD1_mp_abbey=TopmapCOD1_mp_abbey +TopmapCOD1_mp_adlerstein=TopmapCOD1_mp_adlerstein +TopmapCOD1_mp_amberville=TopmapCOD1_mp_amberville +TopmapCOD1_mp_arnhem=TopmapCOD1_mp_arnhem +TopmapCOD1_mp_arnhem2=TopmapCOD1_mp_arnhem2 +TopmapCOD1_mp_bazolles_final=TopmapCOD1_mp_bazolles_final +TopmapCOD1_mp_bellicourt_night=TopmapCOD1_mp_bellicourt_night +TopmapCOD1_mp_bellicourt_night_fix=TopmapCOD1_mp_bellicourt_night_fix +TopmapCOD1_mp_bellicourt_v1_1=TopmapCOD1_mp_bellicourt_v1_1 +TopmapCOD1_mp_berlin=TopmapCOD1_mp_berlin +TopmapCOD1_mp_bocage=TopmapCOD1_mp_bocage +TopmapCOD1_mp_brecourt=TopmapCOD1_mp_brecourt +TopmapCOD1_mp_carentan=TopmapCOD1_mp_carentan +TopmapCOD1_mp_cassino=TopmapCOD1_mp_cassino +TopmapCOD1_mp_chateau=TopmapCOD1_mp_chateau +TopmapCOD1_mp_dawnville=TopmapCOD1_mp_dawnville +TopmapCOD1_mp_depot=TopmapCOD1_mp_depot +TopmapCOD1_mp_falaisevilla=TopmapCOD1_mp_falaisevilla +TopmapCOD1_mp_foy=TopmapCOD1_mp_foy +TopmapCOD1_mp_harbor=TopmapCOD1_mp_harbor +TopmapCOD1_mp_hurtgen=TopmapCOD1_mp_hurtgen +TopmapCOD1_mp_hurtgen-autumn=TopmapCOD1_mp_hurtgen-autumn +TopmapCOD1_mp_italy=TopmapCOD1_mp_italy +TopmapCOD1_mp_junobeach_final=TopmapCOD1_mp_junobeach_final +TopmapCOD1_mp_kharkov=TopmapCOD1_mp_kharkov +TopmapCOD1_mp_kursk=TopmapCOD1_mp_kursk +TopmapCOD1_mp_moosebunker=TopmapCOD1_mp_moosebunker +TopmapCOD1_mp_moosebunker_v1=TopmapCOD1_mp_moosebunker_v1 +TopmapCOD1_mp_neuville=TopmapCOD1_mp_neuville +TopmapCOD1_mp_panzermine=TopmapCOD1_mp_panzermine +TopmapCOD1_mp_pavlov=TopmapCOD1_mp_pavlov +TopmapCOD1_mp_peaks=TopmapCOD1_mp_peaks +TopmapCOD1_mp_pegasusday=TopmapCOD1_mp_pegasusday +TopmapCOD1_mp_pegasusnight=TopmapCOD1_mp_pegasusnight +TopmapCOD1_mp_ponyri=TopmapCOD1_mp_ponyri +TopmapCOD1_mp_powcamp=TopmapCOD1_mp_powcamp +TopmapCOD1_mp_race=TopmapCOD1_mp_race +TopmapCOD1_mp_railyard=TopmapCOD1_mp_railyard +TopmapCOD1_mp_rhinevalley=TopmapCOD1_mp_rhinevalley +TopmapCOD1_mp_rocket=TopmapCOD1_mp_rocket +TopmapCOD1_mp_ship=TopmapCOD1_mp_ship +TopmapCOD1_mp_sicily=TopmapCOD1_mp_sicily +TopmapCOD1_mp_stalingrad=TopmapCOD1_mp_stalingrad +TopmapCOD1_mp_stcomedumont=TopmapCOD1_mp_stcomedumont +TopmapCOD1_mp_streets=TopmapCOD1_mp_streets +TopmapCOD1_mp_streetwar=TopmapCOD1_mp_streetwar +TopmapCOD1_mp_tigertown=TopmapCOD1_mp_tigertown +TopmapCOD1_mp_uo_borisovka=TopmapCOD1_mp_uo_borisovka +TopmapCOD1_mp_uo_carentan=TopmapCOD1_mp_uo_carentan +TopmapCOD1_mp_uo_dawnville=TopmapCOD1_mp_uo_dawnville +TopmapCOD1_mp_uo_depot=TopmapCOD1_mp_uo_depot +TopmapCOD1_mp_uo_harbor=TopmapCOD1_mp_uo_harbor +TopmapCOD1_mp_uo_hollenberg=TopmapCOD1_mp_uo_hollenberg +TopmapCOD1_mp_uo_hurtgen=TopmapCOD1_mp_uo_hurtgen +TopmapCOD1_mp_uo_powcamp=TopmapCOD1_mp_uo_powcamp +TopmapCOD1_mp_uo_stanjel=TopmapCOD1_mp_uo_stanjel +TopmapCOD1_mp_uo_vaddhe=TopmapCOD1_mp_uo_vaddhe +TopmapCOD1_mp_uo_varaville=TopmapCOD1_mp_uo_varaville +TopmapCOD1_mp_valley_night_v3=TopmapCOD1_mp_valley_night_v3 +TopmapCOD1_mp_valley_v2=TopmapCOD1_mp_valley_v2 +TopmapCOD1_mp_varaville=TopmapCOD1_mp_varaville +TopmapCOD1_mp_windmills=TopmapCOD1_mp_windmills +TopmapCOD1_mp_wolfsquare_final=TopmapCOD1_mp_wolfsquare_final +TopmapCOD1_normandy=TopmapCOD1_normandy +TopmapCOD1_nuenen=TopmapCOD1_nuenen +TopmapCOD1_second_coming=TopmapCOD1_second_coming +TopmapCOD1_snipers_canyon=TopmapCOD1_snipers_canyon +TopmapCOD1_stalingrad_line_of_fire_v1.1=TopmapCOD1_stalingrad_line_of_fire_v1.1 +TopmapCOD1_stcomedumont_beta=TopmapCOD1_stcomedumont_beta +TopmapCOD1_tenements=TopmapCOD1_tenements +TopmapCOD1_the_bridge=TopmapCOD1_the_bridge +TopmapCOD1_vieuxville=TopmapCOD1_vieuxville +TopmapCOD1_vikings_omaha=TopmapCOD1_vikings_omaha +TopmapCOD1_wolfsschanze_day=TopmapCOD1_wolfsschanze_day +TopmapCOD2_mp_africorps=TopmapCOD2_mp_africorps +TopmapCOD2_mp_alger=TopmapCOD2_mp_alger +TopmapCOD2_mp_bastogne=TopmapCOD2_mp_bastogne +TopmapCOD2_mp_belltown=TopmapCOD2_mp_belltown +TopmapCOD2_mp_berlin1=TopmapCOD2_mp_berlin1 +TopmapCOD2_mp_borisovka=TopmapCOD2_mp_borisovka +TopmapCOD2_mp_breakout=TopmapCOD2_mp_breakout +TopmapCOD2_mp_brecourt=TopmapCOD2_mp_brecourt +TopmapCOD2_mp_breslau=TopmapCOD2_mp_breslau +TopmapCOD2_mp_bridge=TopmapCOD2_mp_bridge +TopmapCOD2_mp_buhlert=TopmapCOD2_mp_buhlert +TopmapCOD2_mp_burgundy=TopmapCOD2_mp_burgundy +TopmapCOD2_mp_canal_final=TopmapCOD2_mp_canal_final +TopmapCOD2_mp_carentan=TopmapCOD2_mp_carentan +TopmapCOD2_mp_cargotown=TopmapCOD2_mp_cargotown +TopmapCOD2_mp_cassino=TopmapCOD2_mp_cassino +TopmapCOD2_mp_chateau=TopmapCOD2_mp_chateau +TopmapCOD2_mp_dark_forrest_rain_v2=TopmapCOD2_mp_dark_forrest_rain_v2 +TopmapCOD2_mp_dark_forrest_v2=TopmapCOD2_mp_dark_forrest_v2 +TopmapCOD2_mp_dasschlumpfdorf=TopmapCOD2_mp_dasschlumpfdorf +TopmapCOD2_mp_dawnville=TopmapCOD2_mp_dawnville +TopmapCOD2_mp_dawnville_cl_final=TopmapCOD2_mp_dawnville_cl_final +TopmapCOD2_mp_decoy=TopmapCOD2_mp_decoy +TopmapCOD2_mp_devils_den_beta=TopmapCOD2_mp_devils_den_beta +TopmapCOD2_mp_dock_assault=TopmapCOD2_mp_dock_assault +TopmapCOD2_mp_downtown=TopmapCOD2_mp_downtown +TopmapCOD2_mp_farmhouse=TopmapCOD2_mp_farmhouse +TopmapCOD2_mp_frantic2=TopmapCOD2_mp_frantic2 +TopmapCOD2_mp_gothic=TopmapCOD2_mp_gothic +TopmapCOD2_mp_harbor=TopmapCOD2_mp_harbor +TopmapCOD2_mp_heat_final=TopmapCOD2_mp_heat_final +TopmapCOD2_mp_industry=TopmapCOD2_mp_industry +TopmapCOD2_mp_junobeach=TopmapCOD2_mp_junobeach +TopmapCOD2_mp_kalstle_v2=TopmapCOD2_mp_kalstle_v2 +TopmapCOD2_mp_karkand=TopmapCOD2_mp_karkand +TopmapCOD2_mp_leningrad=TopmapCOD2_mp_leningrad +TopmapCOD2_mp_maaloy_cod2=TopmapCOD2_mp_maaloy_cod2 +TopmapCOD2_mp_matmata=TopmapCOD2_mp_matmata +TopmapCOD2_mp_moelingen_fixed=TopmapCOD2_mp_moelingen_fixed +TopmapCOD2_mp_montebourg=TopmapCOD2_mp_montebourg +TopmapCOD2_mp_muppet=TopmapCOD2_mp_muppet +TopmapCOD2_mp_neilos=TopmapCOD2_mp_neilos +TopmapCOD2_mp_neilos_night=TopmapCOD2_mp_neilos_night +TopmapCOD2_mp_otara=TopmapCOD2_mp_otara +TopmapCOD2_mp_pecs=TopmapCOD2_mp_pecs +TopmapCOD2_mp_provence2=TopmapCOD2_mp_provence2 +TopmapCOD2_mp_railyard=TopmapCOD2_mp_railyard +TopmapCOD2_mp_rhine=TopmapCOD2_mp_rhine +TopmapCOD2_mp_rts=TopmapCOD2_mp_rts +TopmapCOD2_mp_russiantown=TopmapCOD2_mp_russiantown +TopmapCOD2_mp_slatmata=TopmapCOD2_mp_slatmata +TopmapCOD2_mp_stanjel=TopmapCOD2_mp_stanjel +TopmapCOD2_mp_stlo=TopmapCOD2_mp_stlo +TopmapCOD2_mp_streets=TopmapCOD2_mp_streets +TopmapCOD2_mp_stuttgart=TopmapCOD2_mp_stuttgart +TopmapCOD2_mp_the_tomb=TopmapCOD2_mp_the_tomb +TopmapCOD2_mp_tigertown_v2=TopmapCOD2_mp_tigertown_v2 +TopmapCOD2_mp_tobruk_pam=TopmapCOD2_mp_tobruk_pam +TopmapCOD2_mp_toujane=TopmapCOD2_mp_toujane +TopmapCOD2_mp_trainstation=TopmapCOD2_mp_trainstation +TopmapCOD2_mp_tunis=TopmapCOD2_mp_tunis +TopmapCOD2_mp_vik1=TopmapCOD2_mp_vik1 +TopmapCOD2_mp_vossennack=TopmapCOD2_mp_vossennack +TopmapCOD2_mtl_raiders=TopmapCOD2_mtl_raiders +TopmapCOD2_mtl_rocknite=TopmapCOD2_mtl_rocknite +TopmapCOD4_mp_backlot=TopmapCOD4_mp_backlot +TopmapCOD4_mp_bloc=TopmapCOD4_mp_bloc +TopmapCOD4_mp_bog=TopmapCOD4_mp_bog +TopmapCOD4_mp_cargoship=TopmapCOD4_mp_cargoship +TopmapCOD4_mp_citystreets=TopmapCOD4_mp_citystreets +TopmapCOD4_mp_convoy=TopmapCOD4_mp_convoy +TopmapCOD4_mp_countdown=TopmapCOD4_mp_countdown +TopmapCOD4_mp_crash=TopmapCOD4_mp_crash +TopmapCOD4_mp_crash_snow=TopmapCOD4_mp_crash_snow +TopmapCOD4_mp_crossfire=TopmapCOD4_mp_crossfire +TopmapCOD4_mp_farm=TopmapCOD4_mp_farm +TopmapCOD4_mp_overgrown=TopmapCOD4_mp_overgrown +TopmapCOD4_mp_pipeline=TopmapCOD4_mp_pipeline +TopmapCOD4_mp_shipment=TopmapCOD4_mp_shipment +TopmapCOD4_mp_showdown=TopmapCOD4_mp_showdown +TopmapCOD4_mp_strike=TopmapCOD4_mp_strike +TopmapCOD4_mp_vacant=TopmapCOD4_mp_vacant +TopmapMOHAA_mohdm1=TopmapMOHAA_mohdm1 +TopmapMOHAA_mohdm2=TopmapMOHAA_mohdm2 +TopmapMOHAA_mohdm3=TopmapMOHAA_mohdm3 +TopmapMOHAA_mohdm4=TopmapMOHAA_mohdm4 +TopmapMOHAA_mohdm6=TopmapMOHAA_mohdm6 +TopmapMOHAA_mohdm7=TopmapMOHAA_mohdm7 +TopmapMOHAA_mp_bahnhof_dm=TopmapMOHAA_mp_bahnhof_dm +TopmapMOHAA_MP_Bazaar_DM=TopmapMOHAA_MP_Bazaar_DM +TopmapMOHAA_mp_brest_dm=TopmapMOHAA_mp_brest_dm +TopmapMOHAA_MP_Flughafen_TOW=TopmapMOHAA_MP_Flughafen_TOW +TopmapMOHAA_MP_Stadt_DM=TopmapMOHAA_MP_Stadt_DM +TopmapMOHAA_MP_Verschneit_DM=TopmapMOHAA_MP_Verschneit_DM +TopmapMOHAA_Navarone=TopmapMOHAA_Navarone +TopmapMOHAA_obj_team1=TopmapMOHAA_obj_team1 +TopmapMOHAA_obj_team2=TopmapMOHAA_obj_team2 +TopmapMOHAA_obj_team3=TopmapMOHAA_obj_team3 +TopmapMOHAA_obj_team4=TopmapMOHAA_obj_team4 +TopmapMOHAA_stlo=TopmapMOHAA_stlo +TopmapQUAKEWARS_area22=TopmapQUAKEWARS_area22 +TopmapQUAKEWARS_ark=TopmapQUAKEWARS_ark +TopmapQUAKEWARS_canyon=TopmapQUAKEWARS_canyon +TopmapQUAKEWARS_island=TopmapQUAKEWARS_island +TopmapQUAKEWARS_outskirts=TopmapQUAKEWARS_outskirts +TopmapQUAKEWARS_quarry=TopmapQUAKEWARS_quarry +TopmapQUAKEWARS_refinery=TopmapQUAKEWARS_refinery +TopmapQUAKEWARS_salvage=TopmapQUAKEWARS_salvage +TopmapQUAKEWARS_sewer=TopmapQUAKEWARS_sewer +TopmapQUAKEWARS_slipgate=TopmapQUAKEWARS_slipgate +TopmapQUAKEWARS_valley=TopmapQUAKEWARS_valley +TopmapQUAKEWARS_volcano=TopmapQUAKEWARS_volcano +TopmapWOLFENSTEIN_baserace_beta2=TopmapWOLFENSTEIN_baserace_beta2 +TopmapWOLFENSTEIN_battery=TopmapWOLFENSTEIN_battery +TopmapWOLFENSTEIN_braundorf_b3=TopmapWOLFENSTEIN_braundorf_b3 +TopmapWOLFENSTEIN_ctf_multi=TopmapWOLFENSTEIN_ctf_multi +TopmapWOLFENSTEIN_dubrovnik_b1=TopmapWOLFENSTEIN_dubrovnik_b1 +TopmapWOLFENSTEIN_dubrovnik_final=TopmapWOLFENSTEIN_dubrovnik_final +TopmapWOLFENSTEIN_et_ice=TopmapWOLFENSTEIN_et_ice +TopmapWOLFENSTEIN_frostbite=TopmapWOLFENSTEIN_frostbite +TopmapWOLFENSTEIN_fueldump=TopmapWOLFENSTEIN_fueldump +TopmapWOLFENSTEIN_goldrush=TopmapWOLFENSTEIN_goldrush +TopmapWOLFENSTEIN_infamy=TopmapWOLFENSTEIN_infamy +TopmapWOLFENSTEIN_kungfugrip=TopmapWOLFENSTEIN_kungfugrip +TopmapWOLFENSTEIN_mp_ameland_final=TopmapWOLFENSTEIN_mp_ameland_final +TopmapWOLFENSTEIN_MP_ASSAULT=TopmapWOLFENSTEIN_MP_ASSAULT +TopmapWOLFENSTEIN_mp_bankraid_final=TopmapWOLFENSTEIN_mp_bankraid_final +TopmapWOLFENSTEIN_mp_base=TopmapWOLFENSTEIN_mp_base +TopmapWOLFENSTEIN_mp_beach=TopmapWOLFENSTEIN_mp_beach +TopmapWOLFENSTEIN_MP_CASTLE=TopmapWOLFENSTEIN_MP_CASTLE +TopmapWOLFENSTEIN_mp_castle_siege=TopmapWOLFENSTEIN_mp_castle_siege +TopmapWOLFENSTEIN_mp_checkpoint=TopmapWOLFENSTEIN_mp_checkpoint +TopmapWOLFENSTEIN_mp_church=TopmapWOLFENSTEIN_mp_church +TopmapWOLFENSTEIN_mp_destruction=TopmapWOLFENSTEIN_mp_destruction +TopmapWOLFENSTEIN_mp_ice=TopmapWOLFENSTEIN_mp_ice +TopmapWOLFENSTEIN_mp_island=TopmapWOLFENSTEIN_mp_island +TopmapWOLFENSTEIN_MP_MURDERHILL=TopmapWOLFENSTEIN_MP_MURDERHILL +TopmapWOLFENSTEIN_MP_RESURRECTION=TopmapWOLFENSTEIN_MP_RESURRECTION +TopmapWOLFENSTEIN_mp_schwalbe=TopmapWOLFENSTEIN_mp_schwalbe +TopmapWOLFENSTEIN_mp_sub=TopmapWOLFENSTEIN_mp_sub +TopmapWOLFENSTEIN_mp_toxicity=TopmapWOLFENSTEIN_mp_toxicity +TopmapWOLFENSTEIN_mp_tram=TopmapWOLFENSTEIN_mp_tram +TopmapWOLFENSTEIN_mp_trenchtoast=TopmapWOLFENSTEIN_mp_trenchtoast +TopmapWOLFENSTEIN_mp_village=TopmapWOLFENSTEIN_mp_village +TopmapWOLFENSTEIN_northpole=TopmapWOLFENSTEIN_northpole +TopmapWOLFENSTEIN_oasis=TopmapWOLFENSTEIN_oasis +TopmapWOLFENSTEIN_radar=TopmapWOLFENSTEIN_radar +TopmapWOLFENSTEIN_railgun=TopmapWOLFENSTEIN_railgun +TopmapWOLFENSTEIN_raw_b3=TopmapWOLFENSTEIN_raw_b3 +TopmapWOLFENSTEIN_rommel_b2=TopmapWOLFENSTEIN_rommel_b2 +TopmapWOLFENSTEIN_rommel_final=TopmapWOLFENSTEIN_rommel_final +TopmapWOLFENSTEIN_Stalingrad=TopmapWOLFENSTEIN_Stalingrad +TopmapWOLFENSTEIN_supplydepot2=TopmapWOLFENSTEIN_supplydepot2 +TopmapWOLFENSTEIN_tc_base=TopmapWOLFENSTEIN_tc_base +TopmapWOLFENSTEIN_te_frostbite=TopmapWOLFENSTEIN_te_frostbite +TopmapWOLFENSTEIN_te_tundrab2=TopmapWOLFENSTEIN_te_tundrab2 +TopmapWOLFENSTEIN_te_ufo=TopmapWOLFENSTEIN_te_ufo +TopmapWOLFENSTEIN_toxic_speedball=TopmapWOLFENSTEIN_toxic_speedball +TopmapWOLFENSTEIN_tundra_rush_beta=TopmapWOLFENSTEIN_tundra_rush_beta +TopmapWOLFENSTEIN_uboot=TopmapWOLFENSTEIN_uboot +TopmapWOLFENSTEIN_vengeance_te_b4=TopmapWOLFENSTEIN_vengeance_te_b4 +TopRoundsPlayed=TopRoundsPlayed +TopScore=TopScore +TopSkill=TopSkill +TopSuicides=TopSuicides +TopteamCOD1_=TopteamCOD1_ +TopteamCOD1_allies=TopteamCOD1_allies +TopteamCOD1_axis=TopteamCOD1_axis +TopteamCOD1_spectator=TopteamCOD1_spectator +TopteamCOD2_=TopteamCOD2_ +TopteamCOD2_allies=TopteamCOD2_allies +TopteamCOD2_axis=TopteamCOD2_axis +TopteamCOD2_playerteam=TopteamCOD2_playerteam +TopteamCOD2_spectator=TopteamCOD2_spectator +TopteamCOD2_targetteam=TopteamCOD2_targetteam +TopteamCOD4_allies=TopteamCOD4_allies +TopteamCOD4_axis=TopteamCOD4_axis +TopteamCOD4_playerteam=TopteamCOD4_playerteam +TopteamCOD4_targetteam=TopteamCOD4_targetteam +TopTeamKills=TopTeamKills +TopTeamKillStreak=TopTeamKillStreak +TopTeamLosses=TopTeamLosses +TopteamMOHAA_allies=TopteamMOHAA_allies +TopteamMOHAA_axis=TopteamMOHAA_axis +TopteamMOHAA_PlayerTeam=TopteamMOHAA_PlayerTeam +TopteamMOHAA_TargetTeam=TopteamMOHAA_TargetTeam +TopteamQUAKEWARS_=TopteamQUAKEWARS_ +TopteamQUAKEWARS_gdf=TopteamQUAKEWARS_gdf +TopteamQUAKEWARS_statsgenworldteam=TopteamQUAKEWARS_statsgenworldteam +TopteamQUAKEWARS_strogg=TopteamQUAKEWARS_strogg +TopTeamWins=TopTeamWins +TopteamWOLFENSTEIN_1=TopteamWOLFENSTEIN_1 +TopteamWOLFENSTEIN_2=TopteamWOLFENSTEIN_2 +TopteamWOLFENSTEIN_3=TopteamWOLFENSTEIN_3 +TopTimePlayed=TopTimePlayed +TopweaponCOD1_30cal_tank_mp=TopweaponCOD1_30cal_tank_mp +TopweaponCOD1_50cal_tank_mp=TopweaponCOD1_50cal_tank_mp +TopweaponCOD1_bar_mp=TopweaponCOD1_bar_mp +TopweaponCOD1_bar_slow_mp=TopweaponCOD1_bar_slow_mp +TopweaponCOD1_BASH=TopweaponCOD1_BASH +TopweaponCOD1_bazooka_mp=TopweaponCOD1_bazooka_mp +TopweaponCOD1_binoculars_artillery_mp=TopweaponCOD1_binoculars_artillery_mp +TopweaponCOD1_binoculars_mp=TopweaponCOD1_binoculars_mp +TopweaponCOD1_bren_mp=TopweaponCOD1_bren_mp +TopweaponCOD1_colt_mp=TopweaponCOD1_colt_mp +TopweaponCOD1_dp28_mp=TopweaponCOD1_dp28_mp +TopweaponCOD1_elefant_turret_mp=TopweaponCOD1_elefant_turret_mp +TopweaponCOD1_enfield_mp=TopweaponCOD1_enfield_mp +TopweaponCOD1_fg42_mp=TopweaponCOD1_fg42_mp +TopweaponCOD1_fg42_semi_mp=TopweaponCOD1_fg42_semi_mp +TopweaponCOD1_flak88_turret_mp=TopweaponCOD1_flak88_turret_mp +TopweaponCOD1_flamethrower_mp=TopweaponCOD1_flamethrower_mp +TopweaponCOD1_fraggrenade_mp=TopweaponCOD1_fraggrenade_mp +TopweaponCOD1_gewehr43_mp=TopweaponCOD1_gewehr43_mp +TopweaponCOD1_kar98k_mp=TopweaponCOD1_kar98k_mp +TopweaponCOD1_kar98k_sniper_mp=TopweaponCOD1_kar98k_sniper_mp +TopweaponCOD1_luger_mp=TopweaponCOD1_luger_mp +TopweaponCOD1_m1carbine_gfm_mp=TopweaponCOD1_m1carbine_gfm_mp +TopweaponCOD1_m1carbine_mp=TopweaponCOD1_m1carbine_mp +TopweaponCOD1_m1garand_mp=TopweaponCOD1_m1garand_mp +TopweaponCOD1_medic_m1carbine_mp=TopweaponCOD1_medic_m1carbine_mp +TopweaponCOD1_mg30cal_mp=TopweaponCOD1_mg30cal_mp +TopweaponCOD1_mg34_mp=TopweaponCOD1_mg34_mp +TopweaponCOD1_mg34_tank_mp=TopweaponCOD1_mg34_tank_mp +TopweaponCOD1_mg42_bipod_duck_mp=TopweaponCOD1_mg42_bipod_duck_mp +TopweaponCOD1_mg42_bipod_prone_mp=TopweaponCOD1_mg42_bipod_prone_mp +TopweaponCOD1_mg42_bipod_stand_mp=TopweaponCOD1_mg42_bipod_stand_mp +TopweaponCOD1_mg42_mp=TopweaponCOD1_mg42_mp +TopweaponCOD1_mg42_turret_mp=TopweaponCOD1_mg42_turret_mp +TopweaponCOD1_mk1britishfrag_mp=TopweaponCOD1_mk1britishfrag_mp +TopweaponCOD1_MOD_CRUSH_JEEP=TopweaponCOD1_MOD_CRUSH_JEEP +TopweaponCOD1_MOD_EXPLOSIVE=TopweaponCOD1_MOD_EXPLOSIVE +TopweaponCOD1_MOD_FALLING=TopweaponCOD1_MOD_FALLING +TopweaponCOD1_MOD_FLAME=TopweaponCOD1_MOD_FLAME +TopweaponCOD1_MOD_SUICIDE=TopweaponCOD1_MOD_SUICIDE +TopweaponCOD1_MOD_TRIGGER_HURT=TopweaponCOD1_MOD_TRIGGER_HURT +TopweaponCOD1_MOD_WATER=TopweaponCOD1_MOD_WATER +TopweaponCOD1_mosin_nagant_mp=TopweaponCOD1_mosin_nagant_mp +TopweaponCOD1_mosin_nagant_sniper_mp=TopweaponCOD1_mosin_nagant_sniper_mp +TopweaponCOD1_mp40_mp=TopweaponCOD1_mp40_mp +TopweaponCOD1_mp44_mp=TopweaponCOD1_mp44_mp +TopweaponCOD1_mp44_semi_mp=TopweaponCOD1_mp44_semi_mp +TopweaponCOD1_pak40_turret_mp=TopweaponCOD1_pak40_turret_mp +TopweaponCOD1_panther_turret_mp=TopweaponCOD1_panther_turret_mp +TopweaponCOD1_panzerfaust_mp=TopweaponCOD1_panzerfaust_mp +TopweaponCOD1_panzeriv_turret_mp=TopweaponCOD1_panzeriv_turret_mp +TopweaponCOD1_panzerschreck_mp=TopweaponCOD1_panzerschreck_mp +TopweaponCOD1_ppsh_mp=TopweaponCOD1_ppsh_mp +TopweaponCOD1_ppsh_semi_mp=TopweaponCOD1_ppsh_semi_mp +TopweaponCOD1_ptrs41_antitank_rifle_mp=TopweaponCOD1_ptrs41_antitank_rifle_mp +TopweaponCOD1_rgd-33russianfrag_mp=TopweaponCOD1_rgd-33russianfrag_mp +TopweaponCOD1_satchelcharge_mp=TopweaponCOD1_satchelcharge_mp +TopweaponCOD1_sg43_tank_mp=TopweaponCOD1_sg43_tank_mp +TopweaponCOD1_sg43_turret_mp=TopweaponCOD1_sg43_turret_mp +TopweaponCOD1_sherman_turret_mp=TopweaponCOD1_sherman_turret_mp +TopweaponCOD1_smokegrenade_mp=TopweaponCOD1_smokegrenade_mp +TopweaponCOD1_springfield_mp=TopweaponCOD1_springfield_mp +TopweaponCOD1_sten_mp=TopweaponCOD1_sten_mp +TopweaponCOD1_sten_silenced_mp=TopweaponCOD1_sten_silenced_mp +TopweaponCOD1_stielhandgranate_mp=TopweaponCOD1_stielhandgranate_mp +TopweaponCOD1_su152_turret_mp=TopweaponCOD1_su152_turret_mp +TopweaponCOD1_svt40_mp=TopweaponCOD1_svt40_mp +TopweaponCOD1_t34_turret_mp=TopweaponCOD1_t34_turret_mp +TopweaponCOD1_thompson_mp=TopweaponCOD1_thompson_mp +TopweaponCOD1_thompson_semi_mp=TopweaponCOD1_thompson_semi_mp +TopweaponCOD1_tt33_mp=TopweaponCOD1_tt33_mp +TopweaponCOD1_webley_mp=TopweaponCOD1_webley_mp +TopweaponCOD2_30cal_prone_mp=TopweaponCOD2_30cal_prone_mp +TopweaponCOD2_30cal_stand_mp=TopweaponCOD2_30cal_stand_mp +TopweaponCOD2_am_mp44_mp=TopweaponCOD2_am_mp44_mp +TopweaponCOD2_artillery_mp=TopweaponCOD2_artillery_mp +TopweaponCOD2_bar_mp=TopweaponCOD2_bar_mp +TopweaponCOD2_BASH=TopweaponCOD2_BASH +TopweaponCOD2_bren_mp=TopweaponCOD2_bren_mp +TopweaponCOD2_colt_mp=TopweaponCOD2_colt_mp +TopweaponCOD2_cook_frag_grenade_american_mp=TopweaponCOD2_cook_frag_grenade_american_mp +TopweaponCOD2_cook_frag_grenade_british_mp=TopweaponCOD2_cook_frag_grenade_british_mp +TopweaponCOD2_cook_frag_grenade_german_mp=TopweaponCOD2_cook_frag_grenade_german_mp +TopweaponCOD2_cook_frag_grenade_russian_mp=TopweaponCOD2_cook_frag_grenade_russian_mp +TopweaponCOD2_enfield_mp=TopweaponCOD2_enfield_mp +TopweaponCOD2_enfield_scope_mp=TopweaponCOD2_enfield_scope_mp +TopweaponCOD2_fire_grenade_mp=TopweaponCOD2_fire_grenade_mp +TopweaponCOD2_frag_grenade_american_mp=TopweaponCOD2_frag_grenade_american_mp +TopweaponCOD2_frag_grenade_british_mp=TopweaponCOD2_frag_grenade_british_mp +TopweaponCOD2_frag_grenade_german_mp=TopweaponCOD2_frag_grenade_german_mp +TopweaponCOD2_frag_grenade_russian_mp=TopweaponCOD2_frag_grenade_russian_mp +TopweaponCOD2_frag_type1_american_mp=TopweaponCOD2_frag_type1_american_mp +TopweaponCOD2_frag_type1_british_mp=TopweaponCOD2_frag_type1_british_mp +TopweaponCOD2_frag_type1_german_mp=TopweaponCOD2_frag_type1_german_mp +TopweaponCOD2_frag_type1_russian_mp=TopweaponCOD2_frag_type1_russian_mp +TopweaponCOD2_g43_mp=TopweaponCOD2_g43_mp +TopweaponCOD2_gas_grenade_mp=TopweaponCOD2_gas_grenade_mp +TopweaponCOD2_greasegun_mp=TopweaponCOD2_greasegun_mp +TopweaponCOD2_kar98k_mp=TopweaponCOD2_kar98k_mp +TopweaponCOD2_kar98k_sniper_mp=TopweaponCOD2_kar98k_sniper_mp +TopweaponCOD2_knife_mp=TopweaponCOD2_knife_mp +TopweaponCOD2_luger_mp=TopweaponCOD2_luger_mp +TopweaponCOD2_m1carbine_mp=TopweaponCOD2_m1carbine_mp +TopweaponCOD2_m1garand_mp=TopweaponCOD2_m1garand_mp +TopweaponCOD2_mg42_bipod_duck_mp=TopweaponCOD2_mg42_bipod_duck_mp +TopweaponCOD2_mg42_bipod_prone_mp=TopweaponCOD2_mg42_bipod_prone_mp +TopweaponCOD2_mg42_bipod_stand_mp=TopweaponCOD2_mg42_bipod_stand_mp +TopweaponCOD2_MOD_EXPLOSIVE=TopweaponCOD2_MOD_EXPLOSIVE +TopweaponCOD2_MOD_FALLING=TopweaponCOD2_MOD_FALLING +TopweaponCOD2_MOD_GRENADE_SPLASH=TopweaponCOD2_MOD_GRENADE_SPLASH +TopweaponCOD2_mod_head_shot=TopweaponCOD2_mod_head_shot +TopweaponCOD2_MOD_PISTOL_BULLET=TopweaponCOD2_MOD_PISTOL_BULLET +TopweaponCOD2_MOD_RIFLE_BULLET=TopweaponCOD2_MOD_RIFLE_BULLET +TopweaponCOD2_MOD_SUICIDE=TopweaponCOD2_MOD_SUICIDE +TopweaponCOD2_MOD_TRIGGER_HURT=TopweaponCOD2_MOD_TRIGGER_HURT +TopweaponCOD2_mosin_nagant_mp=TopweaponCOD2_mosin_nagant_mp +TopweaponCOD2_mosin_nagant_sniper_mp=TopweaponCOD2_mosin_nagant_sniper_mp +TopweaponCOD2_mp40_mp=TopweaponCOD2_mp40_mp +TopweaponCOD2_mp44_mp=TopweaponCOD2_mp44_mp +TopweaponCOD2_panzerschreck_mp=TopweaponCOD2_panzerschreck_mp +TopweaponCOD2_PPS42_mp=TopweaponCOD2_PPS42_mp +TopweaponCOD2_ppsh_mp=TopweaponCOD2_ppsh_mp +TopweaponCOD2_shotgun_mp=TopweaponCOD2_shotgun_mp +TopweaponCOD2_springfield_mp=TopweaponCOD2_springfield_mp +TopweaponCOD2_sten_mp=TopweaponCOD2_sten_mp +TopweaponCOD2_sticky_bomb_mp=TopweaponCOD2_sticky_bomb_mp +TopweaponCOD2_SVT40_mp=TopweaponCOD2_SVT40_mp +TopweaponCOD2_thompson_mp=TopweaponCOD2_thompson_mp +TopweaponCOD2_tnt_bomb_mp=TopweaponCOD2_tnt_bomb_mp +TopweaponCOD2_TT30_mp=TopweaponCOD2_TT30_mp +TopweaponCOD2_webley_mp=TopweaponCOD2_webley_mp +TopweaponCOD4_ak47_acog_mp=TopweaponCOD4_ak47_acog_mp +TopweaponCOD4_ak47_gl_mp=TopweaponCOD4_ak47_gl_mp +TopweaponCOD4_ak47_mp=TopweaponCOD4_ak47_mp +TopweaponCOD4_ak47_reflex_mp=TopweaponCOD4_ak47_reflex_mp +TopweaponCOD4_ak47_silencer_mp=TopweaponCOD4_ak47_silencer_mp +TopweaponCOD4_ak74u_acog_mp=TopweaponCOD4_ak74u_acog_mp +TopweaponCOD4_ak74u_mp=TopweaponCOD4_ak74u_mp +TopweaponCOD4_ak74u_reflex_mp=TopweaponCOD4_ak74u_reflex_mp +TopweaponCOD4_ak74u_silencer_mp=TopweaponCOD4_ak74u_silencer_mp +TopweaponCOD4_artillery_mp=TopweaponCOD4_artillery_mp +TopweaponCOD4_barrett_acog_mp=TopweaponCOD4_barrett_acog_mp +TopweaponCOD4_barrett_mp=TopweaponCOD4_barrett_mp +TopweaponCOD4_BASH=TopweaponCOD4_BASH +TopweaponCOD4_beretta_mp=TopweaponCOD4_beretta_mp +TopweaponCOD4_beretta_silencer_mp=TopweaponCOD4_beretta_silencer_mp +TopweaponCOD4_c4_mp=TopweaponCOD4_c4_mp +TopweaponCOD4_claymore_mp=TopweaponCOD4_claymore_mp +TopweaponCOD4_cobra_20mm_mp=TopweaponCOD4_cobra_20mm_mp +TopweaponCOD4_cobra_ffar_mp=TopweaponCOD4_cobra_ffar_mp +TopweaponCOD4_colt45_mp=TopweaponCOD4_colt45_mp +TopweaponCOD4_colt45_silencer_mp=TopweaponCOD4_colt45_silencer_mp +TopweaponCOD4_concussion_grenade_mp=TopweaponCOD4_concussion_grenade_mp +TopweaponCOD4_deserteagle_mp=TopweaponCOD4_deserteagle_mp +TopweaponCOD4_deserteaglegold_mp=TopweaponCOD4_deserteaglegold_mp +TopweaponCOD4_destructible_car=TopweaponCOD4_destructible_car +TopweaponCOD4_dragunov_acog_mp=TopweaponCOD4_dragunov_acog_mp +TopweaponCOD4_dragunov_mp=TopweaponCOD4_dragunov_mp +TopweaponCOD4_flash_grenade_mp=TopweaponCOD4_flash_grenade_mp +TopweaponCOD4_frag_grenade_mp=TopweaponCOD4_frag_grenade_mp +TopweaponCOD4_frag_grenade_short_mp=TopweaponCOD4_frag_grenade_short_mp +TopweaponCOD4_g36c_acog_mp=TopweaponCOD4_g36c_acog_mp +TopweaponCOD4_g36c_gl_mp=TopweaponCOD4_g36c_gl_mp +TopweaponCOD4_g36c_mp=TopweaponCOD4_g36c_mp +TopweaponCOD4_g36c_reflex_mp=TopweaponCOD4_g36c_reflex_mp +TopweaponCOD4_g36c_silencer_mp=TopweaponCOD4_g36c_silencer_mp +TopweaponCOD4_g3_acog_mp=TopweaponCOD4_g3_acog_mp +TopweaponCOD4_g3_gl_mp=TopweaponCOD4_g3_gl_mp +TopweaponCOD4_g3_mp=TopweaponCOD4_g3_mp +TopweaponCOD4_g3_reflex_mp=TopweaponCOD4_g3_reflex_mp +TopweaponCOD4_g3_silencer_mp=TopweaponCOD4_g3_silencer_mp +TopweaponCOD4_gl_ak47_mp=TopweaponCOD4_gl_ak47_mp +TopweaponCOD4_gl_g36c_mp=TopweaponCOD4_gl_g36c_mp +TopweaponCOD4_gl_g3_mp=TopweaponCOD4_gl_g3_mp +TopweaponCOD4_gl_m14_mp=TopweaponCOD4_gl_m14_mp +TopweaponCOD4_gl_m16_mp=TopweaponCOD4_gl_m16_mp +TopweaponCOD4_gl_m4_mp=TopweaponCOD4_gl_m4_mp +TopweaponCOD4_hind_ffar_mp=TopweaponCOD4_hind_ffar_mp +TopweaponCOD4_m1014_grip_mp=TopweaponCOD4_m1014_grip_mp +TopweaponCOD4_m1014_mp=TopweaponCOD4_m1014_mp +TopweaponCOD4_m1014_reflex_mp=TopweaponCOD4_m1014_reflex_mp +TopweaponCOD4_m14_acog_mp=TopweaponCOD4_m14_acog_mp +TopweaponCOD4_m14_gl_mp=TopweaponCOD4_m14_gl_mp +TopweaponCOD4_m14_mp=TopweaponCOD4_m14_mp +TopweaponCOD4_m14_reflex_mp=TopweaponCOD4_m14_reflex_mp +TopweaponCOD4_m14_silencer_mp=TopweaponCOD4_m14_silencer_mp +TopweaponCOD4_m16_acog_mp=TopweaponCOD4_m16_acog_mp +TopweaponCOD4_m16_gl_mp=TopweaponCOD4_m16_gl_mp +TopweaponCOD4_m16_mp=TopweaponCOD4_m16_mp +TopweaponCOD4_m16_reflex_mp=TopweaponCOD4_m16_reflex_mp +TopweaponCOD4_m16_silencer_mp=TopweaponCOD4_m16_silencer_mp +TopweaponCOD4_m21_acog_mp=TopweaponCOD4_m21_acog_mp +TopweaponCOD4_m21_mp=TopweaponCOD4_m21_mp +TopweaponCOD4_m40a3_acog_mp=TopweaponCOD4_m40a3_acog_mp +TopweaponCOD4_m40a3_mp=TopweaponCOD4_m40a3_mp +TopweaponCOD4_m4_acog_mp=TopweaponCOD4_m4_acog_mp +TopweaponCOD4_m4_gl_mp=TopweaponCOD4_m4_gl_mp +TopweaponCOD4_m4_mp=TopweaponCOD4_m4_mp +TopweaponCOD4_m4_reflex_mp=TopweaponCOD4_m4_reflex_mp +TopweaponCOD4_m4_silencer_mp=TopweaponCOD4_m4_silencer_mp +TopweaponCOD4_m60e4_acog_mp=TopweaponCOD4_m60e4_acog_mp +TopweaponCOD4_m60e4_grip_mp=TopweaponCOD4_m60e4_grip_mp +TopweaponCOD4_m60e4_mp=TopweaponCOD4_m60e4_mp +TopweaponCOD4_m60e4_reflex_mp=TopweaponCOD4_m60e4_reflex_mp +TopweaponCOD4_mod_explosive=TopweaponCOD4_mod_explosive +TopweaponCOD4_mod_falling=TopweaponCOD4_mod_falling +TopweaponCOD4_mod_head_shot=TopweaponCOD4_mod_head_shot +TopweaponCOD4_mod_pistol_bullet=TopweaponCOD4_mod_pistol_bullet +TopweaponCOD4_mod_rifle_bullet=TopweaponCOD4_mod_rifle_bullet +TopweaponCOD4_mod_suicide=TopweaponCOD4_mod_suicide +TopweaponCOD4_mod_trigger_hurt=TopweaponCOD4_mod_trigger_hurt +TopweaponCOD4_mp44_mp=TopweaponCOD4_mp44_mp +TopweaponCOD4_mp5_acog_mp=TopweaponCOD4_mp5_acog_mp +TopweaponCOD4_mp5_mp=TopweaponCOD4_mp5_mp +TopweaponCOD4_mp5_reflex_mp=TopweaponCOD4_mp5_reflex_mp +TopweaponCOD4_mp5_silencer_mp=TopweaponCOD4_mp5_silencer_mp +TopweaponCOD4_p90_acog_mp=TopweaponCOD4_p90_acog_mp +TopweaponCOD4_p90_mp=TopweaponCOD4_p90_mp +TopweaponCOD4_p90_reflex_mp=TopweaponCOD4_p90_reflex_mp +TopweaponCOD4_p90_silencer_mp=TopweaponCOD4_p90_silencer_mp +TopweaponCOD4_remington700_acog_mp=TopweaponCOD4_remington700_acog_mp +TopweaponCOD4_remington700_mp=TopweaponCOD4_remington700_mp +TopweaponCOD4_rpd_acog_mp=TopweaponCOD4_rpd_acog_mp +TopweaponCOD4_rpd_grip_mp=TopweaponCOD4_rpd_grip_mp +TopweaponCOD4_rpd_mp=TopweaponCOD4_rpd_mp +TopweaponCOD4_rpd_reflex_mp=TopweaponCOD4_rpd_reflex_mp +TopweaponCOD4_rpg_mp=TopweaponCOD4_rpg_mp +TopweaponCOD4_saw_acog_mp=TopweaponCOD4_saw_acog_mp +TopweaponCOD4_saw_bipod_crouch_mp=TopweaponCOD4_saw_bipod_crouch_mp +TopweaponCOD4_saw_bipod_stand_mp=TopweaponCOD4_saw_bipod_stand_mp +TopweaponCOD4_saw_grip_mp=TopweaponCOD4_saw_grip_mp +TopweaponCOD4_saw_mp=TopweaponCOD4_saw_mp +TopweaponCOD4_saw_reflex_mp=TopweaponCOD4_saw_reflex_mp +TopweaponCOD4_skorpion_acog_mp=TopweaponCOD4_skorpion_acog_mp +TopweaponCOD4_skorpion_mp=TopweaponCOD4_skorpion_mp +TopweaponCOD4_skorpion_reflex_mp=TopweaponCOD4_skorpion_reflex_mp +TopweaponCOD4_skorpion_silencer_mp=TopweaponCOD4_skorpion_silencer_mp +TopweaponCOD4_smoke_grenade_mp=TopweaponCOD4_smoke_grenade_mp +TopweaponCOD4_usp_mp=TopweaponCOD4_usp_mp +TopweaponCOD4_usp_silencer_mp=TopweaponCOD4_usp_silencer_mp +TopweaponCOD4_uzi_acog_mp=TopweaponCOD4_uzi_acog_mp +TopweaponCOD4_uzi_mp=TopweaponCOD4_uzi_mp +TopweaponCOD4_uzi_reflex_mp=TopweaponCOD4_uzi_reflex_mp +TopweaponCOD4_uzi_silencer_mp=TopweaponCOD4_uzi_silencer_mp +TopweaponCOD4_winchester1200_grip_mp=TopweaponCOD4_winchester1200_grip_mp +TopweaponCOD4_winchester1200_mp=TopweaponCOD4_winchester1200_mp +TopweaponCOD4_winchester1200_reflex_mp=TopweaponCOD4_winchester1200_reflex_mp +TopweaponMOHAA_burned_up=TopweaponMOHAA_burned_up +TopweaponMOHAA_clubbed=TopweaponMOHAA_clubbed +TopweaponMOHAA_explode=TopweaponMOHAA_explode +TopweaponMOHAA_grenade=TopweaponMOHAA_grenade +TopweaponMOHAA_mg=TopweaponMOHAA_mg +TopweaponMOHAA_mine=TopweaponMOHAA_mine +TopweaponMOHAA_pistol=TopweaponMOHAA_pistol +TopweaponMOHAA_rifle=TopweaponMOHAA_rifle +TopweaponMOHAA_shotgun=TopweaponMOHAA_shotgun +TopweaponMOHAA_smg=TopweaponMOHAA_smg +TopweaponMOHAA_sniper=TopweaponMOHAA_sniper +TopweaponMOHAA_suicide=TopweaponMOHAA_suicide +TopweaponMOHAA_telefragged=TopweaponMOHAA_telefragged +TopweaponQUAKEWARS_aa_missile=TopweaponQUAKEWARS_aa_missile +TopweaponQUAKEWARS_accurized_lacerator=TopweaponQUAKEWARS_accurized_lacerator +TopweaponQUAKEWARS_airstrike_marker=TopweaponQUAKEWARS_airstrike_marker +TopweaponQUAKEWARS_anansi=TopweaponQUAKEWARS_anansi +TopweaponQUAKEWARS_apt=TopweaponQUAKEWARS_apt +TopweaponQUAKEWARS_armadillo=TopweaponQUAKEWARS_armadillo +TopweaponQUAKEWARS_artillery=TopweaponQUAKEWARS_artillery +TopweaponQUAKEWARS_assault_rifle=TopweaponQUAKEWARS_assault_rifle +TopweaponQUAKEWARS_avt=TopweaponQUAKEWARS_avt +TopweaponQUAKEWARS_blaster=TopweaponQUAKEWARS_blaster +TopweaponQUAKEWARS_bumblebee=TopweaponQUAKEWARS_bumblebee +TopweaponQUAKEWARS_crush=TopweaponQUAKEWARS_crush +TopweaponQUAKEWARS_cyclops=TopweaponQUAKEWARS_cyclops +TopweaponQUAKEWARS_dark_matter_cannon=TopweaponQUAKEWARS_dark_matter_cannon +TopweaponQUAKEWARS_defibrillator=TopweaponQUAKEWARS_defibrillator +TopweaponQUAKEWARS_desecrator=TopweaponQUAKEWARS_desecrator +TopweaponQUAKEWARS_emp_grenade=TopweaponQUAKEWARS_emp_grenade +TopweaponQUAKEWARS_explosion=TopweaponQUAKEWARS_explosion +TopweaponQUAKEWARS_fall=TopweaponQUAKEWARS_fall +TopweaponQUAKEWARS_flyer_drone=TopweaponQUAKEWARS_flyer_drone +TopweaponQUAKEWARS_frag_grenade=TopweaponQUAKEWARS_frag_grenade +TopweaponQUAKEWARS_gdf_base_defense_turret=TopweaponQUAKEWARS_gdf_base_defense_turret +TopweaponQUAKEWARS_gpmg=TopweaponQUAKEWARS_gpmg +TopweaponQUAKEWARS_grenade_launcher=TopweaponQUAKEWARS_grenade_launcher +TopweaponQUAKEWARS_hammer=TopweaponQUAKEWARS_hammer +TopweaponQUAKEWARS_he_charge=TopweaponQUAKEWARS_he_charge +TopweaponQUAKEWARS_hog=TopweaponQUAKEWARS_hog +TopweaponQUAKEWARS_husky=TopweaponQUAKEWARS_husky +TopweaponQUAKEWARS_hyperblaster=TopweaponQUAKEWARS_hyperblaster +TopweaponQUAKEWARS_knife=TopweaponQUAKEWARS_knife +TopweaponQUAKEWARS_knife_backstab=TopweaponQUAKEWARS_knife_backstab +TopweaponQUAKEWARS_lacerator=TopweaponQUAKEWARS_lacerator +TopweaponQUAKEWARS_law=TopweaponQUAKEWARS_law +TopweaponQUAKEWARS_lightning_pistol=TopweaponQUAKEWARS_lightning_pistol +TopweaponQUAKEWARS_machine_pistol=TopweaponQUAKEWARS_machine_pistol +TopweaponQUAKEWARS_mcp=TopweaponQUAKEWARS_mcp +TopweaponQUAKEWARS_mg=TopweaponQUAKEWARS_mg +TopweaponQUAKEWARS_minigun=TopweaponQUAKEWARS_minigun +TopweaponQUAKEWARS_mining_laser=TopweaponQUAKEWARS_mining_laser +TopweaponQUAKEWARS_nailgun=TopweaponQUAKEWARS_nailgun +TopweaponQUAKEWARS_obliterator=TopweaponQUAKEWARS_obliterator +TopweaponQUAKEWARS_pistol=TopweaponQUAKEWARS_pistol +TopweaponQUAKEWARS_plasma_cannon=TopweaponQUAKEWARS_plasma_cannon +TopweaponQUAKEWARS_plasma_charge=TopweaponQUAKEWARS_plasma_charge +TopweaponQUAKEWARS_plasma_launcher=TopweaponQUAKEWARS_plasma_launcher +TopweaponQUAKEWARS_plasma_mortar=TopweaponQUAKEWARS_plasma_mortar +TopweaponQUAKEWARS_platypus=TopweaponQUAKEWARS_platypus +TopweaponQUAKEWARS_proximity_mine=TopweaponQUAKEWARS_proximity_mine +TopweaponQUAKEWARS_rail_howitzer=TopweaponQUAKEWARS_rail_howitzer +TopweaponQUAKEWARS_railgun=TopweaponQUAKEWARS_railgun +TopweaponQUAKEWARS_respawn=TopweaponQUAKEWARS_respawn +TopweaponQUAKEWARS_rocket=TopweaponQUAKEWARS_rocket +TopweaponQUAKEWARS_rocket_artillery=TopweaponQUAKEWARS_rocket_artillery +TopweaponQUAKEWARS_rocket_launcher=TopweaponQUAKEWARS_rocket_launcher +TopweaponQUAKEWARS_scoped_assault_rifle=TopweaponQUAKEWARS_scoped_assault_rifle +TopweaponQUAKEWARS_scrambler_grenade=TopweaponQUAKEWARS_scrambler_grenade +TopweaponQUAKEWARS_shotgun=TopweaponQUAKEWARS_shotgun +TopweaponQUAKEWARS_shrap_grenade=TopweaponQUAKEWARS_shrap_grenade +TopweaponQUAKEWARS_silenced_machine_pistol=TopweaponQUAKEWARS_silenced_machine_pistol +TopweaponQUAKEWARS_silenced_pistol=TopweaponQUAKEWARS_silenced_pistol +TopweaponQUAKEWARS_sniper_rifle=TopweaponQUAKEWARS_sniper_rifle +TopweaponQUAKEWARS_spikes=TopweaponQUAKEWARS_spikes +TopweaponQUAKEWARS_spikes_backstab=TopweaponQUAKEWARS_spikes_backstab +TopweaponQUAKEWARS_ssm=TopweaponQUAKEWARS_ssm +TopweaponQUAKEWARS_strocket=TopweaponQUAKEWARS_strocket +TopweaponQUAKEWARS_strogg_base_defense_turret=TopweaponQUAKEWARS_strogg_base_defense_turret +TopweaponQUAKEWARS_stroybomb=TopweaponQUAKEWARS_stroybomb +TopweaponQUAKEWARS_stroyent_tool=TopweaponQUAKEWARS_stroyent_tool +TopweaponQUAKEWARS_tank_gun=TopweaponQUAKEWARS_tank_gun +TopweaponQUAKEWARS_third_eye_camera=TopweaponQUAKEWARS_third_eye_camera +TopweaponQUAKEWARS_titan=TopweaponQUAKEWARS_titan +TopweaponQUAKEWARS_tormentor=TopweaponQUAKEWARS_tormentor +TopweaponQUAKEWARS_tripmine=TopweaponQUAKEWARS_tripmine +TopweaponQUAKEWARS_trojan=TopweaponQUAKEWARS_trojan +TopweaponQUAKEWARS_vampire=TopweaponQUAKEWARS_vampire +TopweaponQUAKEWARS_violator=TopweaponQUAKEWARS_violator +TopweaponQUAKEWARS_violator_beacon=TopweaponQUAKEWARS_violator_beacon +TopweaponWOLFENSTEIN_MOD_AIRSTRIKE=TopweaponWOLFENSTEIN_MOD_AIRSTRIKE +TopweaponWOLFENSTEIN_MOD_AKIMBO_COLT=TopweaponWOLFENSTEIN_MOD_AKIMBO_COLT +TopweaponWOLFENSTEIN_MOD_AKIMBO_LUGER=TopweaponWOLFENSTEIN_MOD_AKIMBO_LUGER +TopweaponWOLFENSTEIN_MOD_ARTILLERY=TopweaponWOLFENSTEIN_MOD_ARTILLERY +TopweaponWOLFENSTEIN_MOD_ARTY=TopweaponWOLFENSTEIN_MOD_ARTY +TopweaponWOLFENSTEIN_MOD_BROWNING=TopweaponWOLFENSTEIN_MOD_BROWNING +TopweaponWOLFENSTEIN_MOD_CARBINE=TopweaponWOLFENSTEIN_MOD_CARBINE +TopweaponWOLFENSTEIN_MOD_COLT=TopweaponWOLFENSTEIN_MOD_COLT +TopweaponWOLFENSTEIN_MOD_CRUSH=TopweaponWOLFENSTEIN_MOD_CRUSH +TopweaponWOLFENSTEIN_MOD_CRUSH_CONSTRUCTION=TopweaponWOLFENSTEIN_MOD_CRUSH_CONSTRUCTION +TopweaponWOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER=TopweaponWOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER +TopweaponWOLFENSTEIN_MOD_DYNAMITE=TopweaponWOLFENSTEIN_MOD_DYNAMITE +TopweaponWOLFENSTEIN_MOD_DYNAMITE_SPLASH=TopweaponWOLFENSTEIN_MOD_DYNAMITE_SPLASH +TopweaponWOLFENSTEIN_MOD_EXPLOSIVE=TopweaponWOLFENSTEIN_MOD_EXPLOSIVE +TopweaponWOLFENSTEIN_MOD_FALLING=TopweaponWOLFENSTEIN_MOD_FALLING +TopweaponWOLFENSTEIN_MOD_FG42=TopweaponWOLFENSTEIN_MOD_FG42 +TopweaponWOLFENSTEIN_MOD_FG42SCOPE=TopweaponWOLFENSTEIN_MOD_FG42SCOPE +TopweaponWOLFENSTEIN_MOD_FLAMETHROWER=TopweaponWOLFENSTEIN_MOD_FLAMETHROWER +TopweaponWOLFENSTEIN_MOD_GARAND=TopweaponWOLFENSTEIN_MOD_GARAND +TopweaponWOLFENSTEIN_MOD_GARAND_SCOPE=TopweaponWOLFENSTEIN_MOD_GARAND_SCOPE +TopweaponWOLFENSTEIN_MOD_GOOMBA=TopweaponWOLFENSTEIN_MOD_GOOMBA +TopweaponWOLFENSTEIN_MOD_GPG40=TopweaponWOLFENSTEIN_MOD_GPG40 +TopweaponWOLFENSTEIN_MOD_GRENADE=TopweaponWOLFENSTEIN_MOD_GRENADE +TopweaponWOLFENSTEIN_MOD_GRENADE_LAUNCHER=TopweaponWOLFENSTEIN_MOD_GRENADE_LAUNCHER +TopweaponWOLFENSTEIN_MOD_GRENADE_SPLASH=TopweaponWOLFENSTEIN_MOD_GRENADE_SPLASH +TopweaponWOLFENSTEIN_MOD_K43=TopweaponWOLFENSTEIN_MOD_K43 +TopweaponWOLFENSTEIN_MOD_K43_SCOPE=TopweaponWOLFENSTEIN_MOD_K43_SCOPE +TopweaponWOLFENSTEIN_MOD_KAR98=TopweaponWOLFENSTEIN_MOD_KAR98 +TopweaponWOLFENSTEIN_MOD_KICKED=TopweaponWOLFENSTEIN_MOD_KICKED +TopweaponWOLFENSTEIN_MOD_KNIFE=TopweaponWOLFENSTEIN_MOD_KNIFE +TopweaponWOLFENSTEIN_MOD_KNIFE_STEALTH=TopweaponWOLFENSTEIN_MOD_KNIFE_STEALTH +TopweaponWOLFENSTEIN_MOD_LANDMINE=TopweaponWOLFENSTEIN_MOD_LANDMINE +TopweaponWOLFENSTEIN_MOD_LUGER=TopweaponWOLFENSTEIN_MOD_LUGER +TopweaponWOLFENSTEIN_MOD_M7=TopweaponWOLFENSTEIN_MOD_M7 +TopweaponWOLFENSTEIN_MOD_MACHINEGUN=TopweaponWOLFENSTEIN_MOD_MACHINEGUN +TopweaponWOLFENSTEIN_MOD_MAUSER=TopweaponWOLFENSTEIN_MOD_MAUSER +TopweaponWOLFENSTEIN_MOD_MG42=TopweaponWOLFENSTEIN_MOD_MG42 +TopweaponWOLFENSTEIN_MOD_MOBILE_MG42=TopweaponWOLFENSTEIN_MOD_MOBILE_MG42 +TopweaponWOLFENSTEIN_MOD_MORTAR=TopweaponWOLFENSTEIN_MOD_MORTAR +TopweaponWOLFENSTEIN_MOD_MORTAR_SPLASH=TopweaponWOLFENSTEIN_MOD_MORTAR_SPLASH +TopweaponWOLFENSTEIN_MOD_MP40=TopweaponWOLFENSTEIN_MOD_MP40 +TopweaponWOLFENSTEIN_MOD_PANZERFAUST=TopweaponWOLFENSTEIN_MOD_PANZERFAUST +TopweaponWOLFENSTEIN_MOD_POISON=TopweaponWOLFENSTEIN_MOD_POISON +TopweaponWOLFENSTEIN_MOD_ROCKET=TopweaponWOLFENSTEIN_MOD_ROCKET +TopweaponWOLFENSTEIN_MOD_ROCKET_SPLASH=TopweaponWOLFENSTEIN_MOD_ROCKET_SPLASH +TopweaponWOLFENSTEIN_MOD_SATCHEL=TopweaponWOLFENSTEIN_MOD_SATCHEL +TopweaponWOLFENSTEIN_MOD_SILENCED_COLT=TopweaponWOLFENSTEIN_MOD_SILENCED_COLT +TopweaponWOLFENSTEIN_MOD_SILENCER=TopweaponWOLFENSTEIN_MOD_SILENCER +TopweaponWOLFENSTEIN_MOD_SNIPERRIFLE=TopweaponWOLFENSTEIN_MOD_SNIPERRIFLE +TopweaponWOLFENSTEIN_MOD_STEN=TopweaponWOLFENSTEIN_MOD_STEN +TopweaponWOLFENSTEIN_MOD_SUICIDE=TopweaponWOLFENSTEIN_MOD_SUICIDE +TopweaponWOLFENSTEIN_MOD_SWITCHTEAM=TopweaponWOLFENSTEIN_MOD_SWITCHTEAM +TopweaponWOLFENSTEIN_MOD_THOMPSON=TopweaponWOLFENSTEIN_MOD_THOMPSON +TopweaponWOLFENSTEIN_MOD_TRIGGER_HURT=TopweaponWOLFENSTEIN_MOD_TRIGGER_HURT +TopweaponWOLFENSTEIN_MOD_UNKNOWN=TopweaponWOLFENSTEIN_MOD_UNKNOWN +TopweaponWOLFENSTEIN_MOD_VENOM=TopweaponWOLFENSTEIN_MOD_VENOM +TopweaponWOLFENSTEIN_MOD_WATER=TopweaponWOLFENSTEIN_MOD_WATER +TopWeightedScore=TopWeightedScore +TopWeightedSkill=TopWeightedSkill +TopXPQUAKEWARS_battlesense=TopXPQUAKEWARS_battlesense +TopXPQUAKEWARS_covertops=TopXPQUAKEWARS_covertops +TopXPQUAKEWARS_engineer=TopXPQUAKEWARS_engineer +TopXPQUAKEWARS_fieldops=TopXPQUAKEWARS_fieldops +TopXPQUAKEWARS_medic=TopXPQUAKEWARS_medic +TopXPQUAKEWARS_soldier=TopXPQUAKEWARS_soldier +TopXPQUAKEWARS_vehicle=TopXPQUAKEWARS_vehicle +TopXPQUAKEWARS_weapon_handling=TopXPQUAKEWARS_weapon_handling +weapon_=weapon_ +weapon_COD1_30cal_tank_mp=Call Of Duty 1: 30 Caliber Tank +weapon_COD1_50cal_tank_mp=Call Of Duty 1: 50 Caliber Tank +weapon_COD1_bar_mp=Call Of Duty 1: BAR +weapon_COD1_bar_slow_mp=Call Of Duty 1: BAR (Semi Automatic) +weapon_COD1_BASH=Call Of Duty 1: Bash +weapon_COD1_bazooka_mp=Call Of Duty 1: Bazooka +weapon_COD1_BINOCULAR_BASH=Call Of Duty 1: Binocular Bash +weapon_COD1_binoculars_artillery_mp=Call Of Duty 1: Artillery Strike +weapon_COD1_binoculars_mp=Call Of Duty 1: Binoculars (Artillery) +weapon_COD1_bren_mp=Call Of Duty 1: Bren +weapon_COD1_colt_mp=Call Of Duty 1: Colt +weapon_COD1_dp28_mp=Call Of Duty 1: DP28 +weapon_COD1_elefant_turret_mp=Call Of Duty 1: Elefant Tank Turret +weapon_COD1_enfield_mp=Call Of Duty 1: Enfield +weapon_COD1_fg42_mp=Call Of Duty 1: FG42 +weapon_COD1_fg42_semi_mp=Call Of Duty 1: FG42 (semi) +weapon_COD1_flak88_turret_mp=Call Of Duty 1: FLAK88 Turret +weapon_COD1_flamethrower_mp=Call Of Duty 1: Flamethrower +weapon_COD1_fraggrenade_mp=Call Of Duty 1: American Grenade +weapon_COD1_gewehr43_mp=Call Of Duty 1: Gewehr43 +weapon_COD1_kar98k_mp=Call Of Duty 1: KAR98K +weapon_COD1_kar98k_sniper_mp=Call Of Duty 1: KAR98K Sniper +weapon_COD1_luger_mp=Call Of Duty 1: Luger +weapon_COD1_m1carbine_gfm_mp=Call Of Duty 1: GFM M1 Carbine +weapon_COD1_m1carbine_mp=Call Of Duty 1: M1 Carbine +weapon_COD1_m1garand_mp=Call Of Duty 1: M1 Garand +weapon_COD1_medic_m1carbine_mp=Call Of Duty 1: Medic M1 Carbine +weapon_COD1_mg30cal_mp=Call Of Duty 1: MG 30 Caliber +weapon_COD1_mg34_mp=Call Of Duty 1: MG34 +weapon_COD1_mg34_tank_mp=Call Of Duty 1: MG34 Tank +weapon_COD1_mg42_bipod_duck_mp=Call Of Duty 1: MG42 Bipod (duck) +weapon_COD1_mg42_bipod_prone_mp=Call Of Duty 1: MG42 Bipod (prone) +weapon_COD1_mg42_bipod_stand_mp=Call Of Duty 1: MG42 Bipod (stand) +weapon_COD1_mg42_mp=Call Of Duty 1: MG42 +weapon_COD1_mg42_turret_mp=Call Of Duty 1: MG42 Turret +weapon_COD1_mk1britishfrag_mp=Call Of Duty 1: British Grenade +weapon_COD1_MOD_CRUSH_JEEP=Call Of Duty 1: Crushed By Jeep +weapon_COD1_MOD_CRUSH_TANK=Call Of Duty 1: Crushed By Tank +weapon_COD1_MOD_EXPLOSIVE=Call Of Duty 1: Explosion +weapon_COD1_MOD_FALLING=Call Of Duty 1: Fall +weapon_COD1_MOD_FLAME=Call Of Duty 1: Burnt +weapon_COD1_MOD_SUICIDE=Call Of Duty 1: Team Swap Suicide +weapon_COD1_MOD_TRIGGER_HURT=Call Of Duty 1: Wrong Place Wrong Time +weapon_COD1_MOD_WATER=Call Of Duty 1: Drown +weapon_COD1_mosin_nagant_mp=Call Of Duty 1: Mosin Nagant +weapon_COD1_mosin_nagant_sniper_mp=Call Of Duty 1: Mosin Nagant Sniper +weapon_COD1_mp40_mp=Call Of Duty 1: MP40 +weapon_COD1_mp44_mp=Call Of Duty 1: MP44 +weapon_COD1_mp44_semi_mp=Call Of Duty 1: MP44 (Semi Automatic) +weapon_COD1_pak40_turret_mp=Call Of Duty 1: PAK40 Turret +weapon_COD1_panther_turret_mp=Call Of Duty 1: Panther Turret +weapon_COD1_panzerfaust_mp=Call Of Duty 1: Panzerfaust +weapon_COD1_panzeriv_turret_mp=Call Of Duty 1: Panzer IV Turret +weapon_COD1_panzerschreck_mp=Call Of Duty 1: Panzerschreck +weapon_COD1_ppsh_mp=Call Of Duty 1: PPSH +weapon_COD1_ppsh_semi_mp=Call Of Duty 1: PPSH (Semi Automatic) +weapon_COD1_ptrs41_antitank_rifle_mp=Call Of Duty 1: PTRS41 Anti Tank Rifle +weapon_COD1_rgd-33russianfrag_mp=Call Of Duty 1: Russian Grenade +weapon_COD1_rgd_33russianfrag_mp=weapon_COD1_rgd_33russianfrag_mp +weapon_COD1_satchelcharge_mp=Call Of Duty 1: Satchel Charge +weapon_COD1_sg43_tank_mp=Call Of Duty 1: SG43 Tank +weapon_COD1_sg43_turret_mp=Call Of Duty 1: SG43 Turret +weapon_COD1_sherman_turret_mp=Call Of Duty 1: Sherman Turret +weapon_COD1_smokegrenade_mp=Call Of Duty 1: Smoke Grenade +weapon_COD1_springfield_mp=Call Of Duty 1: Springfield +weapon_COD1_sten_mp=Call Of Duty 1: Sten +weapon_COD1_sten_silenced_mp=Call Of Duty 1: Sten (silenced) +weapon_COD1_stielhandgranate_mp=Call Of Duty 1: German Grenade +weapon_COD1_su152_turret_mp=Call Of Duty 1: SU152 Turret +weapon_COD1_svt40_mp=Call Of Duty 1: SVT40 +weapon_COD1_t34_turret_mp=Call Of Duty 1: T43 Turret +weapon_COD1_thompson_mp=Call Of Duty 1: Thompson +weapon_COD1_thompson_semi_mp=Call Of Duty 1: Thompson (Semi Automatic) +weapon_COD1_tt33_mp=Call Of Duty 1: TT33 Pistol +weapon_COD1_weapon_gfmspaten_mp=Call Of Duty 1: GFM S Paten +weapon_COD1_webley_mp=Call Of Duty 1: Webley +weapon_COD2_30cal_duck_mp=Call Of Duty 2: 30 Calibre (duck) +weapon_COD2_30cal_prone_mp=Call Of Duty 2: 30 Calibre (prone) +weapon_COD2_30cal_stand_mp=Call Of Duty 2: 30 Calibre (stand) +weapon_COD2_am_kar98k_sniper_mp=Call Of Duty 2: AM KAR98K Sniper +weapon_COD2_am_luger_mp=Call Of Duty 2: AM Luger +weapon_COD2_am_mp44_mp=Call Of Duty 2: AM MP44 +weapon_COD2_artillery_mp=Call Of Duty 2: Artillery +weapon_COD2_bar_mp=Call Of Duty 2: BAR +weapon_COD2_bar_slow_mp=Call Of Duty 2: BAR (slow) +weapon_COD2_BASH=Call Of Duty 2: Bash +weapon_COD2_bazooka_mp=Call Of Duty 2: Bazooka +weapon_COD2_binoculars_artillery_mp=Call Of Duty 2: Artillery Strike +weapon_COD2_bren_mp=Call Of Duty 2: Bren +weapon_COD2_colt_mp=Call Of Duty 2: Colt +weapon_COD2_cook_frag_grenade_american_mp=Call Of Duty 2: Grenade (American) - cook +weapon_COD2_cook_frag_grenade_british_mp=Call Of Duty 2: Grenade (British) - cook +weapon_COD2_cook_frag_grenade_german_mp=Call Of Duty 2: Grenade (German) - cook +weapon_COD2_cook_frag_grenade_russian_mp=Call Of Duty 2: Grenade (Russian) - cook +weapon_COD2_enfield_mp=Call Of Duty 2: Enfield +weapon_COD2_enfield_scope_mp=Call Of Duty 2: Enfield Scope +weapon_COD2_fire_grenade_mp=Call Of Duty 2: Fire Grenade +weapon_COD2_flamethrower_mp=Call Of Duty 2: Flamethrower +weapon_COD2_frag_grenade_american_mp=Call Of Duty 2: American Grenade +weapon_COD2_frag_grenade_british_mp=Call Of Duty 2: British Grenade +weapon_COD2_frag_grenade_german_mp=Call Of Duty 2: German Grenade +weapon_COD2_frag_grenade_russian_mp=Call Of Duty 2: Russian Grenade +weapon_COD2_frag_type1_american_mp=Call Of Duty 2: Grenade (American) +weapon_COD2_frag_type1_british_mp=Call Of Duty 2: Grenade (British) +weapon_COD2_frag_type1_german_mp=Call Of Duty 2: Grenade (German) +weapon_COD2_frag_type1_russian_mp=Call Of Duty 2: Grenade (Russian) +weapon_COD2_fraggrenade_mp=Call Of Duty 2: Grenade (American) +weapon_COD2_g43_mp=Call Of Duty 2: Gewehr 43 +weapon_COD2_gas_grenade_mp=Call Of Duty 2: Gas Grenade +weapon_COD2_greasegun_mp=Call Of Duty 2: Greasegun +weapon_COD2_kar98k_mp=Call Of Duty 2: KAR98K +weapon_COD2_kar98k_sniper_mp=Call Of Duty 2: KAR98K Sniper +weapon_COD2_knife_mp=Call Of Duty 2: Knife +weapon_COD2_luger_mp=Call Of Duty 2: Luger +weapon_COD2_m1carbine_mp=Call Of Duty 2: M1 Carbine +weapon_COD2_m1garand_mp=Call Of Duty 2: M1 Garand +weapon_COD2_mg42_bipod_duck_mp=Call Of Duty 2: MG42 Bipod (duck) +weapon_COD2_mg42_bipod_prone_mp=Call Of Duty 2: MG42 Bipod (prone) +weapon_COD2_mg42_bipod_stand_mp=Call Of Duty 2: MG42 Bipod (stand) +weapon_COD2_mk1britishfrag_mp=Call Of Duty 2: Grenade (British) +weapon_COD2_MOD_CRUSH_JEEP=Call Of Duty 2: Crushed By Jeep +weapon_COD2_MOD_EXPLOSIVE=Call Of Duty 2: Explosion +weapon_COD2_MOD_FALLING=Call Of Duty 2: Fall +weapon_COD2_MOD_FLAME=Call Of Duty 2: Burnt +weapon_COD2_MOD_GRENADE_SPLASH=Call Of Duty 2: Bleed (grenade) +weapon_COD2_mod_head_shot=Call Of Duty 2: Bleed (headshot) +weapon_COD2_MOD_PISTOL_BULLET=Call Of Duty 2: Bleed (pistol) +weapon_COD2_MOD_PROJECTILE_SPLASH=Call Of Duty 2: Bleed (projectile) +weapon_COD2_MOD_RIFLE_BULLET=Call Of Duty 2: Bleed (rifle) +weapon_COD2_MOD_SUICIDE=Call Of Duty 2: Team Swap Suicide +weapon_COD2_MOD_TRIGGER_HURT=Call Of Duty 2: Wrong Place Wrong Time +weapon_COD2_MOD_WATER=Call Of Duty 2: Drowned +weapon_COD2_mortar_cannon_walk_mp=Call Of Duty 2: Mortar Cannon +weapon_COD2_mosin_nagant_mp=Call Of Duty 2: Mosin Nagant +weapon_COD2_mosin_nagant_sniper_mp=Call Of Duty 2: Mosin Nagant Sniper +weapon_COD2_mp40_mp=Call Of Duty 2: MP40 +weapon_COD2_mp44_mp=Call Of Duty 2: MP44 +weapon_COD2_panzerfaust_mp=weapon_COD2_panzerfaust_mp +weapon_COD2_panzerschreck_mp=Call Of Duty 2: Panzerschreck +weapon_COD2_PPS42_mp=Call Of Duty 2: PPS42 +weapon_COD2_ppsh_mp=Call Of Duty 2: PPSH +weapon_COD2_rgd-33russianfrag_mp=Call Of Duty 2: Grenade (Russian) +weapon_COD2_satchelcharge_mp=Call Of Duty 2: Satchel Charge +weapon_COD2_shotgun_mp=Call Of Duty 2: Shotgun +weapon_COD2_springfield_mp=Call Of Duty 2: Springfield +weapon_COD2_sten_mp=Call Of Duty 2: Sten +weapon_COD2_sten_silenced_mp=COD2_sten_silenced_mp +weapon_COD2_sticky_bomb_mp=Call Of Duty 2: Sticky Bomb +weapon_COD2_stielhandgranate_mp=weapon_COD2_stielhandgranate_mp +weapon_COD2_SVT40_mp=Call Of Duty 2: SVT40 +weapon_COD2_thompson_mp=Call Of Duty 2: Thompson +weapon_COD2_tnt_bomb_mp=Call Of Duty 2: TNT +weapon_COD2_TT30_mp=Call Of Duty 2: TT30 Pistol +weapon_COD2_tt33_mp=weapon_COD2_tt33_mp +weapon_COD2_webley_mp=Call Of Duty 2: Webley +weapon_COD4_ak47_acog_mp=Call Of Duty 4: AK47 (ACOG) +weapon_COD4_ak47_gl_mp=Call Of Duty 4: AK47 (GL) +weapon_COD4_ak47_mp=Call Of Duty 4: AK47 +weapon_COD4_ak47_reflex_mp=Call Of Duty 4: AK47 (reflex) +weapon_COD4_ak47_silencer_mp=Call Of Duty 4: AK47 (silenced) +weapon_COD4_ak74u_acog_mp=Call Of Duty 4: AK74U (acog) +weapon_COD4_ak74u_mp=Call Of Duty 4: AK74U +weapon_COD4_ak74u_reflex_mp=Call Of Duty 4: AK74U (reflex) +weapon_COD4_ak74u_silencer_mp=Call Of Duty 4: AK74U (silenced) +weapon_COD4_artillery_mp=Call Of Duty 4: Artillery +weapon_COD4_barrett_acog_mp=Call Of Duty 4: Barrett (acog) +weapon_COD4_barrett_mp=Call Of Duty 4: Barrett +weapon_COD4_BASH=Call Of Duty 4: Knife +weapon_COD4_beretta_mp=Call Of Duty 4: Beretta +weapon_COD4_beretta_silencer_mp=Call Of Duty 4: Beretta (silenced) +weapon_COD4_c4_mp=Call Of Duty 4: C4 +weapon_COD4_claymore_mp=Call Of Duty 4: Claymore +weapon_COD4_cobra_20mm_mp=Call Of Duty 4: Cobra 20mm +weapon_COD4_cobra_ffar_mp=Call Of Duty 4: Cobra FFAR +weapon_COD4_colt45_mp=Call Of Duty 4: Colt 45 +weapon_COD4_colt45_silencer_mp=Call Of Duty 4: Colt 45 (silenced) +weapon_COD4_concussion_grenade_mp=Call Of Duty 4: Concussion Grenade +weapon_COD4_deserteagle_mp=Call Of Duty 4: Desert Eagle +weapon_COD4_deserteaglegold_mp=Call Of Duty 4: Desert Eagle - Gold +weapon_COD4_destructible_car=Call Of Duty 4: Destructible Car +weapon_COD4_dragunov_acog_mp=Call Of Duty 4: Dragunov (acog) +weapon_COD4_dragunov_mp=Call Of Duty 4: Dragunov +weapon_COD4_flash_grenade_mp=Call Of Duty 4: Flash Grenade +weapon_COD4_frag_grenade_mp=Call Of Duty 4: Frag Grenade +weapon_COD4_frag_grenade_short_mp=Call Of Duty 4: Frag Grenade (short) +weapon_COD4_g36c_acog_mp=Call Of Duty 4: G36C (acog) +weapon_COD4_g36c_gl_mp=Call Of Duty 4: G36C (GL) +weapon_COD4_g36c_mp=Call Of Duty 4: G36C +weapon_COD4_g36c_reflex_mp=Call Of Duty 4: G36C (reflex) +weapon_COD4_g36c_silencer_mp=Call Of Duty 4: G36C (silenced) +weapon_COD4_g3_acog_mp=Call Of Duty 4: G3 (ACOG) +weapon_COD4_g3_gl_mp=Call Of Duty 4: G3 (GL) +weapon_COD4_g3_mp=Call Of Duty 4: G3 +weapon_COD4_g3_reflex_mp=Call Of Duty 4: G3 (reflex) +weapon_COD4_g3_silencer_mp=Call Of Duty 4: G3 (silenced) +weapon_COD4_gl_ak47_mp=Call Of Duty 4: GL AK47 +weapon_COD4_gl_g36c_mp=Call Of Duty 4: GL G36C +weapon_COD4_gl_g3_mp=Call Of Duty 4: GL G3 +weapon_COD4_gl_m14_mp=Call Of Duty 4: GL M14 +weapon_COD4_gl_m16_mp=Call Of Duty 4: GL M16 +weapon_COD4_gl_m4_mp=Call Of Duty 4: GL M4 +weapon_COD4_hind_ffar_mp=Call Of Duty 4: HIND FFAR +weapon_COD4_m1014_grip_mp=Call Of Duty 4: M1014 (grip) +weapon_COD4_m1014_mp=Call Of Duty 4: M1014 +weapon_COD4_m1014_reflex_mp=Call Of Duty 4: M1014 (reflex) +weapon_COD4_m14_acog_mp=Call Of Duty 4: M14 (acog) +weapon_COD4_m14_gl_mp=Call Of Duty 4: M14 (GL) +weapon_COD4_m14_mp=Call Of Duty 4: M14 +weapon_COD4_m14_reflex_mp=Call Of Duty 4: M14 (reflex) +weapon_COD4_m14_silencer_mp=Call Of Duty 4: M14 (silenced) +weapon_COD4_m16_acog_mp=Call Of Duty 4: M16 (ACOG) +weapon_COD4_m16_gl_mp=Call Of Duty 4: M16 (GL) +weapon_COD4_m16_mp=Call Of Duty 4: M16 +weapon_COD4_m16_reflex_mp=Call Of Duty 4: M16 (reflex) +weapon_COD4_m16_silencer_mp=Call Of Duty 4: M16 (silenced) +weapon_COD4_m21_acog_mp=Call Of Duty 4: M21 (ACOG) +weapon_COD4_m21_mp=Call Of Duty 4: M21 +weapon_COD4_m40a3_acog_mp=Call Of Duty 4: M40A3 (acog) +weapon_COD4_m40a3_mp=Call Of Duty 4: M40A3 +weapon_COD4_m4_acog_mp=Call Of Duty 4: M4 (ACOG) +weapon_COD4_m4_gl_mp=Call Of Duty 4: M4 (GL) +weapon_COD4_m4_mp=Call Of Duty 4: M4 +weapon_COD4_m4_reflex_mp=Call Of Duty 4: M4 (reflex) +weapon_COD4_m4_silencer_mp=Call Of Duty 4: M4 (silenced) +weapon_COD4_m60e4_acog_mp=Call Of Duty 4: M60E4 (ACOG) +weapon_COD4_m60e4_grip_mp=Call Of Duty 4: M60E4 (GRIP) +weapon_COD4_m60e4_mp=Call Of Duty 4: M60E4 +weapon_COD4_m60e4_reflex_mp=Call Of Duty 4: M60E4 (reflex) +weapon_COD4_mod_explosive=Call Of Duty 4: Explosive +weapon_COD4_mod_falling=Call Of Duty 4: Fall +weapon_COD4_mod_head_shot=Call Of Duty 4: Head Shot +weapon_COD4_mod_pistol_bullet=Call Of Duty 4: Pistol Bullet +weapon_COD4_mod_rifle_bullet=Call Of Duty 4: Rifle Bullet +weapon_COD4_mod_suicide=Call Of Duty 4: Team Swap Suicide +weapon_COD4_mod_trigger_hurt=Call Of Duty 4: Wrong Place Wrong Time +weapon_COD4_mp44_mp=Call Of Duty 4: MP44 +weapon_COD4_mp5_acog_mp=Call Of Duty 4: MP5 (ACOG) +weapon_COD4_mp5_mp=Call Of Duty 4: MP5 +weapon_COD4_mp5_reflex_mp=Call Of Duty 4: MP5 (reflex) +weapon_COD4_mp5_silencer_mp=Call Of Duty 4: MP5 (silenced) +weapon_COD4_p90_acog_mp=Call Of Duty 4: P90 (acog) +weapon_COD4_p90_mp=Call Of Duty 4: P90 +weapon_COD4_p90_reflex_mp=Call Of Duty 4: P90 (reflex) +weapon_COD4_p90_silencer_mp=Call Of Duty 4: P90 (silenced) +weapon_COD4_remington700_acog_mp=Call Of Duty 4: Remington 700 (acog) +weapon_COD4_remington700_mp=Call Of Duty 4: Remington 700 +weapon_COD4_rpd_acog_mp=Call Of Duty 4: RPD (ACOG) +weapon_COD4_rpd_grip_mp=Call Of Duty 4: RPD (GRIP) +weapon_COD4_rpd_mp=Call Of Duty 4: RPD +weapon_COD4_rpd_reflex_mp=Call Of Duty 4: RPD (reflex) +weapon_COD4_rpg_mp=Call Of Duty 4: RPG +weapon_COD4_saw_acog_mp=Call Of Duty 4: SAW (ACOG) +weapon_COD4_saw_bipod_crouch_mp=Call Of Duty 4: SAW - Bipod (crouch) +weapon_COD4_saw_bipod_stand_mp=Call Of Duty 4: SAW - Bipod (stand) +weapon_COD4_saw_grip_mp=Call Of Duty 4: SAW (GRIP) +weapon_COD4_saw_mp=Call Of Duty 4: SAW +weapon_COD4_saw_reflex_mp=Call Of Duty 4: SAW (reflex) +weapon_COD4_skorpion_acog_mp=Call Of Duty 4: Skorpian (ACOG) +weapon_COD4_skorpion_mp=Call Of Duty 4: Skorpian +weapon_COD4_skorpion_reflex_mp=Call Of Duty 4: Skorpian (reflex) +weapon_COD4_skorpion_silencer_mp=Call Of Duty 4: Skorpian (silenced) +weapon_COD4_smoke_grenade_mp=Call Of Duty 4: Smoke Grenade +weapon_COD4_usp_mp=Call Of Duty 4: USP +weapon_COD4_usp_silencer_mp=Call Of Duty 4: USP (silenced) +weapon_COD4_uzi_acog_mp=Call Of Duty 4: UZI (acog) +weapon_COD4_uzi_mp=Call Of Duty 4: UZI +weapon_COD4_uzi_reflex_mp=Call Of Duty 4: UZI (reflex) +weapon_COD4_uzi_silencer_mp=Call Of Duty 4: UZI (silenced) +weapon_COD4_winchester1200_grip_mp=Call Of Duty 4: Winchester 1200 (GRIP) +weapon_COD4_winchester1200_mp=Call Of Duty 4: Winchester 1200 +weapon_COD4_winchester1200_reflex_mp=Call Of Duty 4: Winchester 1200 (reflex) +weapon_cod5_30cal_bipod_crouch_mp=Call Of Duty 5: 30 Cal (Bipod Crouch) +weapon_cod5_30cal_bipod_mp=Call Of Duty 5: 30 Cal (Bipod) +weapon_cod5_30cal_bipod_prone_mp=Call Of Duty 5: 30 Cal (Bipod Prone) +weapon_cod5_30cal_bipod_stand_mp=Call Of Duty 5: 30 Cal (Bipod Stand) +weapon_cod5_30cal_mp=Call Of Duty 5: 30 Cal +weapon_cod5_357_mp=Call Of Duty 5: 357 Magnum +weapon_cod5_357magnum_mp=Call Of Duty 5: 357 Magnum +weapon_cod5_artillery_mp=Call Of Duty 5: Artillery +weapon_cod5_bar_bipod_crouch_mp=Call Of Duty 5: BAR (Bipod Crouch) +weapon_cod5_bar_bipod_mp=Call Of Duty 5: BAR (Bipod) +weapon_cod5_bar_bipod_prone_mp=Call Of Duty 5: BAR (Bipod Prone) +weapon_cod5_bar_bipod_stand_mp=Call Of Duty 5: BAR (Bipod Stand) +weapon_cod5_bar_mp=Call Of Duty 5: BAR +weapon_cod5_bash=Call Of Duty 5: Knife +weapon_cod5_bayonet=Call Of Duty 5: Bayonet +weapon_cod5_bazooka_mp=Call Of Duty 5: Bazooka +weapon_cod5_bren_bipod_mp=Call Of Duty 5: Bren (Bipod) +weapon_cod5_bren_mp=Call Of Duty 5: Bren +weapon_cod5_briefcase_bomb_mp=Call Of Duty 5: Briefcase Bomb +weapon_cod5_colt_mp=Call Of Duty 5: Colt +weapon_cod5_destructible_car=Call Of Duty 5: Destructible Car +weapon_cod5_dog_bite_mp=Call Of Duty 5: Dog Bite +weapon_cod5_doublebarreledshotgun_grip_mp=Call Of Duty 5: Double Barreled Shotgun (Grip) +weapon_cod5_doublebarreledshotgun_mp=Call Of Duty 5: Double Barreled Shotgun +weapon_cod5_doublebarreledshotgun_sawoff_mp=Call Of Duty 5: Double Barreled Shotgun (sawnoff) +weapon_cod5_dp28_bipod_crouch_mp=Call Of Duty 5: DP28 (Bipod Crouch) +weapon_cod5_dp28_bipod_mp=Call Of Duty 5: DP28 (Bipod) +weapon_cod5_dp28_bipod_prone_mp=Call Of Duty 5: DP28 (Bipod Prone) +weapon_cod5_dp28_bipod_stand_mp=Call Of Duty 5: DP28 (Bipod Stand) +weapon_cod5_dp28_mp=Call Of Duty 5: DP28 +weapon_cod5_explodable_barrel=Call Of Duty 5: Exploding Barrel +weapon_cod5_fg42_bipod_crouch_mp=Call Of Duty 5: FG42 (Bipod Crouch) +weapon_cod5_fg42_bipod_mp=Call Of Duty 5: FG42 (Bipod) +weapon_cod5_fg42_bipod_prone_mp=Call Of Duty 5: FG42 (Bipod Prone) +weapon_cod5_fg42_bipod_stand_mp=Call Of Duty 5: FG42 (Bipod Stand) +weapon_cod5_fg42_mp=Call Of Duty 5: FG42 +weapon_cod5_fg42_scoped_mp=Call Of Duty 5: FG42 (Scoped) +weapon_cod5_fg42_telescopic_mp=Call Of Duty 5: FG42 (Scoped) +weapon_cod5_frag_grenade_mp=Call Of Duty 5: American Grenade +weapon_cod5_frag_grenade_short_mp=Call Of Duty 5: American Grenade +weapon_cod5_gewehr43_aperture_mp=Call Of Duty 5: Gewehr43 (Aperture) +weapon_cod5_gewehr43_gl_mp=Call Of Duty 5: Gewehr43 (GL) +weapon_cod5_gewehr43_mp=Call Of Duty 5: Gewehr43 +weapon_cod5_gewehr43_silenced_mp=Call Of Duty 5: Gewehr43 (Silenced) +weapon_cod5_gewehr43_telescopic_mp=Call Of Duty 5: Gewehr43 (Scoped) +weapon_cod5_gl_gewehr43_mp=Call Of Duty 5: (GL) Gewehr43 +weapon_cod5_gl_kar98k_mp=Call Of Duty 5: (GL) KAR98K +weapon_cod5_gl_m1carbine_mp=Call Of Duty 5: (GL) M1 Carbine +weapon_cod5_gl_m1garand_mp=Call Of Duty 5: (GL) M1 Garand +weapon_cod5_gl_mosinrifle_mp=Call Of Duty 5: (GL) Mosin Nagant +weapon_cod5_gl_springfield_mp=Call Of Duty 5: (GL) Springfield +weapon_cod5_gl_type99rifle_mp=Call Of Duty 5: (GL) Type 99 Rifle +weapon_cod5_kar98k_bayonet_mp=Call Of Duty 5: KAR98K (Bayonet) +weapon_cod5_kar98k_gl_mp=Call Of Duty 5: KAR98K (GL) +weapon_cod5_kar98k_mp=Call Of Duty 5: KAR98K +weapon_cod5_kar98k_scoped_mp=Call Of Duty 5: KAR98K (Scoped) +weapon_cod5_lee_enfield_bayonet_mp=Call Of Duty 5: Lee Enfield (Bayonet) +weapon_cod5_lee_enfield_mp=Call Of Duty 5: Lee Enfield +weapon_cod5_lee_enfield_scoped_mp=Call Of Duty 5: Lee Enfield (Scoped) +weapon_cod5_m1carbine_aperture_mp=Call Of Duty 5: M1 Carbine (Aperture) +weapon_cod5_m1carbine_bayonet_mp=Call Of Duty 5: M1 Carbine (Bayonet) +weapon_cod5_m1carbine_bigammo_mp=Call Of Duty 5: M1 Carbine (Big Ammo) +weapon_cod5_m1carbine_flash_mp=Call Of Duty 5: M1 Carbine (Flash) +weapon_cod5_m1carbine_gl_mp=Call Of Duty 5: M1 Carbine (GL) +weapon_cod5_m1carbine_mp=Call Of Duty 5: M1 Carbine +weapon_cod5_m1garand_bayonet_mp=Call Of Duty 5: M1 Garand (Bayonet) +weapon_cod5_m1garand_flash_mp=Call Of Duty 5: M1 Garand (Flash) +weapon_cod5_m1garand_gl_mp=Call Of Duty 5: M1 Garand (GL) +weapon_cod5_m1garand_mp=Call Of Duty 5: M1 Garand +weapon_cod5_m1garand_scoped_mp=Call Of Duty 5: M1 Garand (Scoped) +weapon_cod5_m2_flamethrower_mp=Call Of Duty 5: M2 Flamethrower +weapon_cod5_m8_white_smoke_mp=Call Of Duty 5: M8 (White Smoke) +weapon_cod5_mg42_bipod_crouch_mp=Call Of Duty 5: MG42 (Bipod Crouch) +weapon_cod5_mg42_bipod_mp=Call Of Duty 5: MG42 (Bipod) +weapon_cod5_mg42_bipod_prone_mp=Call Of Duty 5: MG42 (Bipod Prone) +weapon_cod5_mg42_bipod_stand_mp=Call Of Duty 5: MG42 (Bipod Stand) +weapon_cod5_mg42_mp=Call Of Duty 5: MG42 +weapon_cod5_mine_bouncing_betty_mp=Call Of Duty 5: Bouncing Betty +weapon_cod5_mod_burned=Call Of Duty 5: Burned To Death +weapon_cod5_mod_explosive=Call Of Duty 5: Explosion +weapon_cod5_mod_falling=Call Of Duty 5: Fall +weapon_cod5_mod_suicide=Call Of Duty 5: Team Swap Suicide +weapon_cod5_mod_trigger_hurt=Call Of Duty 5: Wrong Place Wrong Time +weapon_cod5_molotov_mp=Call Of Duty 5: Molotov +weapon_cod5_mosinrifle_bayonet_mp=Call Of Duty 5: Mosin (Bayonet) +weapon_cod5_mosinrifle_gl_mp=Call Of Duty 5: Mosin (Grenade) +weapon_cod5_mosinrifle_mp=Call Of Duty 5: Mosin +weapon_cod5_mosinrifle_scoped_mp=Call Of Duty 5: Mosin (Scoped) +weapon_cod5_mp40_aperture_mp=Call Of Duty 5: MP40 (Aperture) +weapon_cod5_mp40_bigammo_mp=Call Of Duty 5: MP40 (Big Ammo) +weapon_cod5_mp40_mp=Call Of Duty 5: MP40 +weapon_cod5_mp40_silenced_mp=Call Of Duty 5: MP40 (Silenced) +weapon_cod5_nambu_mp=Call Of Duty 5: Nambu +weapon_cod5_panzer4_gunner_front_mp=Call Of Duty 5: Panzer 4 (Gunner Front) +weapon_cod5_panzer4_gunner_mp=Call Of Duty 5: Panzer 4 (Gunner) +weapon_cod5_panzer4_mp_explosion_mp=Call Of Duty 5: Panzer 4 (Explosion) +weapon_cod5_panzer4_turret_mp=Call Of Duty 5: Panzer 4 (Turret) +weapon_cod5_ppsh_aperture_mp=Call Of Duty 5: PPSH (Aperture) +weapon_cod5_ppsh_bigammo_mp=Call Of Duty 5: PPSH (Big Ammo) +weapon_cod5_ppsh_mp=Call Of Duty 5: PPSH +weapon_cod5_ptrs41_mp=Call Of Duty 5: PTRS 41 +weapon_cod5_satchel_charge_mp=Call Of Duty 5: Satchel Charge +weapon_cod5_shotgun_bayonet_mp=Call Of Duty 5: Shotgun (Bayonet) +weapon_cod5_shotgun_grip_mp=Call Of Duty 5: Shotgun (Grip) +weapon_cod5_shotgun_mp=Call Of Duty 5: Shotgun +weapon_cod5_signal_flare_mp=Call Of Duty 5: Signal Flare +weapon_cod5_springfield_bayonet_mp=Call Of Duty 5: Springfield (Bayonet) +weapon_cod5_springfield_gl_mp=Call Of Duty 5: Springfield (GL) +weapon_cod5_springfield_mp=Call Of Duty 5: Springfield +weapon_cod5_springfield_scoped_mp=Call Of Duty 5: Springfield (Scoped) +weapon_cod5_sten_mp=Call Of Duty 5: Sten +weapon_cod5_sten_silenced_mp=Call Of Duty 5: Sten (Silenced) +weapon_cod5_stg44_aperture_mp=Call Of Duty 5: STG44 (Aperture) +weapon_cod5_stg44_flash_mp=Call Of Duty 5: STG44 (Flash) +weapon_cod5_stg44_mp=Call Of Duty 5: STG44 +weapon_cod5_stg44_telescopic_mp=Call Of Duty 5: STG44 (Scoped) +weapon_cod5_sticky_grenade_mp=Call Of Duty 5: Sticky Grenade +weapon_cod5_svt40_aperture_mp=Call Of Duty 5: SVT40 (Aperture) +weapon_cod5_svt40_flash_mp=Call Of Duty 5: SVT40 (Flash) +weapon_cod5_svt40_mp=Call Of Duty 5: SVT40 +weapon_cod5_svt40_telescopic_mp=Call Of Duty 5: SVT40 (Scoped) +weapon_cod5_t34_gunner_front_mp=Call Of Duty 5: T34 (Gunner Front) +weapon_cod5_t34_gunner_mp=Call Of Duty 5: T34 (Gunner) +weapon_cod5_t34_mp_explosion_mp=Call Of Duty 5: T34 (Explosion) +weapon_cod5_t34_turret_mp=Call Of Duty 5: T34 (Turret) +weapon_cod5_tabun_gas_mp=Call Of Duty 5: Tabun Gas +weapon_cod5_thompson_aperture_mp=Call Of Duty 5: Thompson (Aperture) +weapon_cod5_thompson_bigammo_mp=Call Of Duty 5: Thompson (Big Ammo) +weapon_cod5_thompson_mp=Call Of Duty 5: Thompson +weapon_cod5_thompson_silenced_mp=Call Of Duty 5: Thompson (Silenced) +weapon_cod5_tokarev_mp=Call Of Duty 5: Tokarev +weapon_cod5_type100smg_aperture_mp=Call Of Duty 5: Type 100 SMG (Aperture) +weapon_cod5_type100smg_bigammo_mp=Call Of Duty 5: Type 100 SMG (Big Ammo) +weapon_cod5_type100smg_mp=Call Of Duty 5: Type 100 SMG +weapon_cod5_type100smg_silenced_mp=Call Of Duty 5: Type 100 SMG (Silenced) +weapon_cod5_type99_lmg_bipod_crouch_mp=Call Of Duty 5: Type 99 LMG (Bipod Crouch) +weapon_cod5_type99_lmg_bipod_prone_mp=Call Of Duty 5: Type 99 LMG (Bipod Prone) +weapon_cod5_type99_lmg_bipod_stand_mp=Call Of Duty 5: Type 99 LMG (Bipod Stand) +weapon_cod5_type99lmg_bayonet_mp=Call Of Duty 5: Type 99 LMG (Bayonet) +weapon_cod5_type99lmg_bipod_mp=Call Of Duty 5: Type 99 LMG (Bipod) +weapon_cod5_type99lmg_mp=Call Of Duty 5: Type 99 LMG +weapon_cod5_type99rifle_bayonet_mp=Call Of Duty 5: Type 99 Rifle (Bayonet) +weapon_cod5_type99rifle_gl_mp=Call Of Duty 5: Type 99 Rifle (GL) +weapon_cod5_type99rifle_mp=Call Of Duty 5: Type 99 Rifle +weapon_cod5_type99rifle_scoped_mp=Call Of Duty 5: Type 99 Rifle (Scoped) +weapon_cod5_walther_mp=Call Of Duty 5: Walther +weapon_MOHAA_burned_up=MOHAA: Burned Up +weapon_MOHAA_clubbed=MOHAA: Bash +weapon_MOHAA_explode=MOHAA: Explosion +weapon_MOHAA_grenade=MOHAA: Grenade +weapon_MOHAA_mg=MOHAA: Machine Gun +weapon_MOHAA_mine=MOHAA: Mine +weapon_MOHAA_pistol=MOHAA: Pistol +weapon_MOHAA_rifle=MOHAA: Rifle +weapon_MOHAA_shotgun=MOHAA: Shotgun +weapon_MOHAA_smg=MOHAA: Sub Machine Gun +weapon_MOHAA_sniper=MOHAA: Sniper +weapon_MOHAA_suicide=MOHAA: Suicide +weapon_MOHAA_telefragged=MOHAA: Telefragged +weapon_QUAKEWARS_aa_missile=Quake Wars: AA Missile +weapon_QUAKEWARS_accurized_lacerator=Quake Wars: Lacerator (Accurised) +weapon_QUAKEWARS_airstrike_marker=Quake Wars: Airstrike Marker +weapon_QUAKEWARS_anansi=Quake Wars: Anansi +weapon_QUAKEWARS_apt=Quake Wars: APT +weapon_QUAKEWARS_armadillo=Quake Wars: Armadillo +weapon_QUAKEWARS_artillery=Quake Wars: Artillery +weapon_QUAKEWARS_assault_rifle=Quake Wars: Assault Rifle +weapon_QUAKEWARS_avt=Quake Wars: AVT +weapon_QUAKEWARS_blaster=Quake Wars: Blaster +weapon_QUAKEWARS_bumblebee=Quake Wars: Bumblebee +weapon_QUAKEWARS_crush=Quake Wars: Crushed +weapon_QUAKEWARS_cyclops=Quake Wars: Cyclops +weapon_QUAKEWARS_dark_matter_cannon=Quake Wars: Dark Matter Cannon +weapon_QUAKEWARS_defibrillator=Quake Wars: Defibrillator +weapon_QUAKEWARS_desecrator=Quake Wars: Desecrator +weapon_QUAKEWARS_emp_grenade=Quake Wars: EMP Grenade +weapon_QUAKEWARS_explosion=Quake Wars: Explosion +weapon_QUAKEWARS_fall=Quake Wars: Fall +weapon_QUAKEWARS_flyer_drone=Quake Wars: Flyer Drone +weapon_QUAKEWARS_frag_grenade=Quake Wars: Frag Grenade +weapon_QUAKEWARS_gdf_base_defense_turret=Quake Wars: GDF Base Defense Turret +weapon_QUAKEWARS_gpmg=Quake Wars: GPMG +weapon_QUAKEWARS_grenade_launcher=Quake Wars: Grenade Launcher +weapon_QUAKEWARS_hammer=Quake Wars: Hammer +weapon_QUAKEWARS_he_charge=Quake Wars: High Explosives Charge +weapon_QUAKEWARS_hog=Quake Wars: Hog +weapon_QUAKEWARS_husky=Quake Wars: Husky +weapon_QUAKEWARS_hyperblaster=Quake Wars: Hyperblaster +weapon_QUAKEWARS_knife=Quake Wars: Knife +weapon_QUAKEWARS_knife_backstab=Quake Wars: Knife (backstab) +weapon_QUAKEWARS_lacerator=Quake Wars: Lacerator +weapon_QUAKEWARS_law=Quake Wars: LAW +weapon_QUAKEWARS_lightning_pistol=Quake Wars: Lightning Pistol +weapon_QUAKEWARS_machine_pistol=Quake Wars: Machine Pistol +weapon_QUAKEWARS_mcp=Quake Wars: MCP +weapon_QUAKEWARS_mg=Quake Wars: MG +weapon_QUAKEWARS_minigun=Quake Wars: Minigun +weapon_QUAKEWARS_mining_laser=Quake Wars: Mining Laser +weapon_QUAKEWARS_nailgun=Quake Wars: Nailgun +weapon_QUAKEWARS_obliterator=Quake Wars: Obliterator +weapon_QUAKEWARS_pistol=Quake Wars: Pistol +weapon_QUAKEWARS_plasma_cannon=Quake Wars: Plasma Cannon +weapon_QUAKEWARS_plasma_charge=Quake Wars: Plasma Charge +weapon_QUAKEWARS_plasma_launcher=Quake Wars: Plasma Launcher +weapon_QUAKEWARS_plasma_mortar=Quake Wars: Plasma Mortar +weapon_QUAKEWARS_platypus=Quake Wars: Platypus +weapon_QUAKEWARS_proximity_mine=Quake Wars: Proximity Mine +weapon_QUAKEWARS_rail_howitzer=Quake Wars: Rail Howitzer +weapon_QUAKEWARS_railgun=Quake Wars: Railgun +weapon_QUAKEWARS_respawn=Quake Wars: Respawn +weapon_QUAKEWARS_rocket=Quake Wars: Rocket +weapon_QUAKEWARS_rocket_artillery=Quake Wars: Rocket Artillery +weapon_QUAKEWARS_rocket_launcher=Quake Wars: Rocket Launcher +weapon_QUAKEWARS_scoped_assault_rifle=Quake Wars: Assault Rifle (scoped) +weapon_QUAKEWARS_scrambler_grenade=Quake Wars: Scrambler Grenade +weapon_QUAKEWARS_shotgun=Quake Wars: Shotgun +weapon_QUAKEWARS_shrap_grenade=Quake Wars: Shrapnel Grenade +weapon_QUAKEWARS_silenced_machine_pistol=Quake Wars: Machine Pistol (silenced) +weapon_QUAKEWARS_silenced_pistol=Quake Wars: Pistol (silenced) +weapon_QUAKEWARS_sniper_rifle=Quake Wars: Sniper Rifle +weapon_QUAKEWARS_spikes=Quake Wars: Spikes +weapon_QUAKEWARS_spikes_backstab=Quake Wars: Spikes (backstab) +weapon_QUAKEWARS_ssm=Quake Wars: SSM +weapon_QUAKEWARS_strocket=Quake Wars: ST Rocket +weapon_QUAKEWARS_strogg_base_defense_turret=Quake Wars: Strogg Base Defense Turret +weapon_QUAKEWARS_stroybomb=Quake Wars: Stroy Bomb +weapon_QUAKEWARS_stroyent_tool=Quake Wars: Stroyent Tool +weapon_QUAKEWARS_tank_gun=Quake Wars: Tank Gun +weapon_QUAKEWARS_third_eye_camera=Quake Wars: Third Eye Camera +weapon_QUAKEWARS_titan=Quake Wars: Titan +weapon_QUAKEWARS_tormentor=Quake Wars: Tormentor +weapon_QUAKEWARS_tripmine=Quake Wars: Trip Mine +weapon_QUAKEWARS_trojan=Quake Wars: Trojan +weapon_QUAKEWARS_vampire=Quake Wars: Vampire +weapon_QUAKEWARS_violator=Quake Wars: Violator +weapon_QUAKEWARS_violator_beacon=Quake Wars: Violator Beacon +weapon_WOLFENSTEIN_MOD_AIRSTRIKE=Wolfenstein ET: Airstrike +weapon_WOLFENSTEIN_MOD_AKIMBO_COLT=Wolfenstein ET: Colt (akimbo) +weapon_WOLFENSTEIN_MOD_AKIMBO_LUGER=Wolfenstein ET: Luger (akimbo) +weapon_WOLFENSTEIN_MOD_ARTILLERY=Wolfenstein ET: Artillery 1 +weapon_WOLFENSTEIN_MOD_ARTY=Wolfenstein ET: Artillery 2 +weapon_WOLFENSTEIN_MOD_BROWNING=Wolfenstein ET: Browning +weapon_WOLFENSTEIN_MOD_CARBINE=Wolfenstein ET: Carbine +weapon_WOLFENSTEIN_MOD_COLT=Wolfenstein ET: Colt +weapon_WOLFENSTEIN_MOD_CRUSH=Wolfenstein ET: Crushed 1 +weapon_WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION=Wolfenstein ET: Crushed 2 +weapon_WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER=Wolfenstein ET: Crushed 3 +weapon_WOLFENSTEIN_MOD_DYNAMITE=Wolfenstein ET: Dynamite +weapon_WOLFENSTEIN_MOD_DYNAMITE_SPLASH=Wolfenstein ET: Dynamite Splash +weapon_WOLFENSTEIN_MOD_EXPLOSIVE=Wolfenstein ET: Explosive +weapon_WOLFENSTEIN_MOD_FALLING=Wolfenstein ET: Falling +weapon_WOLFENSTEIN_MOD_FG42=Wolfenstein ET: FG42 +weapon_WOLFENSTEIN_MOD_FG42SCOPE=Wolfenstein ET: FG42 Scoped +weapon_WOLFENSTEIN_MOD_FLAMETHROWER=Wolfenstein ET: Flamethrower +weapon_WOLFENSTEIN_MOD_GARAND=Wolfenstein ET: M1 Garand +weapon_WOLFENSTEIN_MOD_GARAND_SCOPE=Wolfenstein ET: Garand Scoped +weapon_WOLFENSTEIN_MOD_GOOMBA=Wolfenstein ET: Goomba +weapon_WOLFENSTEIN_MOD_GPG40=Wolfenstein ET: Rifle Grenade +weapon_WOLFENSTEIN_MOD_GRENADE=Wolfenstein ET: American Grenade +weapon_WOLFENSTEIN_MOD_GRENADE_LAUNCHER=Wolfenstein ET: Grenade Launcher +weapon_WOLFENSTEIN_MOD_GRENADE_SPLASH=Wolfenstein ET: Grenade Splash +weapon_WOLFENSTEIN_MOD_K43=Wolfenstein ET: K43 +weapon_WOLFENSTEIN_MOD_K43_SCOPE=Wolfenstein ET: K43 Scoped +weapon_WOLFENSTEIN_MOD_KAR98=Wolfenstein ET: KAR 98K +weapon_WOLFENSTEIN_MOD_KICKED=Wolfenstein ET: Kicked +weapon_WOLFENSTEIN_MOD_KNIFE=Wolfenstein ET: Knife +weapon_WOLFENSTEIN_MOD_KNIFE_STEALTH=Wolfenstein ET: Knife (stealth) +weapon_WOLFENSTEIN_MOD_LANDMINE=Wolfenstein ET: Landmine +weapon_WOLFENSTEIN_MOD_LUGER=Wolfenstein ET: Luger +weapon_WOLFENSTEIN_MOD_M7=Wolfenstein ET: M7 +weapon_WOLFENSTEIN_MOD_MACHINEGUN=Wolfenstein ET: Machine Gun +weapon_WOLFENSTEIN_MOD_MAUSER=Wolfenstein ET: Mauser +weapon_WOLFENSTEIN_MOD_MG42=Wolfenstein ET: MG42 +weapon_WOLFENSTEIN_MOD_MOBILE_MG42=Wolfenstein ET: Mobile MG42 +weapon_WOLFENSTEIN_MOD_MORTAR=Wolfenstein ET: Mortar +weapon_WOLFENSTEIN_MOD_MORTAR_SPLASH=Wolfenstein ET: Mortar Splash +weapon_WOLFENSTEIN_MOD_MP40=Wolfenstein ET: MP40 +weapon_WOLFENSTEIN_MOD_PANZERFAUST=Wolfenstein ET: Panzerfaust +weapon_WOLFENSTEIN_MOD_POISON=Wolfenstein ET: Poison +weapon_WOLFENSTEIN_MOD_ROCKET=Wolfenstein ET: Rocket +weapon_WOLFENSTEIN_MOD_ROCKET_SPLASH=Wolfenstein ET: Rocket Splash +weapon_WOLFENSTEIN_MOD_SATCHEL=Wolfenstein ET: Satchel Charge +weapon_WOLFENSTEIN_MOD_SILENCED_COLT=Wolfenstein ET: Colt (silenced) +weapon_WOLFENSTEIN_MOD_SILENCER=Wolfenstein ET: Silenced Pistol +weapon_WOLFENSTEIN_MOD_SNIPERRIFLE=Wolfenstein ET: Sniper Rifle +weapon_WOLFENSTEIN_MOD_STEN=Wolfenstein ET: Sten +weapon_WOLFENSTEIN_MOD_SUICIDE=Wolfenstein ET: Team Swap Suicide +weapon_WOLFENSTEIN_MOD_SWITCHTEAM=Wolfenstein ET: Switch Team +weapon_WOLFENSTEIN_MOD_THOMPSON=Wolfenstein ET: Thompson +weapon_WOLFENSTEIN_MOD_TRIGGER_HURT=Wolfenstein ET: Wrong Place Wrong Time +weapon_WOLFENSTEIN_MOD_UNKNOWN=Wolfenstein ET: Unknown Weapon +weapon_WOLFENSTEIN_MOD_VENOM=Wolfenstein ET: Venom Gun +weapon_WOLFENSTEIN_MOD_WATER=Wolfenstein ET: Drown +weapongroup_ak47=weapongroup_ak47 +weapongroup_ak74u=weapongroup_ak74u +weapongroup_bar=weapongroup_bar +weapongroup_bazooka=weapongroup_bazooka +weapongroup_bolt_action_rifle=weapongroup_bolt_action_rifle +weapongroup_bren=weapongroup_bren +weapongroup_dp28=weapongroup_dp28 +weapongroup_fast_loading_rifle=weapongroup_fast_loading_rifle +weapongroup_fg42=weapongroup_fg42 +weapongroup_flamethrower=weapongroup_flamethrower +weapongroup_g3=weapongroup_g3 +weapongroup_g36c=weapongroup_g36c +weapongroup_gewehr43=weapongroup_gewehr43 +weapongroup_grenade=weapongroup_grenade +weapongroup_helicopter=weapongroup_helicopter +weapongroup_kar98k=weapongroup_kar98k +weapongroup_landmine=weapongroup_landmine +weapongroup_large_machine_gun=weapongroup_large_machine_gun +weapongroup_lee_enfield=weapongroup_lee_enfield +weapongroup_m1014=weapongroup_m1014 +weapongroup_m14=weapongroup_m14 +weapongroup_m16=weapongroup_m16 +weapongroup_m1carbine=weapongroup_m1carbine +weapongroup_m1garand=weapongroup_m1garand +weapongroup_m4=weapongroup_m4 +weapongroup_m40a3=weapongroup_m40a3 +weapongroup_m60e4=weapongroup_m60e4 +weapongroup_machine_gun=weapongroup_machine_gun +weapongroup_mg30=weapongroup_mg30 +weapongroup_mg42=weapongroup_mg42 +weapongroup_mosin_nagant=weapongroup_mosin_nagant +weapongroup_mp40=weapongroup_mp40 +weapongroup_mp44=weapongroup_mp44 +weapongroup_mp5=weapongroup_mp5 +weapongroup_noob_tubes=weapongroup_noob_tubes +weapongroup_p90=weapongroup_p90 +weapongroup_pistol=weapongroup_pistol +weapongroup_ppsh=weapongroup_ppsh +weapongroup_rpd=weapongroup_rpd +weapongroup_satchelcharge=weapongroup_satchelcharge +weapongroup_saw=weapongroup_saw +weapongroup_shotgun=weapongroup_shotgun +weapongroup_skorpion=weapongroup_skorpion +weapongroup_sniper=weapongroup_sniper +weapongroup_springfield=weapongroup_springfield +weapongroup_sten=weapongroup_sten +weapongroup_sub_machine_guns=weapongroup_sub_machine_guns +weapongroup_svt40=weapongroup_svt40 +weapongroup_tank=weapongroup_tank +weapongroup_thompson=weapongroup_thompson +weapongroup_type100smg=weapongroup_type100smg +weapongroup_type99_rifle=weapongroup_type99_rifle +weapongroup_type99lmg=weapongroup_type99lmg +weapongroup_uzi=weapongroup_uzi +xp_QUAKEWARS_battlesense=Battle Sense +xp_QUAKEWARS_covertops=Covert Ops +xp_QUAKEWARS_engineer=Engineer +xp_QUAKEWARS_fieldops=Field Ops +xp_QUAKEWARS_medic=Medic +xp_QUAKEWARS_soldier=Soldier +xp_QUAKEWARS_vehicle=Vehicle +xp_QUAKEWARS_weapon_handling=Weapon Handling +[Images] +action_COD1_bas_attacked=bas.jpg +action_COD1_bas_breached=bas.jpg +action_COD1_bas_defend=bas.jpg +action_COD1_bas_defused=sdbd.jpg +action_COD1_bas_destroyed=bas.jpg +action_COD1_bas_planted=sdbp.jpg +action_COD1_bomb_defuse=sdbd.jpg +action_COD1_bomb_plant=sdbp.jpg +action_COD1_cnq_objective=tdm.jpg +action_COD1_ctf_assist=ctf.jpg +action_COD1_ctf_captured=ctf.jpg +action_COD1_ctf_defended=ctf.jpg +action_COD1_ctf_pickup=ctf.jpg +action_COD1_ctf_returned=ctf.jpg +action_COD1_ctf_score=ctf.jpg +action_COD1_ctf_stole=ctf.jpg +action_COD1_ctf_take=ctf.jpg +action_COD1_dom_captured=dom.jpg +action_COD1_re_capture=re.jpg +action_COD1_re_pickup=re.jpg +action_COD2_bomb_defuse=sdbd.jpg +action_COD2_bomb_plant=sdbp.jpg +action_COD2_ctf_assist=ctf.jpg +action_COD2_ctf_captured=ctf.jpg +action_COD2_ctf_defended=ctf.jpg +action_COD2_ctf_pickup=ctf.jpg +action_COD2_ctf_returned=ctf.jpg +action_COD2_ctf_take=ctf.jpg +action_COD2_heal=medic.jpg +action_COD2_hq_capture=hq.jpg +action_COD2_hq_defend=hq.jpg +action_COD2_hq_destroy=hq.jpg +action_COD2_htf_scored=ctf.jpg +action_COD2_htf_stole=ctf.jpg +action_COD2_sd_defend=sd.jpg +action_COD4_bomb_defused=sd.jpg +action_COD4_bomb_planted=sd.jpg +action_cod5_bd=cod5_action_bomb_defuse.jpg +action_cod5_bp=cod5_action_bomb_plant.jpg +action_cod5_fc=cod5_action_flag_capture.jpg +action_cod5_fr=cod5_action_flag_return.jpg +action_cod5_ft=cod5_action_flag_taken.jpg +action_cod5_rc=cod5_action_region_captured.jpg +action_cod5_rd=cod5_action_region_defended.jpg +action_MOHAA_FreezeTagCapture=freezetag.jpg +action_MOHAA_FreezeTagDrop=freezetag.jpg +action_MOHAA_FreezeTagMelt=freezetag.jpg +action_MOHAA_FreezeTagPickup=freezetag.jpg +action_MOHAA_FreezeTagPost=freezetag.jpg +action_MOHAA_FreezeTagReturn=freezetag.jpg +action_MOHAA_FreezeTagSave=freezetag.jpg +action_WOLFENSTEIN_Dynamite_Defuse=et_dynamite_defuse.gif +action_WOLFENSTEIN_Dynamite_Plant=et_dynamite_plant.gif +ammo_COD1_BASH= +ammo_COD1_binoculars_mp= +ammo_COD1_MOD_ARTILLERY= +ammo_COD1_MOD_CRUSH_JEEP= +ammo_COD1_MOD_CRUSH_TANK= +ammo_COD1_MOD_EXPLOSIVE= +ammo_COD1_MOD_FALLING= +ammo_COD1_MOD_FLAME= +ammo_COD1_MOD_GRENADE_SPLASH= +ammo_COD1_MOD_HEAD_SHOT= +ammo_COD1_MOD_PISTOL_BULLET= +ammo_COD1_MOD_PROJECTILE= +ammo_COD1_MOD_PROJECTILE_SPLASH= +ammo_COD1_MOD_RIFLE_BULLET= +ammo_COD1_MOD_SUICIDE= +ammo_COD1_MOD_WATER= +ammo_COD2_BASH= +ammo_COD2_MOD_EXPLOSIVE= +ammo_COD2_MOD_FALLING= +ammo_COD2_MOD_GRENADE_SPLASH= +ammo_COD2_MOD_HEAD_SHOT= +ammo_COD2_MOD_PISTOL_BULLET= +ammo_COD2_MOD_PROJECTILE= +ammo_COD2_MOD_PROJECTILE_SPLASH= +ammo_COD2_MOD_RIFLE_BULLET= +ammo_COD2_MOD_SUICIDE= +ammo_COD2_MOD_TRIGGER_HURT= +ammo_COD4_BASH= +ammo_COD4_MOD_EXPLOSIVE= +ammo_COD4_MOD_FALLING= +ammo_COD4_MOD_GRENADE= +ammo_COD4_MOD_GRENADE_SPLASH= +ammo_COD4_MOD_HEAD_SHOT= +ammo_COD4_MOD_IMPACT= +ammo_COD4_MOD_PISTOL_BULLET= +ammo_COD4_MOD_PROJECTILE= +ammo_COD4_MOD_PROJECTILE_SPLASH= +ammo_COD4_MOD_RIFLE_BULLET= +ammo_COD4_MOD_SUICIDE= +ammo_COD4_MOD_TRIGGER_HURT= +ammo_cod5_bash= +ammo_cod5_bayonet= +ammo_cod5_mod_bayonet= +ammo_cod5_mod_burned= +ammo_cod5_mod_crush= +ammo_cod5_mod_explosive= +ammo_cod5_mod_falling= +ammo_cod5_mod_grenade= +ammo_cod5_mod_grenade_splash= +ammo_cod5_mod_head_shot= +ammo_cod5_mod_impact= +ammo_cod5_mod_melee= +ammo_cod5_mod_pistol_bullet= +ammo_cod5_mod_projectile= +ammo_cod5_mod_projectile_splash= +ammo_cod5_mod_rifle_bullet= +ammo_cod5_mod_suicide= +ammo_cod5_mod_trigger_hurt= +ammo_cod5_mod_unknown= +ammo_MOHAA_= +ammo_WOLFENSTEIN_= +class_COD1_=soldier.jpg +class_COD1_Soldier=soldier.jpg +class_COD2_=soldier.jpg +class_COD2_Soldier=soldier.jpg +class_COD4_=cod4_soldier.jpg +class_COD4_soldier=cod4_soldier.jpg +class_cod5_= +class_cod5_soldier=cod5_class_soldier.jpg +class_MOHAA_=player.jpg +class_MOHAA_soldier=player.jpg +class_QUAKEWARS_aggressor=aggressor.png +class_QUAKEWARS_constructor=constructor.png +class_QUAKEWARS_covertops=covertops.png +class_QUAKEWARS_engineer=engineer.png +class_QUAKEWARS_fieldops=fieldops.png +class_QUAKEWARS_infiltrator=infiltrator.png +class_QUAKEWARS_medic=medic.png +class_QUAKEWARS_oppressor=oppressor.png +class_QUAKEWARS_soldier=soldier.png +class_QUAKEWARS_technician=technician.png +class_WOLFENSTEIN_= +class_WOLFENSTEIN_0=soldier.jpg +class_WOLFENSTEIN_1=medic.jpg +class_WOLFENSTEIN_2=engineer.jpg +class_WOLFENSTEIN_3=fieldops.jpg +class_WOLFENSTEIN_4=covert.jpg +class_WOLFENSTEIN_7=lieutenant.jpg +class_WOLFENSTEIN_soldier=default.jpg +gametype_COD1_actf=ctf.jpg +gametype_COD1_bas=bas.jpg +gametype_COD1_bel=bel.jpg +gametype_COD1_cnq=tdm.jpg +gametype_COD1_ctf=ctf.jpg +gametype_COD1_dm=dm.jpg +gametype_COD1_dom=dom.jpg +gametype_COD1_hq=hq.jpg +gametype_COD1_re=re.jpg +gametype_COD1_rsd=sd.jpg +gametype_COD1_sd=sd.jpg +gametype_COD1_tdm=tdm.jpg +gametype_COD2_csd=sd.jpg +gametype_COD2_ctb=ctb.jpg +gametype_COD2_ctf=ctf.jpg +gametype_COD2_ctfb=ctf.jpg +gametype_COD2_dm=dm.jpg +gametype_COD2_dom=dom.jpg +gametype_COD2_ein=einstein.jpg +gametype_COD2_esd=sd.jpg +gametype_COD2_hq=hq.jpg +gametype_COD2_hq2=hq.jpg +gametype_COD2_htf=ctf.jpg +gametype_COD2_noz=noz.jpg +gametype_COD2_sd=sd.jpg +gametype_COD2_sdr=sd.jpg +gametype_COD2_tdm=tdm.jpg +gametype_COD4_dm=cod4_gametype_dm.jpg +gametype_COD4_dom=cod4_gametype_dom.jpg +gametype_COD4_koth=cod4_gametype_koth.jpg +gametype_COD4_sab=cod4_gametype_saboteur.jpg +gametype_COD4_sd=cod4_gametype_sd.jpg +gametype_COD4_war=cod4_gametype_war.jpg +gametype_COD5_ctf=cod5_gametype_ctf.jpg +gametype_COD5_dm=cod5_gametype_dm.jpg +gametype_COD5_dom=cod5_gametype_dom.jpg +gametype_COD5_koth=cod5_gametype_hq.jpg +gametype_COD5_sab=cod5_gametype_sab.jpg +gametype_COD5_sd=cod5_gametype_sd.jpg +gametype_COD5_sur=cod5_gametype_sur.jpg +gametype_COD5_tdm=cod5_gametype_tdm.jpg +gametype_COD5_twar=cod5_gametype_twar.jpg +gametype_MOHAA_Capture-The-Flag=ctf.jpg +gametype_MOHAA_dm=dm.jpg +gametype_MOHAA_Freeze-Tag-CTF=freezetag.jpg +gametype_MOHAA_obj=sd.jpg +gametype_MOHAA_Objective-Match=sd.jpg +gametype_WOLFENSTEIN_2=et_objective.gif +gametype_WOLFENSTEIN_3=et_stopwatch.gif +gametype_WOLFENSTEIN_4=et_campaign.gif +gametype_WOLFENSTEIN_5=et_lastmanstanding.gif +gametype_WOLFENSTEIN_6= +gametype_WOLFENSTEIN_7= +location_COD1_head=head.jpg +location_COD1_helmet=head.jpg +location_COD1_left_arm_lower=leftforearm.jpg +location_COD1_left_arm_upper=leftupper.jpg +location_COD1_left_foot=leftfoot.jpg +location_COD1_left_hand=lefthand.jpg +location_COD1_left_leg_lower=leftcalf.jpg +location_COD1_left_leg_upper=leftthigh.jpg +location_COD1_neck=neck.jpg +location_COD1_none=wholebody.jpg +location_COD1_right_arm_lower=rightforearm.jpg +location_COD1_right_arm_upper=rightupper.jpg +location_COD1_right_foot=rightfoot.jpg +location_COD1_right_hand=righthand.jpg +location_COD1_right_leg_lower=rightcalf.jpg +location_COD1_right_leg_upper=rightthigh.jpg +location_COD1_torso_lower=stomach.jpg +location_COD1_torso_upper=chest.jpg +location_COD2_head=head.jpg +location_COD2_helmet=head.jpg +location_COD2_left_arm_lower=leftforearm.jpg +location_COD2_left_arm_upper=leftupper.jpg +location_COD2_left_foot=leftfoot.jpg +location_COD2_left_hand=lefthand.jpg +location_COD2_left_leg_lower=leftcalf.jpg +location_COD2_left_leg_upper=leftthigh.jpg +location_COD2_neck=neck.jpg +location_COD2_none=wholebody.jpg +location_COD2_right_arm_lower=rightforearm.jpg +location_COD2_right_arm_upper=rightupper.jpg +location_COD2_right_foot=rightfoot.jpg +location_COD2_right_hand=righthand.jpg +location_COD2_right_leg_lower=rightcalf.jpg +location_COD2_right_leg_upper=rightthigh.jpg +location_COD2_torso_lower=stomach.jpg +location_COD2_torso_upper=chest.jpg +location_COD4_head=cod4_head.jpg +location_COD4_left_arm_lower=cod4_left_forearm.jpg +location_COD4_left_arm_upper=cod4_left_bicep.jpg +location_COD4_left_foot=cod4_left_foot.jpg +location_COD4_left_hand=cod4_left_hand.jpg +location_COD4_left_leg_lower=cod4_left_calf.jpg +location_COD4_left_leg_upper=cod4_left_thigh.jpg +location_COD4_neck=cod4_neck.jpg +location_COD4_none=cod4_all_over.jpg +location_COD4_right_arm_lower=cod4_right_forearm.jpg +location_COD4_right_arm_upper=cod4_right_bicep.jpg +location_COD4_right_foot=cod4_right_foot.jpg +location_COD4_right_hand=cod4_right_hand.jpg +location_COD4_right_leg_lower=cod4_right_calf.jpg +location_COD4_right_leg_upper=cod4_right_thigh.jpg +location_COD4_torso_lower=cod4_stomach.jpg +location_COD4_torso_upper=cod4_chest.jpg +location_cod5_head=cod5_head.jpg +location_cod5_left_arm_lower=cod5_leftforearm.jpg +location_cod5_left_arm_upper=cod5_leftupper.jpg +location_cod5_left_foot=cod5_leftfoot.jpg +location_cod5_left_hand=cod5_lefthand.jpg +location_cod5_left_leg_lower=cod5_leftcalf.jpg +location_cod5_left_leg_upper=cod5_leftthigh.jpg +location_cod5_neck=cod5_neck.jpg +location_cod5_none=cod5_wholebody.jpg +location_cod5_right_arm_lower=cod5_rightforearm.jpg +location_cod5_right_arm_upper=cod5_rightupper.jpg +location_cod5_right_foot=cod5_rightfoot.jpg +location_cod5_right_hand=cod5_righthand.jpg +location_cod5_right_leg_lower=cod5_rightcalf.jpg +location_cod5_right_leg_upper=cod5_rightthigh.jpg +location_cod5_torso_lower=cod5_stomach.jpg +location_cod5_torso_upper=cod5_chest.jpg +location_MOHAA_=wholebody.jpg +location_QUAKEWARS_=soldier.png +location_QUAKEWARS_gdf=soldier.png +location_QUAKEWARS_strogg=oppressor.png +location_WOLFENSTEIN_=wholebody.jpg +map_COD1_mp_arnhem=mp_arnhem.jpg +map_COD1_mp_berlin=mp_berlin.jpg +map_COD1_mp_bocage=bocage.jpg +map_COD1_mp_brecourt=brecourt.jpg +map_COD1_mp_carentan=carentan.jpg +map_COD1_mp_cassino=mp_cassino.jpg +map_COD1_mp_chateau=chateau.jpg +map_COD1_mp_dawnville=dawnville.jpg +map_COD1_mp_foy=mp_foy.jpg +map_COD1_mp_harbor=harbor.jpg +map_COD1_mp_hurtgen=hurtgen.jpg +map_COD1_mp_hurtgen-autumn=hurtgen.jpg +map_COD1_mp_italy=mp_italy.jpg +map_COD1_mp_kharkov=mp_kharkov.jpg +map_COD1_mp_kursk=mp_kursk.jpg +map_COD1_mp_neuville=neuville.jpg +map_COD1_mp_pavlov=pavlov.jpg +map_COD1_mp_peaks= +map_COD1_mp_ponyri=mp_ponyri.jpg +map_COD1_mp_powcamp=powcamp.jpg +map_COD1_mp_railyard=railyard.jpg +map_COD1_mp_rhinevalley=mp_rhinevalley.jpg +map_COD1_mp_rocket=rocket.jpg +map_COD1_mp_ship=ship.jpg +map_COD1_mp_sicily=mp_sicily.jpg +map_COD1_mp_stalingrad=mp_stalingrad.jpg +map_COD1_mp_streets= +map_COD1_mp_tigertown= +map_COD1_mp_uo_carentan=carentan.jpg +map_COD1_mp_uo_dawnville=dawnville.jpg +map_COD1_mp_uo_depot= +map_COD1_mp_uo_harbor=harbor.jpg +map_COD1_mp_uo_hurtgen=hurtgen.jpg +map_COD1_mp_uo_powcamp=powcamp.jpg +map_COD1_mp_uo_stanjel=mp_uo_stanjel.jpg +map_COD2_mp_africorps= +map_COD2_mp_argentan_france= +map_COD2_mp_bastogne= +map_COD2_mp_belltown= +map_COD2_mp_berlin1= +map_COD2_mp_breakout=breakout.jpg +map_COD2_mp_brecourt=brecourt2.jpg +map_COD2_mp_burgundy=burgundy.jpg +map_COD2_mp_carentan=carentan2.jpg +map_COD2_mp_chateau= +map_COD2_mp_chateauday= +map_COD2_mp_cr_kasserine= +map_COD2_mp_dawnville=dawnville2.jpg +map_COD2_mp_dawnville_cl_final= +map_COD2_mp_decoy=decoy.jpg +map_COD2_mp_devils_den_beta= +map_COD2_mp_dock_assault= +map_COD2_mp_downtown=downtown.jpg +map_COD2_mp_farmhouse=beltot.jpg +map_COD2_mp_frantic2= +map_COD2_mp_gothic= +map_COD2_mp_harbor=cod2_mp_harbor.jpg +map_COD2_mp_hawk= +map_COD2_mp_highside= +map_COD2_mp_junobeach= +map_COD2_mp_kalstle_v2= +map_COD2_mp_leningrad=leningrad.jpg +map_COD2_mp_lflnchateau= +map_COD2_mp_maaloy_cod2= +map_COD2_mp_maaloy_cod2_final= +map_COD2_mp_matmata=matmata.jpg +map_COD2_mp_mazza= +map_COD2_mp_montebourg= +map_COD2_mp_otara= +map_COD2_mp_provence2= +map_COD2_mp_railyard=railyard2.jpg +map_COD2_mp_rhine=cod2_mp_rhine.jpg +map_COD2_mp_slatmata= +map_COD2_mp_stanjel= +map_COD2_mp_the_tomb= +map_COD2_mp_toujane=toujane.jpg +map_COD2_mp_trainstation=caen.jpg +map_COD2_mp_tunis= +map_COD2_mp_tunisia_dawn= +map_COD2_mp_vik1= +map_COD2_mp_villageraid= +map_COD2_mp_xfire_bay= +map_COD4_mp_backlot=cod4_mp_backlot.jpg +map_COD4_mp_bloc=cod4_mp_bloc.jpg +map_COD4_mp_bog=cod4_mp_bog.jpg +map_COD4_mp_broadcast=cod4_mp_broadcast.jpg +map_COD4_mp_carentan=cod4_mp_carentan.jpg +map_COD4_mp_cargoship=cod4_mp_cargoship.jpg +map_COD4_mp_citystreets=cod4_mp_citystreets.jpg +map_COD4_mp_convoy=cod4_mp_convoy.jpg +map_COD4_mp_countdown=cod4_mp_countdown.jpg +map_COD4_mp_crash=cod4_mp_crash.jpg +map_COD4_mp_crash_snow=cod4_crash_snow.jpg +map_COD4_mp_creek=cod4_mp_creek.jpg +map_COD4_mp_crossfire=cod4_mp_crossfire.jpg +map_COD4_mp_dusk=cod4_mp_dusk.jpg +map_COD4_mp_farm=cod4_mp_farm.jpg +map_COD4_mp_hill=cod4_mp_hill.jpg +map_COD4_mp_killhouse= +map_COD4_mp_overgrown=cod4_mp_overgrown.jpg +map_COD4_mp_pipeline=cod4_mp_pipeline.jpg +map_COD4_mp_shipment=cod4_mp_shipment.jpg +map_COD4_mp_showdown=cod4_mp_showdown.jpg +map_COD4_mp_strike=cod4_mp_strike.jpg +map_COD4_mp_vacant=cod4_mp_vacant.jpg +map_COD5_mp_airfield=cod5_map_airfield.jpg +map_COD5_mp_asylum=cod5_map_asylum.jpg +map_COD5_mp_castle=cod5_map_castle.jpg +map_COD5_mp_cliffside=cod5_map_cliffside.jpg +map_COD5_mp_courtyard=cod5_map_courtyard.jpg +map_COD5_mp_dome=cod5_map_dome.jpg +map_COD5_mp_downfall=cod5_map_downfall.jpg +map_COD5_mp_hangar=cod5_map_hangar.jpg +map_COD5_mp_kneedeep=cod5_map_kneedeep.jpg +map_COD5_mp_makin=cod5_map_makin.jpg +map_COD5_mp_makin_day=cod5_map_makin_day.jpg +map_COD5_mp_nachtfeuer=cod5_map_nachtfeuer.jpg +map_COD5_mp_outskirts=cod5_map_outskirts.jpg +map_COD5_mp_roundhouse=cod5_map_roundhouse.jpg +map_COD5_mp_seelow=cod5_map_seelow.jpg +map_COD5_mp_shrine=cod5_map_shrine.jpg +map_COD5_mp_suburban=cod5_map_suburban.jpg +map_COD5_mp_subway=cod5_map_subway.jpg +map_COD5_mp_upheaval=cod5_map_upheaval.jpg +map_COD5_mp_bgate=cod5_map_docks.jpg +map_COD5_mp_docks=cod5_map_docks.jpg +map_COD5_mp_drum=cod5_map_drum.jpg +map_COD5_mp_kwai=cod5_map_kwai.jpg +map_COD5_mp_stalingrad=cod5_map_stalingrad.jpg +map_COD5_mp_vodka=cod5_map_vodka.jpg +map_MOHAA_= +map_MOHAA_obj_team1=TheHunt.jpg +map_MOHAA_obj_team2=V2.jpg +map_MOHAA_obj_team3=OmahaBeach.jpg +map_MOHAA_obj_team4=TheBridge.jpg +map_MOHAA_stlo=stlo.jpg +map_QUAKEWARS_area22=qw_area_22.jpg +map_QUAKEWARS_ark=qw_ark.jpg +map_QUAKEWARS_canyon=qw_canyon.jpg +map_QUAKEWARS_island=qw_island.jpg +map_QUAKEWARS_outskirts=qw_outskirts.jpg +map_QUAKEWARS_quarry=qw_quarry.jpg +map_QUAKEWARS_refinery=qw_refinery.jpg +map_QUAKEWARS_salvage=qw_salvage.jpg +map_QUAKEWARS_sewer=qw_sewer.jpg +map_QUAKEWARS_slipgate=qw_slipgate.jpg +map_QUAKEWARS_valley=qw_valley.jpg +map_QUAKEWARS_volcano=qw_volcano.jpg +map_WOLFENSTEIN_baserace_beta2= +map_WOLFENSTEIN_battery=et_battery.gif +map_WOLFENSTEIN_braundorf_b3= +map_WOLFENSTEIN_ctf_multi=ctf.jpg +map_WOLFENSTEIN_dubrovnik_b1= +map_WOLFENSTEIN_dubrovnik_final= +map_WOLFENSTEIN_et_ice= +map_WOLFENSTEIN_frostbite= +map_WOLFENSTEIN_fueldump=et_fueldump.gif +map_WOLFENSTEIN_goldrush=et_goldrush.gif +map_WOLFENSTEIN_infamy= +map_WOLFENSTEIN_kungfugrip= +map_WOLFENSTEIN_mp_ameland_final= +map_WOLFENSTEIN_MP_ASSAULT=et_assault.jpg +map_WOLFENSTEIN_mp_bankraid_final= +map_WOLFENSTEIN_mp_base=et_base.jpg +map_WOLFENSTEIN_mp_beach=et_beach.jpg +map_WOLFENSTEIN_mp_bridge= +map_WOLFENSTEIN_MP_CASTLE=et_castle.jpg +map_WOLFENSTEIN_mp_castle_siege= +map_WOLFENSTEIN_mp_checkpoint= +map_WOLFENSTEIN_mp_church= +map_WOLFENSTEIN_mp_destruction=et_destruction.jpg +map_WOLFENSTEIN_mp_ice= +map_WOLFENSTEIN_mp_island= +map_WOLFENSTEIN_mp_murderhill= +map_WOLFENSTEIN_mp_resurrection= +map_WOLFENSTEIN_mp_schwalbe= +map_WOLFENSTEIN_mp_sub=et_sub.jpg +map_WOLFENSTEIN_mp_toxicity= +map_WOLFENSTEIN_mp_tram= +map_WOLFENSTEIN_mp_trenchtoast= +map_WOLFENSTEIN_MP_VILLAGE=et_village.jpg +map_WOLFENSTEIN_northpole= +map_WOLFENSTEIN_oasis=et_oasis.gif +map_WOLFENSTEIN_radar=et_radar.gif +map_WOLFENSTEIN_railgun=et_railgun.gif +map_WOLFENSTEIN_raw_b3= +map_WOLFENSTEIN_rommel_b2= +map_WOLFENSTEIN_rommel_final= +map_WOLFENSTEIN_stalingrad= +map_WOLFENSTEIN_supplydepot2= +map_WOLFENSTEIN_tc_base= +map_WOLFENSTEIN_te_frostbite= +map_WOLFENSTEIN_te_tundrab2= +map_WOLFENSTEIN_te_ufo= +map_WOLFENSTEIN_toxic_speedball= +map_WOLFENSTEIN_tundra_rush_beta= +map_WOLFENSTEIN_uboot= +map_WOLFENSTEIN_vengeance_te_b4= +team_COD1_=unknown.jpg +team_COD1_allies=allies.jpg +team_COD1_axis=axis.jpg +team_COD1_playerteam= +team_COD1_spectator=unknown.jpg +team_COD1_targetteam= +team_COD2_=unknown.jpg +team_COD2_allies=allies.jpg +team_COD2_axis=axis.jpg +team_COD2_playerteam= +team_COD2_spectator=unknown.jpg +team_COD2_targetteam= +team_COD4_allies=cod4_allies.jpg +team_COD4_axis=cod4_axis.jpg +team_COD4_playerteam= +team_COD4_targetteam= +team_cod5_= +team_COD5_allies=cod5_team_allies.jpg +team_COD5_axis=cod5_team_axis.jpg +team_COD5_playerteam=cod5_team_unknown.jpg +team_COD5_spectator= +team_COD5_targetteam=cod5_team_unknown.jpg +team_MOHAA_allies=allies.jpg +team_MOHAA_axis=axis.jpg +team_MOHAA_PlayerTeam= +team_MOHAA_TargetTeam= +team_QUAKEWARS_=soldier.png +team_QUAKEWARS_gdf=soldier.png +team_QUAKEWARS_strogg=aggressor.png +team_STATSGENWORLDTEAM= +team_WOLFENSTEIN_1=allies.jpg +team_WOLFENSTEIN_2=axis.jpg +team_WOLFENSTEIN_3=unknown.jpg +weapon_COD1_30cal_tank_mp=30cal_tank_mp.gif +weapon_COD1_50cal_tank_mp=50cal_tank_mp.gif +weapon_COD1_bar_mp=bar_mp.gif +weapon_COD1_bar_slow_mp=bar_mp.gif +weapon_COD1_BASH= +weapon_COD1_bazooka_mp=bazooka_mp.gif +weapon_COD1_binoculars_artillery_mp=binoculars_artillery_mp.gif +weapon_COD1_binoculars_mp=binoculars_artillery_mp.gif +weapon_COD1_bren_mp=bren_mp.gif +weapon_COD1_colt_mp=colt_mp.gif +weapon_COD1_dp28_mp=dp28_mp.gif +weapon_COD1_elefant_turret_mp=elefant_turret_mp.gif +weapon_COD1_enfield_mp=enfield_mp.gif +weapon_COD1_fg42_mp=fg42_mp.gif +weapon_COD1_fg42_semi_mp=fg42_mp.gif +weapon_COD1_flak88_turret_mp=flak88_turret_mp.gif +weapon_COD1_flamethrower_mp=flamethrower_mp.gif +weapon_COD1_fraggrenade_mp=fraggrenade_mp.gif +weapon_COD1_gewehr43_mp=gewehr43_mp.gif +weapon_COD1_kar98k_mp=kar98k_mp.gif +weapon_COD1_kar98k_sniper_mp=kar98k_sniper_mp.gif +weapon_COD1_luger_mp=luger_mp.gif +weapon_COD1_m1carbine_gfm_mp=m1carbine_mp.gif +weapon_COD1_m1carbine_mp=m1carbine_mp.gif +weapon_COD1_m1garand_mp=m1garand_mp.gif +weapon_COD1_medic_m1carbine_mp=m1carbine_mp.gif +weapon_COD1_mg30cal_mp=mg30cal_mp.gif +weapon_COD1_mg34_mp=mg34_mp.gif +weapon_COD1_mg34_tank_mp=mg34_tank_mp.gif +weapon_COD1_mg42_bipod_duck_mp=mg42_bipod_stand_mp.gif +weapon_COD1_mg42_bipod_prone_mp=mg42_bipod_stand_mp.gif +weapon_COD1_mg42_bipod_stand_mp=mg42_bipod_stand_mp.gif +weapon_COD1_mg42_mp=mg42_bipod_stand_mp.gif +weapon_COD1_mg42_turret_mp=mg42_turret_mp.gif +weapon_COD1_mk1britishfrag_mp=mk1britishfrag_mp.gif +weapon_COD1_mod_crush_jeep= +weapon_COD1_mod_explosive= +weapon_COD1_mod_falling= +weapon_COD1_mod_flame= +weapon_COD1_mod_suicide= +weapon_COD1_mod_water= +weapon_COD1_mosin_nagant_mp=mosin_nagant_mp.gif +weapon_COD1_mosin_nagant_sniper_mp=mosin_nagant_sniper_mp.gif +weapon_COD1_mp40_mp=mp40_mp.gif +weapon_COD1_mp44_mp=mp44_mp.gif +weapon_COD1_mp44_semi_mp=mp44_mp.gif +weapon_COD1_panzerfaust_mp=panzerfaust_mp.gif +weapon_COD1_panzeriv_turret_mp=panzeriv_turret_mp.gif +weapon_COD1_panzerschreck_mp=panzerschreck_mp.gif +weapon_COD1_ppsh_mp=ppsh_mp.gif +weapon_COD1_ppsh_semi_mp=ppsh_mp.gif +weapon_COD1_ptrs41_antitank_rifle_mp= +weapon_COD1_rgd-33russianfrag_mp=rgd-33russianfrag_mp.gif +weapon_COD1_rgd_33russianfrag_mp= +weapon_COD1_satchelcharge_mp=satchelcharge_mp.gif +weapon_COD1_sg43_tank_mp=sg43_tank_mp.gif +weapon_COD1_sg43_turret_mp=sg43_turret_mp.gif +weapon_COD1_sherman_turret_mp=sherman_turret_mp.gif +weapon_COD1_springfield_mp=springfield_mp.gif +weapon_COD1_sten_mp=sten_mp.gif +weapon_COD1_sten_silenced_mp=sten_mp.gif +weapon_COD1_stielhandgranate_mp=stielhandgranate_mp.gif +weapon_COD1_su152_turret_mp=su152_turret_mp.gif +weapon_COD1_svt40_mp=svt40_mp.gif +weapon_COD1_t34_turret_mp=t34_turret_mp.gif +weapon_COD1_thompson_mp=thompson_mp.gif +weapon_COD1_thompson_semi_mp=thompson_mp.gif +weapon_COD1_tt33_mp=tt33_mp.gif +weapon_COD1_webley_mp=webley_mp.gif +weapon_COD2_30cal_duck_mp=30cal_stand_mp.gif +weapon_COD2_30cal_prone_mp=30cal_stand_mp.gif +weapon_COD2_30cal_stand_mp=30cal_stand_mp.gif +weapon_COD2_am_mp44_mp=mp44_mp.gif +weapon_COD2_artillery_mp=arty.jpg +weapon_COD2_bar_mp=bar_mp.gif +weapon_COD2_BASH=bash.gif +weapon_COD2_bren_mp=bren_mp.gif +weapon_COD2_colt_mp=colt_mp.gif +weapon_COD2_cook_frag_grenade_american_mp=fraggrenade_mp.gif +weapon_COD2_cook_frag_grenade_british_mp=mk1britishfrag_mp.gif +weapon_COD2_cook_frag_grenade_german_mp=stielhandgranate_mp.gif +weapon_COD2_cook_frag_grenade_russian_mp=rgd-33russianfrag_mp.gif +weapon_COD2_enfield_mp=enfield_mp.gif +weapon_COD2_enfield_scope_mp=enfield_scope_mp.gif +weapon_COD2_fire_grenade_mp=fire.jpg +weapon_COD2_frag_grenade_american_mp=fraggrenade_mp.gif +weapon_COD2_frag_grenade_british_mp=mk1britishfrag_mp.gif +weapon_COD2_frag_grenade_german_mp=stielhandgranate_mp.gif +weapon_COD2_frag_grenade_russian_mp=rgd-33russianfrag_mp.gif +weapon_COD2_frag_type1_american_mp=fraggrenade_mp.gif +weapon_COD2_frag_type1_british_mp=mk1britishfrag_mp.gif +weapon_COD2_frag_type1_german_mp=stielhandgranate_mp.gif +weapon_COD2_frag_type1_russian_mp=rgd-33russianfrag_mp.gif +weapon_COD2_g43_mp=gewehr43_mp.gif +weapon_COD2_gas_grenade_mp=gas.jpg +weapon_COD2_greasegun_mp=greasegun.gif +weapon_COD2_kar98k_mp=kar98k_mp.gif +weapon_COD2_kar98k_sniper_mp=kar98k_sniper_mp.gif +weapon_COD2_knife_mp=knife.jpg +weapon_COD2_luger_mp=luger_mp.gif +weapon_COD2_m1carbine_mp=m1carbine_mp.gif +weapon_COD2_m1garand_mp=m1garand_mp.gif +weapon_COD2_mg42_bipod_duck_mp=mg42_bipod_stand_mp.gif +weapon_COD2_mg42_bipod_prone_mp=mg42_bipod_stand_mp.gif +weapon_COD2_mg42_bipod_stand_mp=mg42_bipod_stand_mp.gif +weapon_COD2_MOD_EXPLOSIVE=explosion.gif +weapon_COD2_MOD_FALLING=suicide.gif +weapon_COD2_MOD_GRENADE_SPLASH=grenade.jpg +weapon_COD2_mod_head_shot= +weapon_COD2_MOD_PISTOL_BULLET=pistol.jpg +weapon_COD2_MOD_PROJECTILE_SPLASH=projectile.jpg +weapon_COD2_MOD_RIFLE_BULLET=rifle.jpg +weapon_COD2_MOD_SUICIDE=suicide.gif +weapon_COD2_mod_trigger_hurt= +weapon_COD2_mortar_cannon_walk_mp=mortar.jpg +weapon_COD2_mosin_nagant_mp=mosin_nagant_mp.gif +weapon_COD2_mosin_nagant_sniper_mp=mosin_nagant_sniper_mp.gif +weapon_COD2_mp40_mp=mp40_mp.gif +weapon_COD2_mp44_mp=mp44_mp.gif +weapon_COD2_panzerschreck_mp=panzerschreck.jpg +weapon_COD2_PPS42_mp=pps42_mp.gif +weapon_COD2_ppsh_mp=ppsh_mp.gif +weapon_COD2_shotgun_mp=trenchgun.gif +weapon_COD2_springfield_mp=springfield_mp.gif +weapon_COD2_sten_mp=sten_mp.gif +weapon_COD2_SVT40_mp=svt40_mp.gif +weapon_COD2_thompson_mp=thompson_mp.gif +weapon_COD2_tnt_bomb_mp=tnt.jpg +weapon_COD2_TT30_mp=tt30_mp.gif +weapon_COD2_webley_mp=webley_mp.gif +weapon_COD4_ak47_acog_mp=cod4_ak47acog.jpg +weapon_COD4_ak47_gl_mp=cod4_ak47gl.jpg +weapon_COD4_ak47_mp=cod4_ak47.jpg +weapon_COD4_ak47_reflex_mp=cod4_ak47reddot.jpg +weapon_COD4_ak47_silencer_mp=cod4_ak47silencer.jpg +weapon_COD4_ak74u_acog_mp=cod4_ak74uacog.jpg +weapon_COD4_ak74u_mp=cod4_ak74u.jpg +weapon_COD4_ak74u_reflex_mp=cod4_ak74ureddot.jpg +weapon_COD4_ak74u_silencer_mp=cod4_ak74usilencer.jpg +weapon_COD4_artillery_mp=cod4_artillery.jpg +weapon_COD4_barrett_acog_mp=cod4_barrettacog.jpg +weapon_COD4_barrett_mp=cod4_barrett.jpg +weapon_COD4_BASH=cod4_knife.jpg +weapon_COD4_beretta_mp=cod4_beretta.jpg +weapon_COD4_beretta_silencer_mp=cod4_beretta_silenced.jpg +weapon_COD4_c4_mp=cod4_c4.jpg +weapon_COD4_claymore_mp=cod4_claymore.jpg +weapon_COD4_cobra_20mm_mp=cod4_cobra.jpg +weapon_COD4_cobra_ffar_mp=cod4_cobra.jpg +weapon_COD4_colt45_mp=cod4_colt45.jpg +weapon_COD4_colt45_silencer_mp=cod4_colt45.jpg +weapon_COD4_concussion_grenade_mp=cod4_concussion_grenade.jpg +weapon_COD4_deserteagle_mp=cod4_desert_eagle.jpg +weapon_COD4_deserteaglegold_mp=cod4_desert_eagle_gold.jpg +weapon_COD4_destructible_car=cod4_destructable_car.jpg +weapon_COD4_dragunov_acog_mp=cod4_dragunovacog.jpg +weapon_COD4_dragunov_mp=cod4_dragunov.jpg +weapon_COD4_flash_grenade_mp=cod4_flashbang.jpg +weapon_COD4_frag_grenade_mp=cod4_frag_grenade.jpg +weapon_COD4_frag_grenade_short_mp=cod4_frag_grenade.jpg +weapon_COD4_g36c_acog_mp=cod4_g36cacog.jpg +weapon_COD4_g36c_gl_mp=cod4_g36cgl.jpg +weapon_COD4_g36c_mp=cod4_g36c.jpg +weapon_COD4_g36c_reflex_mp=cod4_g36creddot.jpg +weapon_COD4_g36c_silencer_mp=cod4_g36csilencer.jpg +weapon_COD4_g3_acog_mp=cod4_g3acog.jpg +weapon_COD4_g3_gl_mp=cod4_g3gl.jpg +weapon_COD4_g3_mp=cod4_g3.jpg +weapon_COD4_g3_reflex_mp=cod4_g3reddot.jpg +weapon_COD4_g3_silencer_mp=cod4_g3silencer.jpg +weapon_COD4_gl_ak47_mp=cod4_ak47.jpg +weapon_COD4_gl_g36c_mp=cod4_g36c.jpg +weapon_COD4_gl_g3_mp=cod4_g3.jpg +weapon_COD4_gl_m14_mp=cod4_m14.jpg +weapon_COD4_gl_m16_mp=cod4_m16.jpg +weapon_COD4_gl_m4_mp=cod4_m4.jpg +weapon_COD4_hind_ffar_mp=cod4_cobra.jpg +weapon_COD4_m1014_grip_mp=cod4_m1014grip.jpg +weapon_COD4_m1014_mp=cod4_m1014.jpg +weapon_COD4_m1014_reflex_mp=cod4_m1014reddot.jpg +weapon_COD4_m14_acog_mp=cod4_m14acog.jpg +weapon_COD4_m14_gl_mp=cod4_m14gl.jpg +weapon_COD4_m14_mp=cod4_m14.jpg +weapon_COD4_m14_reflex_mp=cod4_m14reddot.jpg +weapon_COD4_m14_silencer_mp=cod4_m14silencer.jpg +weapon_COD4_m16_acog_mp=cod4_m16acog.jpg +weapon_COD4_m16_gl_mp=cod4_m16gl.jpg +weapon_COD4_m16_mp=cod4_m16.jpg +weapon_COD4_m16_reflex_mp=cod4_m16reddot.jpg +weapon_COD4_m16_silencer_mp=cod4_m16silencer.jpg +weapon_COD4_m21_acog_mp=cod4_m21acog.jpg +weapon_COD4_m21_mp=cod4_m21.jpg +weapon_COD4_m40a3_acog_mp=cod4_m40a3acog.jpg +weapon_COD4_m40a3_mp=cod4_m40a3.jpg +weapon_COD4_m4_acog_mp=cod4_m4acog.jpg +weapon_COD4_m4_gl_mp=cod4_m4gl.jpg +weapon_COD4_m4_mp=cod4_m4.jpg +weapon_COD4_m4_reflex_mp=cod4_m4reddot.jpg +weapon_COD4_m4_silencer_mp=cod4_m4silencer.jpg +weapon_COD4_m60e4_acog_mp=cod4_m60e4acog.jpg +weapon_COD4_m60e4_grip_mp=cod4_m60e4grip.jpg +weapon_COD4_m60e4_mp=cod4_m60e4.jpg +weapon_COD4_m60e4_reflex_mp=cod4_m60e4reddot.jpg +weapon_COD4_mod_explosive=cod4_explosion.jpg +weapon_COD4_mod_falling=cod4_fall.jpg +weapon_COD4_mod_head_shot= +weapon_COD4_mod_pistol_bullet=cod4_pistolbullet.jpg +weapon_COD4_mod_rifle_bullet=cod4_riflebullet.jpg +weapon_COD4_mod_suicide= +weapon_COD4_mod_trigger_hurt=cod4_wrongplace.jpg +weapon_COD4_mp44_mp=cod4_mp44.jpg +weapon_COD4_mp5_acog_mp=cod4_mp5acog.jpg +weapon_COD4_mp5_mp=cod4_mp5.jpg +weapon_COD4_mp5_reflex_mp=cod4_mp5reddot.jpg +weapon_COD4_mp5_silencer_mp=cod4_mp5silencer.jpg +weapon_COD4_p90_acog_mp=cod4_p90acog.jpg +weapon_COD4_p90_mp=cod4_p90.jpg +weapon_COD4_p90_reflex_mp=cod4_p90reddot.jpg +weapon_COD4_p90_silencer_mp=cod4_p90silencer.jpg +weapon_COD4_remington700_acog_mp=cod4_remingtonacog.jpg +weapon_COD4_remington700_mp=cod4_remington.jpg +weapon_COD4_rpd_acog_mp=cod4_rpdacog.jpg +weapon_COD4_rpd_grip_mp=cod4_rpdgrip.jpg +weapon_COD4_rpd_mp=cod4_rpd.jpg +weapon_COD4_rpd_reflex_mp=cod4_rpdreddot.jpg +weapon_COD4_rpg_mp=cod4_rpg.jpg +weapon_COD4_saw_acog_mp=cod4_sawacog.jpg +weapon_COD4_saw_bipod_crouch_mp=cod4_saw.jpg +weapon_COD4_saw_bipod_stand_mp=cod4_saw.jpg +weapon_COD4_saw_grip_mp=cod4_sawgrip.jpg +weapon_COD4_saw_mp=cod4_saw.jpg +weapon_COD4_saw_reflex_mp=cod4_sawreddot.jpg +weapon_COD4_skorpion_acog_mp=cod4_skorpianacog.jpg +weapon_COD4_skorpion_mp=cod4_skorpian.jpg +weapon_COD4_skorpion_reflex_mp=cod4_skorpianreddot.jpg +weapon_COD4_skorpion_silencer_mp=cod4_skorpiansilencer.jpg +weapon_COD4_smoke_grenade_mp=cod4_smokegrenade.jpg +weapon_COD4_usp_mp=cod4_usp.jpg +weapon_COD4_usp_silencer_mp=cod4_uspsilencer.jpg +weapon_COD4_uzi_acog_mp=cod4_uziacog.jpg +weapon_COD4_uzi_mp=cod4_uzi.jpg +weapon_COD4_uzi_reflex_mp=cod4_uzireddot.jpg +weapon_COD4_uzi_silencer_mp=cod4_uzisilencer.jpg +weapon_COD4_winchester1200_grip_mp=cod4_winchestergrip.jpg +weapon_COD4_winchester1200_mp=cod4_winchester.jpg +weapon_COD4_winchester1200_reflex_mp=cod4_winchesterreddot.jpg +weapon_cod5_30cal_bipod_crouch_mp=cod5_weapon_30cal_bipod_crouch.jpg +weapon_cod5_30cal_bipod_mp=cod5_weapon_30cal_bipod.jpg +weapon_cod5_30cal_bipod_prone_mp=cod5_weapon_30cal_bipod_prone.jpg +weapon_cod5_30cal_bipod_stand_mp=cod5_weapon_30cal_bipod_stand.jpg +weapon_cod5_30cal_mp=cod5_weapon_30cal.jpg +weapon_cod5_357_mp=cod5_weapon_357.jpg +weapon_cod5_357magnum_mp=cod5_weapon_357.jpg +weapon_cod5_artillery_mp=cod5_weapon_arty.jpg +weapon_cod5_bar_bipod_crouch_mp=cod5_weapon_bar_bipod_crouch.jpg +weapon_cod5_bar_bipod_mp=cod5_weapon_bar_bipod.jpg +weapon_cod5_bar_bipod_prone_mp=cod5_weapon_bar_bipod_prone.jpg +weapon_cod5_bar_bipod_stand_mp=cod5_weapon_bar_bipod_stand.jpg +weapon_cod5_bar_mp=cod5_weapon_bar.jpg +weapon_cod5_bash=cod5_weapon_bash.jpg +weapon_cod5_bayonet=cod5_weapon_bayonet.jpg +weapon_cod5_bazooka_mp=cod5_weapon_bazooka.jpg +weapon_cod5_bren_bipod_mp=cod5_weapon_bren_bipod.jpg +weapon_cod5_bren_mp=cod5_weapon_bren.jpg +weapon_cod5_briefcase_bomb_mp=cod5_weapon_briefcase_bomb.jpg +weapon_cod5_colt_mp=cod5_weapon_colt.jpg +weapon_cod5_destructible_car=cod5_weapon_car.jpg +weapon_cod5_dog_bite_mp=cod5_weapon_dog_bite.jpg +weapon_cod5_doublebarreledshotgun_grip_mp=cod5_weapon_dbl_shotgun_grip.jpg +weapon_cod5_doublebarreledshotgun_mp=cod5_weapon_dbl_shotgun.jpg +weapon_cod5_doublebarreledshotgun_sawoff_mp=cod5_weapon_dbl_shotgun_sawnoff.jpg +weapon_cod5_dp28_bipod_crouch_mp=cod5_weapon_dp28_bipod_crouch.jpg +weapon_cod5_dp28_bipod_mp=cod5_weapon_dp28_bipod.jpg +weapon_cod5_dp28_bipod_prone_mp=cod5_weapon_dp28_bipod_prone.jpg +weapon_cod5_dp28_bipod_stand_mp=cod5_weapon_dp28_bipod_stand.jpg +weapon_cod5_dp28_mp=cod5_weapon_dp28.jpg +weapon_cod5_explodable_barrel=cod5_weapon_exploding_barrel.jpg +weapon_cod5_fg42_bipod_crouch_mp=cod5_weapon_fg42_bipod_crouch.jpg +weapon_cod5_fg42_bipod_mp=cod5_weapon_fg42_bipod.jpg +weapon_cod5_fg42_bipod_prone_mp=cod5_weapon_fg42_prone.jpg +weapon_cod5_fg42_bipod_stand_mp=cod5_weapon_fg42_stand.jpg +weapon_cod5_fg42_mp=cod5_weapon_fg42.jpg +weapon_cod5_fg42_scoped_mp=cod5_weapon_fg42_scope.jpg +weapon_cod5_fg42_telescopic_mp=cod5_weapon_fg42_scope.jpg +weapon_cod5_frag_grenade_mp=cod5_weapon_frag_grenade.jpg +weapon_cod5_frag_grenade_short_mp=cod5_weapon_frag_grenade.jpg +weapon_cod5_gewehr43_aperture_mp=cod5_weapon_gewehr43_aperture.jpg +weapon_cod5_gewehr43_gl_mp=cod5_weapon_gewehr43_gl.jpg +weapon_cod5_gewehr43_mp=cod5_weapon_gewehr43.jpg +weapon_cod5_gewehr43_silenced_mp=cod5_weapon_gewehr43_silenced.jpg +weapon_cod5_gewehr43_telescopic_mp=cod5_weapon_gewehr43_scope.jpg +weapon_cod5_gl_gewehr43_mp=cod5_weapon_gl_gewehr43.jpg +weapon_cod5_gl_kar98k_mp=cod5_weapon_gl_kar98k.jpg +weapon_cod5_gl_m1carbine_mp=cod5_weapon_gl_m1carbine.jpg +weapon_cod5_gl_m1garand_mp=cod5_weapon_gl_m1garand.jpg +weapon_cod5_gl_mosinrifle_mp=cod5_weapon_mosin_nagant_gl.jpg +weapon_cod5_gl_springfield_mp=cod5_weapon_gl_springfield.jpg +weapon_cod5_gl_type99rifle_mp=cod5_weapon_gl_type99_rifle.jpg +weapon_cod5_kar98k_bayonet_mp=cod5_weapon_kar98k_bayonet.jpg +weapon_cod5_kar98k_gl_mp=cod5_weapon_kar98k_gl.jpg +weapon_cod5_kar98k_mp=cod5_weapon_kar98k.jpg +weapon_cod5_kar98k_scoped_mp=cod5_weapon_kar98k_scope.jpg +weapon_cod5_lee_enfield_bayonet_mp=cod5_weapon_lee_enfield_bayonet.jpg +weapon_cod5_lee_enfield_mp=cod5_weapon_lee_enfield.jpg +weapon_cod5_lee_enfield_scoped_mp=cod5_weapon_lee_enfield_scope.jpg +weapon_cod5_m1carbine_aperture_mp=cod5_weapon_m1carbine_aperture.jpg +weapon_cod5_m1carbine_bayonet_mp=cod5_weapon_m1carbine_bayonet.jpg +weapon_cod5_m1carbine_bigammo_mp=cod5_weapon_m1carbine_bigammo.jpg +weapon_cod5_m1carbine_flash_mp=cod5_weapon_m1carbine_flash.jpg +weapon_cod5_m1carbine_gl_mp=cod5_weapon_m1carbine_gl.jpg +weapon_cod5_m1carbine_mp=cod5_weapon_m1carbine.jpg +weapon_cod5_m1garand_bayonet_mp=cod5_weapon_m1garand_bayonet.jpg +weapon_cod5_m1garand_flash_mp=cod5_weapon_m1garand_flash.jpg +weapon_cod5_m1garand_gl_mp=cod5_weapon_m1garand_gl.jpg +weapon_cod5_m1garand_mp=cod5_weapon_m1garand.jpg +weapon_cod5_m1garand_scoped_mp=cod5_weapon_m1garand_scoped.jpg +weapon_cod5_m2_flamethrower_mp=cod5_weapon_flamethrower.jpg +weapon_cod5_m8_white_smoke_mp=cod5_weapon_m8_white_smoke.jpg +weapon_cod5_mg42_bipod_crouch_mp=cod5_weapon_mg42_bipod_crouch.jpg +weapon_cod5_mg42_bipod_mp=cod5_weapon_mg42_bipod.jpg +weapon_cod5_mg42_bipod_prone_mp=cod5_weapon_mg42_bipod_prone.jpg +weapon_cod5_mg42_bipod_stand_mp=cod5_weapon_mg42_bipod_stand.jpg +weapon_cod5_mg42_mp=cod5_weapon_mg42.jpg +weapon_cod5_mine_bouncing_betty_mp=cod5_weapon_bouncing_betty.jpg +weapon_cod5_mod_burned=cod5_weapon_flamethrower.jpg +weapon_cod5_mod_explosive=cod5_weapon_explosion.jpg +weapon_cod5_mod_falling=cod5_weapon_fall.jpg +weapon_cod5_mod_suicide=cod5_weapon_suicide.jpg +weapon_cod5_mod_trigger_hurt=cod5_weapon_wrongplace.jpg +weapon_cod5_molotov_mp=cod5_weapon_molotov.jpg +weapon_cod5_mosinrifle_bayonet_mp=cod5_weapon_mosin_nagant_bayonet.jpg +weapon_cod5_mosinrifle_gl_mp=cod5_weapon_mosin_nagant_gl.jpg +weapon_cod5_mosinrifle_mp=cod5_weapon_mosin_nagant.jpg +weapon_cod5_mosinrifle_scoped_mp=cod5_weapon_mosin_nagant_scope.jpg +weapon_cod5_mp40_aperture_mp=cod5_weapon_mp40_aperture.jpg +weapon_cod5_mp40_bigammo_mp=cod5_weapon_mp40_bigammo.jpg +weapon_cod5_mp40_mp=cod5_weapon_mp40.jpg +weapon_cod5_mp40_silenced_mp=cod5_weapon_mp40_silenced.jpg +weapon_cod5_nambu_mp=cod5_weapon_nambu.jpg +weapon_cod5_panzer4_gunner_front_mp=cod5_weapon_panzer4_gunner_front.jpg +weapon_cod5_panzer4_gunner_mp=cod5_weapon_panzer4_gunner.jpg +weapon_cod5_panzer4_mp_explosion_mp=cod5_weapon_panzer4_explosion.jpg +weapon_cod5_panzer4_turret_mp=cod5_weapon_panzer4_turret.jpg +weapon_cod5_ppsh_aperture_mp=cod5_weapon_ppsh_aperture.jpg +weapon_cod5_ppsh_bigammo_mp=cod5_weapon_ppsh_bigammo.jpg +weapon_cod5_ppsh_mp=cod5_weapon_ppsh.jpg +weapon_cod5_ptrs41_mp=cod5_weapon_ptrs41.jpg +weapon_cod5_satchel_charge_mp=cod5_weapon_satchel_charge.jpg +weapon_cod5_shotgun_bayonet_mp=cod5_weapon_shotgun_bayonet.jpg +weapon_cod5_shotgun_grip_mp=cod5_weapon_shotgun_grip.jpg +weapon_cod5_shotgun_mp=cod5_weapon_shotgun.jpg +weapon_cod5_signal_flare_mp=cod5_weapon_signal_flare.jpg +weapon_cod5_springfield_bayonet_mp=cod5_weapon_springfield_bayonet.jpg +weapon_cod5_springfield_gl_mp=cod5_weapon_springfield_gl.jpg +weapon_cod5_springfield_mp=cod5_weapon_springfield.jpg +weapon_cod5_springfield_scoped_mp=cod5_weapon_springfield_scope.jpg +weapon_cod5_sten_mp=cod5_weapon_sten.jpg +weapon_cod5_sten_silenced_mp=cod5_weapon_sten_silenced.jpg +weapon_cod5_stg44_aperture_mp=cod5_weapon_stg44_aperture.jpg +weapon_cod5_stg44_flash_mp=cod5_weapon_stg44_flash.jpg +weapon_cod5_stg44_mp=cod5_weapon_stg44.jpg +weapon_cod5_stg44_telescopic_mp=cod5_weapon_stg44_scoped.jpg +weapon_cod5_sticky_grenade_mp=cod5_weapon_sticky_grenade.jpg +weapon_cod5_svt40_aperture_mp=cod5_weapon_svt40_aperture.jpg +weapon_cod5_svt40_flash_mp=cod5_weapon_svt40_flash.jpg +weapon_cod5_svt40_mp=cod5_weapon_svt40.jpg +weapon_cod5_svt40_telescopic_mp=cod5_weapon_svt40_scope.jpg +weapon_cod5_t34_gunner_front_mp=cod5_weapon_panzer4_gunner_front.jpg +weapon_cod5_t34_gunner_mp=cod5_weapon_t34_gunner.jpg +weapon_cod5_t34_mp_explosion_mp=cod5_weapon_t34_explosion.jpg +weapon_cod5_t34_turret_mp=cod5_weapon_t34_turret.jpg +weapon_cod5_tabun_gas_mp=cod5_weapon_tabun_gas.jpg +weapon_cod5_thompson_aperture_mp=cod5_weapon_thompson_aperture.jpg +weapon_cod5_thompson_bigammo_mp=cod5_weapon_thompson_bigammo.jpg +weapon_cod5_thompson_mp=cod5_weapon_thompson.jpg +weapon_cod5_thompson_silenced_mp=cod5_weapon_thompson_silenced.jpg +weapon_cod5_tokarev_mp=cod5_weapon_tokarev.jpg +weapon_cod5_type100smg_aperture_mp=cod5_weapon_type100_smg_aperture.jpg +weapon_cod5_type100smg_bigammo_mp=cod5_weapon_type100_smg_bigammo.jpg +weapon_cod5_type100smg_mp=cod5_weapon_type100_smg.jpg +weapon_cod5_type100smg_silenced_mp=cod5_weapon_type100_smg_silenced.jpg +weapon_cod5_type99_lmg_bipod_crouch_mp=cod5_weapon_type99_lmg_bipod_crouch.jpg +weapon_cod5_type99_lmg_bipod_prone_mp=cod5_weapon_type99_lmg_bipod_prone.jpg +weapon_cod5_type99_lmg_bipod_stand_mp=cod5_weapon_type99_lmg_bipod_stand.jpg +weapon_cod5_type99lmg_bayonet_mp=cod5_weapon_type99_lmg_bayonet.jpg +weapon_cod5_type99lmg_bipod_mp=cod5_weapon_type99_lmg_bipod.jpg +weapon_cod5_type99lmg_mp=cod5_weapon_type99_lmg.jpg +weapon_cod5_type99rifle_bayonet_mp=cod5_weapon_type99_rifle_bayonet.jpg +weapon_cod5_type99rifle_gl_mp=cod5_weapon_gl_type99_rifle.jpg +weapon_cod5_type99rifle_mp=cod5_weapon_type99_rifle.jpg +weapon_cod5_type99rifle_scoped_mp=cod5_weapon_type99_rifle_scoped.jpg +weapon_cod5_walther_mp=cod5_weapon_walther.jpg +weapon_MOHAA_burned_up=mohaa-flame.gif +weapon_MOHAA_clubbed=mohaa-owned.jpg +weapon_MOHAA_explode=mohaa-explosion.gif +weapon_MOHAA_grenade=grenade.gif +weapon_MOHAA_mg=machine-gunned.gif +weapon_MOHAA_mine=mohaa-explosion.gif +weapon_MOHAA_pistol=gunned-down.gif +weapon_MOHAA_rifle=rifled.gif +weapon_MOHAA_shotgun=shot.gif +weapon_MOHAA_smg=smg.gif +weapon_MOHAA_sniper=sniped.gif +weapon_MOHAA_suicide= +weapon_QUAKEWARS_accurized_lacerator=lacerator.png +weapon_QUAKEWARS_airstrike_marker=airstrikemarker.png +weapon_QUAKEWARS_anansi=anansi.png +weapon_QUAKEWARS_apt=gdf-apt.png +weapon_QUAKEWARS_armadillo=armadillo.png +weapon_QUAKEWARS_artillery=gdf-artillery.png +weapon_QUAKEWARS_assault_rifle=assaultrifle.png +weapon_QUAKEWARS_avt=gdf-avt.png +weapon_QUAKEWARS_blaster=stroggblaster.png +weapon_QUAKEWARS_bumblebee=buffalo.png +weapon_QUAKEWARS_cyclops=cyclops.png +weapon_QUAKEWARS_dark_matter_cannon=strogg-dmc.png +weapon_QUAKEWARS_defibrillator=gdfdefibrilators.png +weapon_QUAKEWARS_desecrator=desecrator.png +weapon_QUAKEWARS_emp_grenade=empgrenade.png +weapon_QUAKEWARS_flyer_drone=flyerdrone.png +weapon_QUAKEWARS_frag_grenade=fraggrenade.png +weapon_QUAKEWARS_gdf_base_defense_turret=mcp.png +weapon_QUAKEWARS_gpmg=gpmg.png +weapon_QUAKEWARS_grenade_launcher=assaultgrenade.png +weapon_QUAKEWARS_hammer=gdf-ssm.png +weapon_QUAKEWARS_he_charge=hecharge.png +weapon_QUAKEWARS_hog=hog.png +weapon_QUAKEWARS_husky=husky.png +weapon_QUAKEWARS_hyperblaster=hyperblaster.png +weapon_QUAKEWARS_knife=combatknife.png +weapon_QUAKEWARS_knife_backstab=combatknife.png +weapon_QUAKEWARS_lacerator=lacerator.png +weapon_QUAKEWARS_law=rocketlauncher.png +weapon_QUAKEWARS_lightning_pistol=lightningpistol.png +weapon_QUAKEWARS_machine_pistol=machinepistol.png +weapon_QUAKEWARS_mcp=mcp.png +weapon_QUAKEWARS_mg=machinepistol.png +weapon_QUAKEWARS_nailgun=nailgun.png +weapon_QUAKEWARS_obliterator=obliterator.png +weapon_QUAKEWARS_pistol=pistol.png +weapon_QUAKEWARS_plasma_cannon=cyclops.png +weapon_QUAKEWARS_plasma_charge=plasmacharge.png +weapon_QUAKEWARS_plasma_launcher=strogg-plasma-mortar.png +weapon_QUAKEWARS_plasma_mortar=strogg-plasma-mortar.png +weapon_QUAKEWARS_platypus=platypus.png +weapon_QUAKEWARS_proximity_mine=landmine.png +weapon_QUAKEWARS_rail_howitzer=strogg-railhowitzer.png +weapon_QUAKEWARS_railgun=railgun.png +weapon_QUAKEWARS_respawn=teleporter.png +weapon_QUAKEWARS_rocket=rocketlauncher.png +weapon_QUAKEWARS_rocket_artillery=gdf-rockets.png +weapon_QUAKEWARS_rocket_launcher=rocketlauncher.png +weapon_QUAKEWARS_scoped_assault_rifle=assaultrifle.png +weapon_QUAKEWARS_scrambler_grenade=scramblergrenade.png +weapon_QUAKEWARS_shotgun=shotgun.png +weapon_QUAKEWARS_shrap_grenade=shrapgrenade.png +weapon_QUAKEWARS_silenced_machine_pistol=silencedmachinepistol.png +weapon_QUAKEWARS_silenced_pistol=silencedpistol.png +weapon_QUAKEWARS_sniper_rifle=sniperrifle.png +weapon_QUAKEWARS_spikes=stroggspikes.png +weapon_QUAKEWARS_spikes_backstab=stroggspikes.png +weapon_QUAKEWARS_ssm=gdf-ssm.png +weapon_QUAKEWARS_strocket=rocketlauncher.png +weapon_QUAKEWARS_stroybomb=stroggmine.png +weapon_QUAKEWARS_stroyent_tool=stroyenttool.png +weapon_QUAKEWARS_tank_gun=titan.png +weapon_QUAKEWARS_third_eye_camera=thirdeyecamera.png +weapon_QUAKEWARS_titan=titan.png +weapon_QUAKEWARS_tormentor=tormentor.png +weapon_QUAKEWARS_tripmine=landmine.png +weapon_QUAKEWARS_trojan=trojan.png +weapon_QUAKEWARS_violator=violatorbeacon.png +weapon_QUAKEWARS_violator_beacon=violatorbeacon.png +weapon_WOLFENSTEIN_MOD_AIRSTRIKE=et_binoculars.gif +weapon_WOLFENSTEIN_MOD_AKIMBO_COLT=et_alliedpistol.gif +weapon_WOLFENSTEIN_MOD_AKIMBO_LUGER=et_axispistol.gif +weapon_WOLFENSTEIN_MOD_ARTILLERY=et_binoculars.gif +weapon_WOLFENSTEIN_MOD_ARTY=et_binoculars.gif +weapon_WOLFENSTEIN_MOD_BROWNING=et_mountedbrowning30cal.gif +weapon_WOLFENSTEIN_MOD_CARBINE=et_carbine.gif +weapon_WOLFENSTEIN_MOD_COLT=et_alliedpistol.gif +weapon_WOLFENSTEIN_MOD_CRUSH=enemy_territory.gif +weapon_WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION=enemy_territory.gif +weapon_WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER=enemy_territory.gif +weapon_WOLFENSTEIN_MOD_DYNAMITE=et_dynamite.gif +weapon_WOLFENSTEIN_MOD_DYNAMITE_SPLASH=et_dynamite.gif +weapon_WOLFENSTEIN_MOD_EXPLOSIVE=enemy_territory_MOD_EXPLOSIVE.gif +weapon_WOLFENSTEIN_MOD_FALLING=falling.gif +weapon_WOLFENSTEIN_MOD_FG42=et_fg42.gif +weapon_WOLFENSTEIN_MOD_FG42SCOPE=et_fg42.gif +weapon_WOLFENSTEIN_MOD_FLAMETHROWER=et_flamethrower.gif +weapon_WOLFENSTEIN_MOD_GARAND=et_m1garand.gif +weapon_WOLFENSTEIN_MOD_GARAND_SCOPE=et_m1garand.gif +weapon_WOLFENSTEIN_MOD_GOOMBA=enemy_territory_MOD_GOOMBA.gif +weapon_WOLFENSTEIN_MOD_GPG40=et_alliedgrenade.gif +weapon_WOLFENSTEIN_MOD_GRENADE=et_alliedgrenade.gif +weapon_WOLFENSTEIN_MOD_GRENADE_LAUNCHER=et_alliedgrenade.gif +weapon_WOLFENSTEIN_MOD_GRENADE_SPLASH=et_alliedgrenade.gif +weapon_WOLFENSTEIN_MOD_K43=et_k43.gif +weapon_WOLFENSTEIN_MOD_K43_SCOPE=et_k43.gif +weapon_WOLFENSTEIN_MOD_KAR98=et_kar98k.gif +weapon_WOLFENSTEIN_mod_kicked= +weapon_WOLFENSTEIN_MOD_KNIFE=et_knife.gif +weapon_WOLFENSTEIN_MOD_KNIFE_STEALTH=et_knife.gif +weapon_WOLFENSTEIN_MOD_LANDMINE=et_landmine.gif +weapon_WOLFENSTEIN_MOD_LUGER=et_axispistol.gif +weapon_WOLFENSTEIN_MOD_M7=et_alliedgrenade.gif +weapon_WOLFENSTEIN_MOD_MACHINEGUN=et_mountedbrowning30cal.gif +weapon_WOLFENSTEIN_MOD_MAUSER=et_kar98k.gif +weapon_WOLFENSTEIN_MOD_MG42=et_mg42.gif +weapon_WOLFENSTEIN_MOD_MOBILE_MG42=et_mg42.gif +weapon_WOLFENSTEIN_MOD_MORTAR=et_mortar.gif +weapon_WOLFENSTEIN_MOD_MORTAR_SPLASH=et_mortar.gif +weapon_WOLFENSTEIN_MOD_MP40=et_mp40.gif +weapon_WOLFENSTEIN_MOD_PANZERFAUST=et_panzerfaust.gif +weapon_WOLFENSTEIN_MOD_POISON=et_poison.gif +weapon_WOLFENSTEIN_MOD_ROCKET=et_panzerfaust.gif +weapon_WOLFENSTEIN_MOD_ROCKET_SPLASH=et_panzerfaust.gif +weapon_WOLFENSTEIN_MOD_SATCHEL=et_satchelcharge.gif +weapon_WOLFENSTEIN_MOD_SILENCED_COLT=et_alliedpistol.gif +weapon_WOLFENSTEIN_MOD_SILENCER=et_alliedpistol.gif +weapon_WOLFENSTEIN_MOD_SNIPERRIFLE=et_kar98k.gif +weapon_WOLFENSTEIN_MOD_STEN=et_sten.gif +weapon_WOLFENSTEIN_mod_suicide= +weapon_WOLFENSTEIN_mod_switchteam= +weapon_WOLFENSTEIN_MOD_THOMPSON=et_thompson.gif +weapon_WOLFENSTEIN_mod_trigger_hurt= +weapon_WOLFENSTEIN_mod_unknown= +weapon_WOLFENSTEIN_MOD_VENOM=et_venom.gif +weapon_WOLFENSTEIN_MOD_WATER=MOD_WATER.gif +[LogEntriesACTION] +COD1_bas_attacked= +COD1_bas_breached= +COD1_bas_defend= +COD1_bas_defused= +COD1_bas_destroyed= +COD1_bas_planted= +COD1_bel_alive_tick= +COD1_bomb_defuse= +COD1_bomb_plant= +COD1_cnq_objective= +COD1_ctf_assist= +COD1_ctf_captured= +COD1_ctf_defended= +COD1_ctf_pickup= +COD1_ctf_returned= +COD1_ctf_score= +COD1_ctf_stole= +COD1_ctf_take= +COD1_dom_captured= +COD1_re_capture= +COD1_re_pickup= +COD2_bas_attacked= +COD2_bas_breached= +COD2_bas_defend= +COD2_bas_defused= +COD2_bas_destroyed= +COD2_bas_planted= +COD2_bel_alive_tick= +COD2_bomb_defuse= +COD2_bomb_plant= +COD2_ctf_assist= +COD2_ctf_captured= +COD2_ctf_defended= +COD2_ctf_pickup= +COD2_ctf_returned= +COD2_ctf_take= +COD2_Exploit_abuser_was_suicided_by_server= +COD2_heal= +COD2_hq_capture= +COD2_hq_defend= +COD2_hq_destroy= +COD2_htf_scored= +COD2_htf_stole= +COD2_sd_defend= +COD4_bomb_defused= +COD4_bomb_planted= +COD4_kill_assist= +cod5_bd= +cod5_bp= +cod5_fc= +cod5_fr= +cod5_ft= +cod5_rc= +cod5_rd= +MOHAA_FreezeTagCapture= +MOHAA_FreezeTagDrop= +MOHAA_FreezeTagMelt= +MOHAA_FreezeTagPickup= +MOHAA_FreezeTagPost= +MOHAA_FreezeTagReturn= +MOHAA_FreezeTagSave= +WOLFENSTEIN_Dynamite_Defuse= +WOLFENSTEIN_Dynamite_Plant= +[LogEntriesWEAPON] +COD1_30cal_tank_mp= +COD1_50cal_tank_mp= +COD1_bar_mp= +COD1_bar_slow_mp= +COD1_BASH= +COD1_bazooka_mp= +COD1_binoculars_artillery_mp= +COD1_binoculars_mp= +COD1_bren_mp= +COD1_colt_mp= +COD1_dp28_mp= +COD1_elefant_turret_mp= +COD1_enfield_mp= +COD1_fg42_mp= +COD1_fg42_semi_mp= +COD1_flak88_turret_mp= +COD1_flamethrower_mp= +COD1_fraggrenade_mp= +COD1_gewehr43_mp= +COD1_kar98k_mp= +COD1_kar98k_sniper_mp= +COD1_luger_mp= +COD1_m1carbine_gfm_mp= +COD1_m1carbine_mp= +COD1_m1garand_mp= +COD1_medic_m1carbine_mp= +COD1_mg30cal_mp= +COD1_mg34_mp= +COD1_mg34_tank_mp= +COD1_mg42_bipod_duck_mp= +COD1_mg42_bipod_prone_mp= +COD1_mg42_bipod_stand_mp= +COD1_mg42_mp= +COD1_mg42_turret_mp= +COD1_mk1britishfrag_mp= +COD1_MOD_CRUSH_JEEP= +COD1_MOD_EXPLOSIVE= +COD1_MOD_FALLING= +COD1_MOD_FLAME= +COD1_MOD_SUICIDE= +COD1_MOD_TRIGGER_HURT= +COD1_MOD_WATER= +COD1_mosin_nagant_mp= +COD1_mosin_nagant_sniper_mp= +COD1_mp40_mp= +COD1_mp44_mp= +COD1_mp44_semi_mp= +COD1_pak40_turret_mp= +COD1_panther_turret_mp= +COD1_panzerfaust_mp= +COD1_panzeriv_turret_mp= +COD1_panzerschreck_mp= +COD1_ppsh_mp= +COD1_ppsh_semi_mp= +COD1_ptrs41_antitank_rifle_mp= +COD1_rgd-33russianfrag_mp= +COD1_rgd_33russianfrag_mp= +COD1_satchelcharge_mp= +COD1_sg43_tank_mp= +COD1_sg43_turret_mp= +COD1_sherman_turret_mp= +COD1_smokegrenade_mp= +COD1_springfield_mp= +COD1_sten_mp= +COD1_sten_silenced_mp= +COD1_stielhandgranate_mp= +COD1_su152_turret_mp= +COD1_svt40_mp= +COD1_t34_turret_mp= +COD1_thompson_mp= +COD1_thompson_semi_mp= +COD1_tt33_mp= +COD1_webley_mp= +COD2_30cal_prone_mp= +COD2_30cal_stand_mp= +COD2_am_mp44_mp= +COD2_artillery_mp= +COD2_bar_mp= +COD2_bar_slow_mp= +COD2_BASH= +COD2_bazooka_mp= +COD2_binoculars_artillery_mp= +COD2_bren_mp= +COD2_colt_mp= +COD2_cook_frag_grenade_american_mp= +COD2_cook_frag_grenade_british_mp= +COD2_cook_frag_grenade_german_mp= +COD2_cook_frag_grenade_russian_mp= +COD2_enfield_mp= +COD2_enfield_scope_mp= +COD2_fire_grenade_mp= +COD2_flamethrower_mp= +COD2_frag_grenade_american_mp= +COD2_frag_grenade_british_mp= +COD2_frag_grenade_german_mp= +COD2_frag_grenade_russian_mp= +COD2_frag_type1_american_mp= +COD2_frag_type1_british_mp= +COD2_frag_type1_german_mp= +COD2_frag_type1_russian_mp= +COD2_fraggrenade_mp= +COD2_g43_mp= +COD2_gas_grenade_mp= +COD2_greasegun_mp= +COD2_kar98k_mp= +COD2_kar98k_sniper_mp= +COD2_knife_mp= +COD2_luger_mp= +COD2_m1carbine_mp= +COD2_m1garand_mp= +COD2_mg42_bipod_duck_mp= +COD2_mg42_bipod_prone_mp= +COD2_mg42_bipod_stand_mp= +COD2_mk1britishfrag_mp= +COD2_MOD_CRUSH_JEEP= +COD2_MOD_EXPLOSIVE= +COD2_MOD_FALLING= +COD2_MOD_FLAME= +COD2_MOD_GRENADE_SPLASH= +COD2_mod_head_shot= +COD2_MOD_PISTOL_BULLET= +COD2_MOD_RIFLE_BULLET= +COD2_MOD_SUICIDE= +COD2_MOD_TRIGGER_HURT= +COD2_MOD_WATER= +COD2_mosin_nagant_mp= +COD2_mosin_nagant_sniper_mp= +COD2_mp40_mp= +COD2_mp44_mp= +COD2_panzerschreck_mp= +COD2_PPS42_mp= +COD2_ppsh_mp= +COD2_rgd-33russianfrag_mp= +COD2_satchelcharge_mp= +COD2_shotgun_mp= +COD2_springfield_mp= +COD2_sten_mp= +COD2_sticky_bomb_mp= +COD2_SVT40_mp= +COD2_thompson_mp= +COD2_tnt_bomb_mp= +COD2_TT30_mp= +COD2_webley_mp= +COD4_ak47_acog_mp= +COD4_ak47_gl_mp= +COD4_ak47_mp= +COD4_ak47_reflex_mp= +COD4_ak47_silencer_mp= +COD4_ak74u_acog_mp= +COD4_ak74u_mp= +COD4_ak74u_reflex_mp= +COD4_ak74u_silencer_mp= +COD4_artillery_mp= +COD4_barrett_acog_mp= +COD4_barrett_mp= +COD4_BASH= +COD4_beretta_mp= +COD4_beretta_silencer_mp= +COD4_c4_mp= +COD4_claymore_mp= +COD4_cobra_20mm_mp= +COD4_cobra_ffar_mp= +COD4_colt45_mp= +COD4_colt45_silencer_mp= +COD4_concussion_grenade_mp= +COD4_deserteagle_mp= +COD4_deserteaglegold_mp= +COD4_destructible_car= +COD4_dragunov_acog_mp= +COD4_dragunov_mp= +COD4_flash_grenade_mp= +COD4_frag_grenade_mp= +COD4_frag_grenade_short_mp= +COD4_g36c_acog_mp= +COD4_g36c_gl_mp= +COD4_g36c_mp= +COD4_g36c_reflex_mp= +COD4_g36c_silencer_mp= +COD4_g3_acog_mp= +COD4_g3_gl_mp= +COD4_g3_mp= +COD4_g3_reflex_mp= +COD4_g3_silencer_mp= +COD4_gl_ak47_mp= +COD4_gl_g36c_mp= +COD4_gl_g3_mp= +COD4_gl_m14_mp= +COD4_gl_m16_mp= +COD4_gl_m4_mp= +COD4_hind_ffar_mp= +COD4_m1014_grip_mp= +COD4_m1014_mp= +COD4_m1014_reflex_mp= +COD4_m14_acog_mp= +COD4_m14_gl_mp= +COD4_m14_mp= +COD4_m14_reflex_mp= +COD4_m14_silencer_mp= +COD4_m16_acog_mp= +COD4_m16_gl_mp= +COD4_m16_mp= +COD4_m16_reflex_mp= +COD4_m16_silencer_mp= +COD4_m21_acog_mp= +COD4_m21_mp= +COD4_m40a3_acog_mp= +COD4_m40a3_mp= +COD4_m4_acog_mp= +COD4_m4_gl_mp= +COD4_m4_mp= +COD4_m4_reflex_mp= +COD4_m4_silencer_mp= +COD4_m60e4_acog_mp= +COD4_m60e4_grip_mp= +COD4_m60e4_mp= +COD4_m60e4_reflex_mp= +COD4_mod_explosive= +COD4_mod_falling= +COD4_mod_head_shot= +COD4_mod_pistol_bullet= +COD4_mod_rifle_bullet= +COD4_mod_suicide= +COD4_mod_trigger_hurt= +COD4_mp44_mp= +COD4_mp5_acog_mp= +COD4_mp5_mp= +COD4_mp5_reflex_mp= +COD4_mp5_silencer_mp= +COD4_p90_acog_mp= +COD4_p90_mp= +COD4_p90_reflex_mp= +COD4_p90_silencer_mp= +COD4_remington700_acog_mp= +COD4_remington700_mp= +COD4_rpd_acog_mp= +COD4_rpd_grip_mp= +COD4_rpd_mp= +COD4_rpd_reflex_mp= +COD4_rpg_mp= +COD4_saw_acog_mp= +COD4_saw_bipod_crouch_mp= +COD4_saw_bipod_stand_mp= +COD4_saw_grip_mp= +COD4_saw_mp= +COD4_saw_reflex_mp= +COD4_skorpion_acog_mp= +COD4_skorpion_mp= +COD4_skorpion_reflex_mp= +COD4_skorpion_silencer_mp= +COD4_smoke_grenade_mp= +COD4_usp_mp= +COD4_usp_silencer_mp= +COD4_uzi_acog_mp= +COD4_uzi_mp= +COD4_uzi_reflex_mp= +COD4_uzi_silencer_mp= +COD4_winchester1200_grip_mp= +COD4_winchester1200_mp= +COD4_winchester1200_reflex_mp= +cod5_30cal_bipod_crouch_mp= +cod5_30cal_bipod_mp= +cod5_30cal_bipod_prone_mp= +cod5_30cal_bipod_stand_mp= +cod5_30cal_mp= +cod5_357_mp= +cod5_357magnum_mp= +cod5_artillery_mp= +cod5_bar_bipod_crouch_mp= +cod5_bar_bipod_mp= +cod5_bar_bipod_prone_mp= +cod5_bar_bipod_stand_mp= +cod5_bar_mp= +cod5_bash= +cod5_bayonet= +cod5_bazooka_mp= +cod5_bren_bipod_mp= +cod5_bren_mp= +cod5_briefcase_bomb_mp= +cod5_colt_mp= +cod5_destructible_car= +cod5_dog_bite_mp= +cod5_doublebarreledshotgun_grip_mp= +cod5_doublebarreledshotgun_mp= +cod5_doublebarreledshotgun_sawoff_mp= +cod5_dp28_bipod_crouch_mp= +cod5_dp28_bipod_mp= +cod5_dp28_bipod_prone_mp= +cod5_dp28_bipod_stand_mp= +cod5_dp28_mp= +cod5_explodable_barrel= +cod5_fg42_bipod_crouch_mp= +cod5_fg42_bipod_mp= +cod5_fg42_bipod_prone_mp= +cod5_fg42_bipod_stand_mp= +cod5_fg42_mp= +cod5_fg42_scoped_mp= +cod5_fg42_telescopic_mp= +cod5_frag_grenade_mp= +cod5_frag_grenade_short_mp= +cod5_gewehr43_aperture_mp= +cod5_gewehr43_gl_mp= +cod5_gewehr43_mp= +cod5_gewehr43_silenced_mp= +cod5_gewehr43_telescopic_mp= +cod5_gl_gewehr43_mp= +cod5_gl_kar98k_mp= +cod5_gl_m1carbine_mp= +cod5_gl_m1garand_mp= +cod5_gl_mosinrifle_mp= +cod5_gl_springfield_mp= +cod5_gl_type99rifle_mp= +cod5_kar98k_bayonet_mp= +cod5_kar98k_gl_mp= +cod5_kar98k_mp= +cod5_kar98k_scoped_mp= +cod5_lee_enfield_bayonet_mp= +cod5_lee_enfield_mp= +cod5_lee_enfield_scoped_mp= +cod5_m1carbine_aperture_mp= +cod5_m1carbine_bayonet_mp= +cod5_m1carbine_bigammo_mp= +cod5_m1carbine_flash_mp= +cod5_m1carbine_gl_mp= +cod5_m1carbine_mp= +cod5_m1garand_bayonet_mp= +cod5_m1garand_flash_mp= +cod5_m1garand_gl_mp= +cod5_m1garand_mp= +cod5_m1garand_scoped_mp= +cod5_m2_flamethrower_mp= +cod5_m8_white_smoke_mp= +cod5_mg42_bipod_crouch_mp= +cod5_mg42_bipod_mp= +cod5_mg42_bipod_prone_mp= +cod5_mg42_bipod_stand_mp= +cod5_mg42_mp= +cod5_mine_bouncing_betty_mp= +cod5_mod_burned= +cod5_mod_explosive= +cod5_mod_falling= +cod5_mod_suicide= +cod5_mod_trigger_hurt= +cod5_molotov_mp= +cod5_mosinrifle_bayonet_mp= +cod5_mosinrifle_gl_mp= +cod5_mosinrifle_mp= +cod5_mosinrifle_scoped_mp= +cod5_mp40_aperture_mp= +cod5_mp40_bigammo_mp= +cod5_mp40_mp= +cod5_mp40_silenced_mp= +cod5_nambu_mp= +cod5_panzer4_gunner_front_mp= +cod5_panzer4_gunner_mp= +cod5_panzer4_mp_explosion_mp= +cod5_panzer4_turret_mp= +cod5_ppsh_aperture_mp= +cod5_ppsh_bigammo_mp= +cod5_ppsh_mp= +cod5_ptrs41_mp= +cod5_satchel_charge_mp= +cod5_shotgun_bayonet_mp= +cod5_shotgun_grip_mp= +cod5_shotgun_mp= +cod5_signal_flare_mp= +cod5_springfield_bayonet_mp= +cod5_springfield_gl_mp= +cod5_springfield_mp= +cod5_springfield_scoped_mp= +cod5_sten_mp= +cod5_sten_silenced_mp= +cod5_stg44_aperture_mp= +cod5_stg44_flash_mp= +cod5_stg44_mp= +cod5_stg44_telescopic_mp= +cod5_sticky_grenade_mp= +cod5_svt40_aperture_mp= +cod5_svt40_flash_mp= +cod5_svt40_mp= +cod5_svt40_telescopic_mp= +cod5_t34_gunner_front_mp= +cod5_t34_gunner_mp= +cod5_t34_mp_explosion_mp= +cod5_t34_turret_mp= +cod5_tabun_gas_mp= +cod5_thompson_aperture_mp= +cod5_thompson_bigammo_mp= +cod5_thompson_mp= +cod5_thompson_silenced_mp= +cod5_tokarev_mp= +cod5_type100smg_aperture_mp= +cod5_type100smg_bigammo_mp= +cod5_type100smg_mp= +cod5_type100smg_silenced_mp= +cod5_type99_lmg_bipod_crouch_mp= +cod5_type99_lmg_bipod_prone_mp= +cod5_type99_lmg_bipod_stand_mp= +cod5_type99lmg_bayonet_mp= +cod5_type99lmg_bipod_mp= +cod5_type99lmg_mp= +cod5_type99rifle_bayonet_mp= +cod5_type99rifle_gl_mp= +cod5_type99rifle_mp= +cod5_type99rifle_scoped_mp= +cod5_walther_mp= +MOHAA_burned_up= +MOHAA_clubbed= +MOHAA_explode= +MOHAA_grenade= +MOHAA_mg= +MOHAA_mine= +MOHAA_pistol= +MOHAA_rifle= +MOHAA_shotgun= +MOHAA_smg= +MOHAA_sniper= +MOHAA_suicide= +MOHAA_telefragged= +QUAKEWARS_aa_missile= +QUAKEWARS_accurized_lacerator= +QUAKEWARS_airstrike_marker= +QUAKEWARS_anansi= +QUAKEWARS_apt= +QUAKEWARS_armadillo= +QUAKEWARS_artillery= +QUAKEWARS_assault_rifle= +QUAKEWARS_avt= +QUAKEWARS_blaster= +QUAKEWARS_bumblebee= +QUAKEWARS_crush= +QUAKEWARS_cyclops= +QUAKEWARS_dark_matter_cannon= +QUAKEWARS_defibrillator= +QUAKEWARS_desecrator= +QUAKEWARS_emp_grenade= +QUAKEWARS_explosion= +QUAKEWARS_fall= +QUAKEWARS_flyer_drone= +QUAKEWARS_frag_grenade= +QUAKEWARS_gdf_base_defense_turret= +QUAKEWARS_gpmg= +QUAKEWARS_grenade_launcher= +QUAKEWARS_hammer= +QUAKEWARS_he_charge= +QUAKEWARS_hog= +QUAKEWARS_husky= +QUAKEWARS_hyperblaster= +QUAKEWARS_knife= +QUAKEWARS_knife_backstab= +QUAKEWARS_lacerator= +QUAKEWARS_law= +QUAKEWARS_lightning_pistol= +QUAKEWARS_machine_pistol= +QUAKEWARS_mcp= +QUAKEWARS_mg= +QUAKEWARS_minigun= +QUAKEWARS_mining_laser= +QUAKEWARS_nailgun= +QUAKEWARS_obliterator= +QUAKEWARS_pistol= +QUAKEWARS_plasma_cannon= +QUAKEWARS_plasma_charge= +QUAKEWARS_plasma_launcher= +QUAKEWARS_plasma_mortar= +QUAKEWARS_platypus= +QUAKEWARS_proximity_mine= +QUAKEWARS_rail_howitzer= +QUAKEWARS_railgun= +QUAKEWARS_respawn= +QUAKEWARS_rocket= +QUAKEWARS_rocket_artillery= +QUAKEWARS_rocket_launcher= +QUAKEWARS_scoped_assault_rifle= +QUAKEWARS_scrambler_grenade= +QUAKEWARS_shotgun= +QUAKEWARS_shrap_grenade= +QUAKEWARS_silenced_machine_pistol= +QUAKEWARS_silenced_pistol= +QUAKEWARS_sniper_rifle= +QUAKEWARS_spikes= +QUAKEWARS_spikes_backstab= +QUAKEWARS_ssm= +QUAKEWARS_strocket= +QUAKEWARS_strogg_base_defense_turret= +QUAKEWARS_stroybomb= +QUAKEWARS_stroyent_tool= +QUAKEWARS_tank_gun= +QUAKEWARS_third_eye_camera= +QUAKEWARS_titan= +QUAKEWARS_tormentor= +QUAKEWARS_tripmine= +QUAKEWARS_trojan= +QUAKEWARS_vampire= +QUAKEWARS_violator= +QUAKEWARS_violator_beacon= +WOLFENSTEIN_MOD_AIRSTRIKE= +WOLFENSTEIN_MOD_AKIMBO_COLT= +WOLFENSTEIN_MOD_AKIMBO_LUGER= +WOLFENSTEIN_MOD_ARTILLERY= +WOLFENSTEIN_MOD_ARTY= +WOLFENSTEIN_MOD_BROWNING= +WOLFENSTEIN_MOD_CARBINE= +WOLFENSTEIN_MOD_COLT= +WOLFENSTEIN_MOD_CRUSH= +WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION= +WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER= +WOLFENSTEIN_MOD_DYNAMITE= +WOLFENSTEIN_MOD_DYNAMITE_SPLASH= +WOLFENSTEIN_MOD_EXPLOSIVE= +WOLFENSTEIN_MOD_FALLING= +WOLFENSTEIN_MOD_FG42= +WOLFENSTEIN_MOD_FG42SCOPE= +WOLFENSTEIN_MOD_FLAMETHROWER= +WOLFENSTEIN_MOD_GARAND= +WOLFENSTEIN_MOD_GARAND_SCOPE= +WOLFENSTEIN_MOD_GOOMBA= +WOLFENSTEIN_MOD_GPG40= +WOLFENSTEIN_MOD_GRENADE= +WOLFENSTEIN_MOD_GRENADE_LAUNCHER= +WOLFENSTEIN_MOD_GRENADE_SPLASH= +WOLFENSTEIN_MOD_K43= +WOLFENSTEIN_MOD_K43_SCOPE= +WOLFENSTEIN_MOD_KAR98= +WOLFENSTEIN_MOD_KICKED= +WOLFENSTEIN_MOD_KNIFE= +WOLFENSTEIN_MOD_KNIFE_STEALTH= +WOLFENSTEIN_MOD_LANDMINE= +WOLFENSTEIN_MOD_LUGER= +WOLFENSTEIN_MOD_M7= +WOLFENSTEIN_MOD_MACHINEGUN= +WOLFENSTEIN_MOD_MAUSER= +WOLFENSTEIN_MOD_MG42= +WOLFENSTEIN_MOD_MOBILE_MG42= +WOLFENSTEIN_MOD_MORTAR= +WOLFENSTEIN_MOD_MORTAR_SPLASH= +WOLFENSTEIN_MOD_MP40= +WOLFENSTEIN_MOD_PANZERFAUST= +WOLFENSTEIN_MOD_POISON= +WOLFENSTEIN_MOD_ROCKET= +WOLFENSTEIN_MOD_ROCKET_SPLASH= +WOLFENSTEIN_MOD_SATCHEL= +WOLFENSTEIN_MOD_SILENCED_COLT= +WOLFENSTEIN_MOD_SILENCER= +WOLFENSTEIN_MOD_SNIPERRIFLE= +WOLFENSTEIN_MOD_STEN= +WOLFENSTEIN_MOD_SUICIDE= +WOLFENSTEIN_MOD_SWITCHTEAM= +WOLFENSTEIN_MOD_THOMPSON= +WOLFENSTEIN_MOD_TRIGGER_HURT= +WOLFENSTEIN_MOD_UNKNOWN= +WOLFENSTEIN_MOD_VENOM= +WOLFENSTEIN_MOD_WATER= +[LogEntriesLOCATION] +COD1_head= +COD1_helmet= +COD1_left_arm_lower= +COD1_left_arm_upper= +COD1_left_foot= +COD1_left_hand= +COD1_left_leg_lower= +COD1_left_leg_upper= +COD1_neck= +COD1_none= +COD1_right_arm_lower= +COD1_right_arm_upper= +COD1_right_foot= +COD1_right_hand= +COD1_right_leg_lower= +COD1_right_leg_upper= +COD1_torso_lower= +COD1_torso_upper= +COD2_head= +COD2_helmet= +COD2_left_arm_lower= +COD2_left_arm_upper= +COD2_left_foot= +COD2_left_hand= +COD2_left_leg_lower= +COD2_left_leg_upper= +COD2_neck= +COD2_none= +COD2_right_arm_lower= +COD2_right_arm_upper= +COD2_right_foot= +COD2_right_hand= +COD2_right_leg_lower= +COD2_right_leg_upper= +COD2_torso_lower= +COD2_torso_upper= +COD4_head= +COD4_left_arm_lower= +COD4_left_arm_upper= +COD4_left_foot= +COD4_left_hand= +COD4_left_leg_lower= +COD4_left_leg_upper= +COD4_neck= +COD4_none= +COD4_right_arm_lower= +COD4_right_arm_upper= +COD4_right_foot= +COD4_right_hand= +COD4_right_leg_lower= +COD4_right_leg_upper= +COD4_torso_lower= +COD4_torso_upper= +cod5_head= +cod5_left_arm_lower= +cod5_left_arm_upper= +cod5_left_foot= +cod5_left_hand= +cod5_left_leg_lower= +cod5_left_leg_upper= +cod5_neck= +cod5_none= +cod5_right_arm_lower= +cod5_right_arm_upper= +cod5_right_foot= +cod5_right_hand= +cod5_right_leg_lower= +cod5_right_leg_upper= +cod5_torso_lower= +cod5_torso_upper= +MOHAA_= +QUAKEWARS_= +QUAKEWARS_gdf= +QUAKEWARS_strogg= +WOLFENSTEIN_= +[MessageCentreFormats] +awardadmiral_fire= +awardadmiral_gas= +AWARDadmiral_projectile=$1$^7 is the best with Project weapons with $2$ points +AWARDadmiral_purple_heart=$1$^7 keeps bleeding to death with $2$ points +awardadmiral_tnt= +AWARDgeneric_aimless=$1$^7 is the best with lucky kills with $2$ points +AWARDgeneric_airstrike=$1$^7 is the best with airstrikes with $2$ points +AWARDgeneric_daredevil=$1$^7 has done something stupid $2$ times +AWARDgeneric_deaths=$1$^7 has the most deaths per round at $2$ +AWARDgeneric_fall=$1$^7 has fallen to their deaths $2$ times +AWARDgeneric_grenade_killer=$1$^7 is the best with grenades with $2$ points +AWARDgeneric_grenade_magnet=$1$^7 likes to eat grenades the most with $2$ points +AWARDgeneric_headshots=$1$^7 has $2$ headshots +AWARDgeneric_kills=$1$^7 has the most kills per round at $2$ +AWARDgeneric_knife=$1$^7 has knifed $2$ people in the back +AWARDgeneric_large_caliber=$1$^7 is the best with highest Large Caliber Guns with $2$ +AWARDgeneric_marksman=$1$^7 has high accuracy rating with $2$ points +AWARDgeneric_ratio=$1$^7 has the best kills and deaths combination, $2$ points +AWARDgeneric_rpg=$1$^7 is the best with RPGs with $2$ points +AWARDgeneric_shotgun=$1$^7 is the best with shotguns with $2$ points +AWARDgeneric_sidearm=$1$^7 is the best with sidearms with $2$ points +AWARDgeneric_silencer=$1$^7 is the best with silenced weapons with $2$ points +AWARDgeneric_sniper=$1$^7 is the best with snipers with $2$ points +AWARDgeneric_speech=$1$^7 likes to talk the most with $2$ points +AWARDgeneric_suicide=$1$^7 could not take it anymore $2$ times +AWARDgeneric_wrongplace=$1$^7 has been in the wrong place at the wrong time the moost with $2$ points +AWARDmodern_acog=$1$^7 is the best with ACOG scoped weapons with $2$ points +AWARDmodern_assault=$1$^7 is the best with Assault weapons with $2$ points +AWARDmodern_explosives=$1$^7 is the best with explosives with $2$ points +AWARDmodern_explosives_magnet=$1$^7 likes to eat explosives the most with $2$ points +AWARDmodern_grenade_launcher=$1$^7 is the best with Grenade Launchers with $2$ points +AWARDmodern_grip=$1$^7 is the best with GRIP weapons with $2$ points +AWARDmodern_heavy_gun=$1$^7 is the best with Heavy Guns with $2$ points +AWARDmodern_helicopter=$1$^7 is the best with Helicopters with $2$ points +AWARDmodern_red_dot=$1$^7 is the best with Reflex scoped weapons with $2$ points +AWARDmodern_sub_machine_gun=$1$^7 is the best with Sub Machine Guns with $2$ points +AWARDquakewars_defenseturrets=Award: Defensive Turrets - $1$^7 with $2$ points +AWARDquakewars_firesupport=Award: Fire Support - $1$^7 with $2$ points +AWARDquakewars_flyingvehicles=Award: Flying Vehicles - $1$^7 with $2$ points +AWARDquakewars_grenademagnet=Award: Grenade Magnet - $1$^7 with $2$ points +AWARDquakewars_grenades=Award: Grenades - $1$^7 with $2$ points +AWARDquakewars_groundvehicles=Award: Ground Vehicles - $1$^7 with $2$ points +AWARDquakewars_meleeweapons=Award: Melee Weapons - $1$^7 with $2$ points +AWARDquakewars_primaryweapons=Award: Primary Weapons - $1$^7 with $2$ points +AWARDquakewars_sidearms=Award: Side Arms - $1$^7 with $2$ points +AWARDquakewars_xpbattlesense=Award: XP Battle Sense - $1$^7 with $2$ points +AWARDquakewars_xpcovertops=Award: XP Covert Ops - $1$^7 with $2$ points +AWARDquakewars_xpengineer=Award: XP Engineer - $1$^7 with $2$ points +AWARDquakewars_xpfieldops=Award: XP Field Ops - $1$^7 with $2$ points +AWARDquakewars_xpmedic=Award: XP Medic - $1$^7 with $2$ points +AWARDquakewars_xpsoldier=Award: XP Soldier - $1$^7 with $2$ points +AWARDquakewars_xpvehicle=Award: XP Vehicle Handling - $1$^7 with $2$ points +AWARDquakewars_xpweaponhandling=Award: XP Weapon Handling - $1$^7 with $2$ points +AWARDww2_american=$1$^7 is the best with American weapons with $2$ points +AWARDww2_bash=$1$^7 has $2$ bash kills +AWARDww2_bolt_action_rifles=$1$^7 is the best with Bolt Action Rifles with $2$ points +AWARDww2_british=$1$^7 is the best with British weapons with $2$ points +AWARDww2_fast_loading_rifles=$1$^7 is the best with Fast Loading Rifles with $2$ points +AWARDww2_german=$1$^7 is the best with German weapons with $2$ points +awardww2_large_machine_gun=$1$^7 is the best with Large Machine Guns with $2$ points +AWARDww2_russian=$1$^7 is the best with Russian weapons with $2$ points +AWARDww2_small_machine_gun=$1$^7 is the best with SMG weapons with $2$ points +TopDeaths=$1$^7 has died $2$ times and is the top of the rankings +TopDeathStreak=$1$^7 has been killed $2$ times in a row +TopKillDeathRatio=$1$^7 has the best kill to death ration of $2$ +TopKills=$1$^7 has made $2$ kills and is the top of the rankings +TopKillStreak=$1$^7 has killed $2$ people in a row +TopRoundsPlayed=$1$^7 has played $2$ rounds and needs to get a life +TopScore=$1$^7 has the highest score rating of $2$ +TopSkill=$1$^7 has the highest skill rating of $2$ +TopSuicides=$1$^7 has ended their own life $2$ times +TopTeamKills=$1$^7 has killed their team mates $2$ times +TopTeamKillStreak=$1$^7 has killed $2$ team mates in a row +TopTeamLosses=$1$^7 has been on the losing team $2$ times +TopTeamWins=$1$^7 has been on the winning team $2$ times +TopTimePlayed=$1$^7 has played for $2$ and needs to get a life +TopWeightedScore=$1$^7 has the top weighted skill of $2$ +TopWeightedSkill=$1$^7 has the top weighted score of $2$ +TopXPQUAKEWARS_battlesense=XP:Battlesense - $1$^7 with $2$ points +TopXPQUAKEWARS_covertops=XP:Covert Ops - $1$^7 with $2$ points +TopXPQUAKEWARS_engineer=XP:Engineer - $1$^7 with $2$ points +TopXPQUAKEWARS_fieldops=XP:Field Ops - $1$^7 with $2$ points +TopXPQUAKEWARS_medic=XP:Medic - $1$^7 with $2$ points +TopXPQUAKEWARS_soldier=XP:Soldier - $1$^7 with $2$ points +TopXPQUAKEWARS_vehicle=XP:Vehicle Handling - $1$^7 with $2$ points +TopXPQUAKEWARS_weapon_handling=XP:Weapon Handling - $1$^7 with $2$ points +[LogSubstituteACTION] +COD1_bas_attacked= +COD1_bas_breached= +COD1_bas_defend= +COD1_bas_defused= +COD1_bas_destroyed= +COD1_bas_planted= +COD1_bomb_defuse= +COD1_bomb_plant= +COD1_ctf_assist= +COD1_ctf_captured= +COD1_ctf_defended= +COD1_ctf_pickup= +COD1_ctf_returned= +COD1_ctf_take= +COD1_dom_captured= +cod1_re_capture= +cod1_re_pickup= +COD2_bomb_defuse= +COD2_bomb_plant= +cod2_ctf_assist= +cod2_ctf_captured= +cod2_ctf_defended= +cod2_ctf_pickup= +cod2_ctf_returned= +cod2_ctf_take= +cod2_hq_capture= +cod2_hq_defend= +cod2_hq_destroy= +COD2_htf_scored= +COD2_htf_stole= +COD2_sd_defend= +cod5_bd= +cod5_bp= +cod5_fc= +cod5_fr= +cod5_ft= +cod5_rc= +cod5_rd= +WOLFENSTEIN_dynamite_defuse= +WOLFENSTEIN_dynamite_plant= +[LogSubstituteAMMO] +COD1_MOD_ARTILLERY= +COD1_MOD_CRUSH_JEEP= +COD1_MOD_CRUSH_TANK= +COD1_MOD_EXPLOSIVE= +COD1_MOD_FALLING= +COD1_MOD_FLAME= +COD1_MOD_GRENADE_SPLASH= +COD1_MOD_HEAD_SHOT= +COD1_MOD_MELEE=COD1_BASH +COD1_MOD_MELEE_BINOCULARS=COD1_binoculars_mp +COD1_MOD_PISTOL_BULLET= +COD1_MOD_PROJECTILE= +COD1_MOD_PROJECTILE_SPLASH= +COD1_MOD_RIFLE_BULLET= +COD1_MOD_SUICIDE= +COD1_MOD_WATER= +COD2_MOD_EXPLOSIVE= +COD2_MOD_FALLING= +COD2_MOD_GRENADE_SPLASH= +COD2_MOD_HEAD_SHOT= +COD2_MOD_MELEE=COD2_BASH +COD2_MOD_PISTOL_BULLET= +COD2_MOD_PROJECTILE= +COD2_MOD_PROJECTILE_SPLASH= +COD2_MOD_RIFLE_BULLET= +COD2_MOD_SUICIDE= +COD2_MOD_TRIGGER_HURT= +COD4_MOD_EXPLOSIVE= +COD4_MOD_FALLING= +COD4_MOD_GRENADE= +COD4_MOD_GRENADE_SPLASH= +COD4_MOD_HEAD_SHOT= +COD4_MOD_IMPACT= +COD4_MOD_MELEE=COD4_BASH +COD4_MOD_PISTOL_BULLET= +COD4_MOD_PROJECTILE= +COD4_MOD_PROJECTILE_SPLASH= +COD4_MOD_RIFLE_BULLET= +COD4_MOD_SUICIDE= +COD4_MOD_TRIGGER_HURT= +cod5_mod_bayonet=cod5_bayonet +cod5_mod_burned= +cod5_mod_crush= +cod5_mod_explosive= +cod5_mod_falling= +cod5_mod_grenade= +cod5_mod_grenade_splash= +cod5_mod_head_shot= +cod5_mod_impact= +cod5_mod_melee=cod5_bash +cod5_mod_pistol_bullet= +cod5_mod_projectile= +cod5_mod_projectile_splash= +cod5_mod_rifle_bullet= +cod5_mod_suicide= +cod5_mod_trigger_hurt= +cod5_mod_unknown= +MOHAA_= +WOLFENSTEIN_= +[LogSubstituteGAMETYPE] +COD1_actf= +COD1_bas= +COD1_ctf= +COD1_dm= +COD1_dom= +COD1_hq= +COD1_re= +COD1_rsd= +COD1_sd= +COD1_tdm= +COD2_ctf= +COD2_dm= +COD2_esd= +COD2_hq= +COD2_htf= +COD2_sd= +COD2_tdm= +COD4_dm= +COD4_dom= +COD4_koth= +COD4_sab= +COD4_sd= +COD4_war= +COD5_ctf= +COD5_dm= +COD5_dom= +COD5_koth= +COD5_sab= +COD5_sd= +COD5_sur= +COD5_tdm= +COD5_twar= +MOHAA_obj= +MOHAA_objective-match= +WOLFENSTEIN_2= +WOLFENSTEIN_3= +WOLFENSTEIN_4= +WOLFENSTEIN_5= +WOLFENSTEIN_6= +WOLFENSTEIN_7= +[LogSubstituteMAP] +COD1_mp_arnhem= +COD1_mp_berlin= +COD1_mp_bocage= +COD1_mp_carentan= +COD1_mp_chateau= +COD1_mp_dawnville= +COD1_mp_foy= +COD1_mp_harbor= +COD1_mp_kharkov= +COD1_mp_neuville= +COD1_mp_pavlov= +COD1_mp_peaks= +COD1_mp_railyard= +COD1_mp_rhinevalley= +COD1_mp_sicily= +COD1_mp_streets= +COD1_mp_tigertown= +COD1_mp_uo_carentan= +COD1_mp_uo_dawnville= +COD1_mp_uo_depot= +COD1_mp_uo_harbor= +COD1_mp_uo_hurtgen= +COD1_mp_uo_stanjel= +COD2_mp_africorps= +COD2_mp_argentan_france= +COD2_mp_bastogne= +COD2_mp_belltown= +COD2_mp_berlin1= +COD2_mp_breakout= +COD2_mp_brecourt= +COD2_mp_burgundy= +COD2_mp_carentan= +COD2_mp_chateau= +COD2_mp_chateauday= +COD2_mp_cr_kasserine= +COD2_mp_dawnville= +COD2_mp_dawnville_cl_final= +COD2_mp_decoy= +COD2_mp_devils_den_beta= +COD2_mp_dock_assault= +COD2_mp_downtown= +COD2_mp_farmhouse= +COD2_mp_frantic2= +COD2_mp_gothic= +COD2_mp_harbor= +COD2_mp_hawk= +COD2_mp_highside= +COD2_mp_junobeach= +COD2_mp_kalstle_v2= +COD2_mp_leningrad= +COD2_mp_lflnchateau= +COD2_mp_maaloy_cod2= +COD2_mp_maaloy_cod2_final= +COD2_mp_matmata= +COD2_mp_mazza= +COD2_mp_montebourg= +COD2_mp_otara= +COD2_mp_provence2= +COD2_mp_railyard= +COD2_mp_slatmata= +COD2_mp_stanjel= +COD2_mp_the_tomb= +COD2_mp_toujane= +COD2_mp_trainstation= +COD2_mp_tunis= +COD2_mp_tunisia_dawn= +COD2_mp_vik1= +COD2_mp_villageraid= +COD2_mp_xfire_bay= +COD4_mp_backlot= +COD4_mp_bloc= +COD4_mp_bog= +COD4_mp_broadcast= +COD4_mp_carentan= +COD4_mp_cargoship= +COD4_mp_citystreets= +COD4_mp_convoy= +COD4_mp_countdown= +COD4_mp_crash= +COD4_mp_crash_snow= +COD4_mp_creek= +COD4_mp_crossfire= +COD4_mp_farm= +COD4_mp_killhouse= +COD4_mp_overgrown= +COD4_mp_pipeline= +COD4_mp_shipment= +COD4_mp_showdown= +COD4_mp_strike= +COD4_mp_vacant= +COD5_mp_airfield= +COD5_mp_asylum= +COD5_mp_castle= +COD5_mp_courtyard= +COD5_mp_dome= +COD5_mp_downfall= +COD5_mp_hangar= +COD5_mp_kneedeep= +COD5_mp_makin= +COD5_mp_makin_day= +COD5_mp_nachtfeuer= +COD5_mp_outskirts= +COD5_mp_roundhouse= +COD5_mp_seelow= +COD5_mp_shrine= +COD5_mp_suburban= +COD5_mp_subway= +MOHAA_= +MOHAA_obj_team1= +MOHAA_obj_team2= +MOHAA_obj_team4= +MOHAA_stlo= +WOLFENSTEIN_baserace_beta2= +WOLFENSTEIN_battery= +WOLFENSTEIN_braundorf_b3= +WOLFENSTEIN_ctf_multi= +WOLFENSTEIN_dubrovnik_b1= +WOLFENSTEIN_dubrovnik_final= +WOLFENSTEIN_et_ice= +WOLFENSTEIN_frostbite= +WOLFENSTEIN_fueldump= +WOLFENSTEIN_goldrush= +WOLFENSTEIN_infamy= +WOLFENSTEIN_kungfugrip= +WOLFENSTEIN_mp_ameland_final= +WOLFENSTEIN_mp_assault= +WOLFENSTEIN_mp_bankraid_final= +WOLFENSTEIN_mp_base= +WOLFENSTEIN_mp_beach= +WOLFENSTEIN_mp_bridge= +WOLFENSTEIN_mp_castle= +WOLFENSTEIN_mp_castle_siege= +WOLFENSTEIN_mp_checkpoint= +WOLFENSTEIN_mp_church= +WOLFENSTEIN_mp_destruction= +WOLFENSTEIN_mp_ice= +WOLFENSTEIN_mp_island= +WOLFENSTEIN_mp_murderhill= +WOLFENSTEIN_mp_resurrection= +WOLFENSTEIN_mp_schwalbe= +WOLFENSTEIN_mp_sub= +WOLFENSTEIN_mp_toxicity= +WOLFENSTEIN_mp_tram= +WOLFENSTEIN_mp_trenchtoast= +WOLFENSTEIN_mp_village= +WOLFENSTEIN_northpole= +WOLFENSTEIN_oasis= +WOLFENSTEIN_radar= +WOLFENSTEIN_railgun= +WOLFENSTEIN_raw_b3= +WOLFENSTEIN_rommel_b2= +WOLFENSTEIN_rommel_final= +WOLFENSTEIN_stalingrad= +WOLFENSTEIN_supplydepot2= +WOLFENSTEIN_tc_base= +WOLFENSTEIN_te_frostbite= +WOLFENSTEIN_te_tundrab2= +WOLFENSTEIN_te_ufo= +WOLFENSTEIN_toxic_speedball= +WOLFENSTEIN_tundra_rush_beta= +WOLFENSTEIN_uboot= +WOLFENSTEIN_vengeance_te_b4= +[LogSubstituteCLASS] +COD1_= +COD1_soldier= +COD2_= +COD2_soldier= +COD4_soldier= +cod5_= +cod5_soldier= +MOHAA_= +MOHAA_soldier= +WOLFENSTEIN_= +WOLFENSTEIN_0= +WOLFENSTEIN_1= +WOLFENSTEIN_2= +WOLFENSTEIN_3= +WOLFENSTEIN_4= +WOLFENSTEIN_7= +WOLFENSTEIN_soldier= +[LogSubstituteTEAM] +COD1_= +COD1_allies= +COD1_axis= +COD1_playerteam= +COD1_targetteam= +COD2_= +COD2_allies= +COD2_axis= +COD2_playerteam= +COD2_spectator= +COD2_targetteam= +COD4_allies= +COD4_axis= +COD4_playerteam= +COD4_targetteam= +cod5_= +COD5_allies= +COD5_axis= +COD5_playerteam= +COD5_spectator= +COD5_targetteam= +MOHAA_allies= +MOHAA_axis= +MOHAA_playerteam= +MOHAA_targetteam= +STATSGENWORLDTEAM= +WOLFENSTEIN_1= +WOLFENSTEIN_2= +WOLFENSTEIN_3= +[LogSubstituteWEAPON] +COD1_30cal_tank_mp= +COD1_50cal_tank_mp= +COD1_bar_mp= +COD1_bar_slow_mp= +COD1_bazooka_mp= +COD1_binoculars_artillery_mp= +COD1_binoculars_mp= +COD1_bren_mp= +COD1_colt_mp= +COD1_dp28_mp= +COD1_elefant_turret_mp= +COD1_enfield_mp= +COD1_flak88_turret_mp= +COD1_flamethrower_mp= +COD1_fraggrenade_mp= +COD1_gewehr43_mp= +COD1_kar98k_mp= +COD1_kar98k_sniper_mp= +COD1_luger_mp= +COD1_m1carbine_mp= +COD1_m1garand_mp= +COD1_mg30cal_mp= +COD1_mg34_mp= +COD1_mg34_tank_mp= +COD1_mg42_bipod_duck_mp= +COD1_mg42_bipod_stand_mp= +COD1_mg42_turret_mp= +COD1_mk1britishfrag_mp= +COD1_mod_crush_jeep= +COD1_mod_explosive= +COD1_mod_falling= +COD1_mod_flame= +COD1_mod_suicide= +COD1_mod_water= +COD1_mosin_nagant_mp= +COD1_mosin_nagant_sniper_mp= +COD1_mp40_mp= +COD1_mp44_mp= +COD1_mp44_semi_mp= +COD1_panzerfaust_mp= +COD1_panzeriv_turret_mp= +COD1_panzerschreck_mp= +COD1_ppsh_mp= +COD1_ppsh_semi_mp= +COD1_ptrs41_antitank_rifle_mp= +COD1_rgd_33russianfrag_mp= +COD1_satchelcharge_mp= +COD1_sg43_tank_mp= +COD1_sg43_turret_mp= +COD1_sherman_turret_mp= +COD1_springfield_mp= +COD1_sten_mp= +COD1_sten_silenced_mp= +COD1_stielhandgranate_mp= +COD1_su152_turret_mp= +COD1_svt40_mp= +COD1_t34_turret_mp= +COD1_thompson_mp= +COD1_tt33_mp= +COD1_webley_mp= +COD2_30cal_stand_mp= +COD2_bar_mp= +COD2_bren_mp= +COD2_colt_mp= +COD2_cook_frag_grenade_american_mp= +COD2_cook_frag_grenade_british_mp= +COD2_cook_frag_grenade_german_mp= +COD2_cook_frag_grenade_russian_mp= +COD2_enfield_mp= +COD2_enfield_scope_mp= +COD2_frag_grenade_american_mp= +COD2_frag_grenade_german_mp= +cod2_frag_type1_american_mp= +cod2_frag_type1_british_mp= +cod2_frag_type1_german_mp= +cod2_frag_type1_russian_mp= +COD2_g43_mp= +COD2_greasegun_mp= +COD2_kar98k_mp= +COD2_kar98k_sniper_mp= +COD2_luger_mp= +COD2_m1carbine_mp= +COD2_m1garand_mp= +COD2_mg42_bipod_duck_mp= +COD2_mg42_bipod_stand_mp= +COD2_mod_explosive= +COD2_mod_falling= +COD2_mod_head_shot= +COD2_mod_rifle_bullet= +COD2_mod_suicide= +COD2_mod_trigger_hurt= +COD2_mosin_nagant_mp= +COD2_mosin_nagant_sniper_mp= +COD2_mp40_mp= +COD2_mp44_mp= +COD2_panzerschreck_mp= +COD2_pps42_mp= +COD2_ppsh_mp= +COD2_shotgun_mp= +COD2_springfield_mp= +COD2_sten_mp= +COD2_svt40_mp= +COD2_thompson_mp= +COD2_tt30_mp= +COD2_webley_mp= +COD4_ak47_acog_mp= +COD4_ak47_gl_mp= +COD4_ak47_mp= +COD4_ak47_reflex_mp= +COD4_ak47_silencer_mp= +COD4_ak74u_acog_mp= +COD4_ak74u_mp= +COD4_ak74u_reflex_mp= +COD4_ak74u_silencer_mp= +COD4_artillery_mp= +COD4_barrett_acog_mp= +COD4_barrett_mp= +COD4_beretta_mp= +COD4_beretta_silencer_mp= +COD4_c4_mp= +COD4_claymore_mp= +COD4_cobra_20mm_mp= +COD4_cobra_ffar_mp= +COD4_colt45_mp= +COD4_colt45_silencer_mp= +COD4_concussion_grenade_mp= +COD4_deserteagle_mp= +COD4_deserteaglegold_mp= +COD4_destructible_car= +COD4_dragunov_acog_mp= +COD4_dragunov_mp= +COD4_flash_grenade_mp= +COD4_frag_grenade_mp= +COD4_frag_grenade_short_mp= +COD4_g36c_acog_mp= +COD4_g36c_gl_mp= +COD4_g36c_mp= +COD4_g36c_reflex_mp= +COD4_g36c_silencer_mp= +COD4_g3_acog_mp= +COD4_g3_gl_mp= +COD4_g3_mp= +COD4_g3_reflex_mp= +COD4_g3_silencer_mp= +COD4_gl_ak47_mp= +COD4_gl_g36c_mp= +COD4_gl_g3_mp= +COD4_gl_m14_mp= +COD4_gl_m16_mp= +COD4_gl_m4_mp= +COD4_hind_ffar_mp= +COD4_m1014_grip_mp= +COD4_m1014_mp= +COD4_m1014_reflex_mp= +COD4_m14_acog_mp= +COD4_m14_gl_mp= +COD4_m14_mp= +COD4_m14_reflex_mp= +COD4_m14_silencer_mp= +COD4_m16_acog_mp= +COD4_m16_gl_mp= +COD4_m16_mp= +COD4_m16_reflex_mp= +COD4_m16_silencer_mp= +COD4_m21_acog_mp= +COD4_m21_mp= +COD4_m40a3_acog_mp= +COD4_m40a3_mp= +COD4_m4_acog_mp= +COD4_m4_gl_mp= +COD4_m4_mp= +COD4_m4_reflex_mp= +COD4_m4_silencer_mp= +COD4_m60e4_acog_mp= +COD4_m60e4_grip_mp= +COD4_m60e4_mp= +COD4_m60e4_reflex_mp= +COD4_mod_explosive= +COD4_mod_falling= +COD4_mod_head_shot= +COD4_mod_melee= +COD4_mod_pistol_bullet= +COD4_mod_rifle_bullet= +COD4_mod_suicide= +COD4_mod_trigger_hurt= +COD4_mp44_mp= +COD4_mp5_acog_mp= +COD4_mp5_mp= +COD4_mp5_reflex_mp= +COD4_mp5_silencer_mp= +COD4_p90_acog_mp= +COD4_p90_mp= +COD4_p90_reflex_mp= +COD4_p90_silencer_mp= +COD4_remington700_acog_mp= +COD4_remington700_mp= +COD4_rpd_acog_mp= +COD4_rpd_grip_mp= +COD4_rpd_mp= +COD4_rpd_reflex_mp= +COD4_rpg_mp= +COD4_saw_acog_mp= +COD4_saw_bipod_crouch_mp= +COD4_saw_bipod_stand_mp= +COD4_saw_grip_mp= +COD4_saw_mp= +COD4_saw_reflex_mp= +COD4_skorpion_acog_mp= +COD4_skorpion_mp= +COD4_skorpion_reflex_mp= +COD4_skorpion_silencer_mp= +COD4_smoke_grenade_mp= +COD4_usp_mp= +COD4_usp_silencer_mp= +COD4_uzi_acog_mp= +COD4_uzi_mp= +COD4_uzi_reflex_mp= +COD4_uzi_silencer_mp= +COD4_winchester1200_grip_mp= +COD4_winchester1200_mp= +COD4_winchester1200_reflex_mp= +cod5_30cal_bipod_crouch_mp= +cod5_30cal_bipod_mp= +cod5_30cal_bipod_prone_mp= +cod5_30cal_bipod_stand_mp= +cod5_30cal_mp= +cod5_357magnum_mp= +cod5_artillery_mp= +cod5_bar_bipod_crouch_mp= +cod5_bar_bipod_mp= +cod5_bar_bipod_prone_mp= +cod5_bar_bipod_stand_mp= +cod5_bar_mp= +cod5_bazooka_mp= +cod5_briefcase_bomb_mp= +cod5_colt_mp= +cod5_destructible_car= +cod5_dog_bite_mp= +cod5_doublebarreledshotgun_grip_mp= +cod5_doublebarreledshotgun_mp= +cod5_doublebarreledshotgun_sawoff_mp= +cod5_dp28_bipod_crouch_mp= +cod5_dp28_bipod_mp= +cod5_dp28_bipod_prone_mp= +cod5_dp28_bipod_stand_mp= +cod5_dp28_mp= +cod5_explodable_barrel= +cod5_fg42_bipod_crouch_mp= +cod5_fg42_bipod_mp= +cod5_fg42_bipod_prone_mp= +cod5_fg42_bipod_stand_mp= +cod5_fg42_mp= +cod5_fg42_telescopic_mp= +cod5_frag_grenade_mp= +cod5_frag_grenade_short_mp= +cod5_gewehr43_aperture_mp= +cod5_gewehr43_gl_mp= +cod5_gewehr43_mp= +cod5_gewehr43_silenced_mp= +cod5_gewehr43_telescopic_mp= +cod5_gl_gewehr43_mp= +cod5_gl_kar98k_mp= +cod5_gl_m1garand_mp= +cod5_gl_mosinrifle_mp= +cod5_gl_springfield_mp= +cod5_gl_type99rifle_mp= +cod5_kar98k_bayonet_mp= +cod5_kar98k_gl_mp= +cod5_kar98k_mp= +cod5_kar98k_scoped_mp= +cod5_m1carbine_aperture_mp= +cod5_m1carbine_bayonet_mp= +cod5_m1carbine_bigammo_mp= +cod5_m1carbine_flash_mp= +cod5_m1carbine_mp= +cod5_m1garand_bayonet_mp= +cod5_m1garand_flash_mp= +cod5_m1garand_gl_mp= +cod5_m1garand_mp= +cod5_m1garand_scoped_mp= +cod5_m2_flamethrower_mp= +cod5_m8_white_smoke_mp= +cod5_mg42_bipod_crouch_mp= +cod5_mg42_bipod_mp= +cod5_mg42_bipod_prone_mp= +cod5_mg42_bipod_stand_mp= +cod5_mg42_mp= +cod5_mine_bouncing_betty_mp= +cod5_mod_burned= +cod5_mod_explosive= +cod5_mod_falling= +cod5_mod_melee= +cod5_mod_suicide= +cod5_mod_trigger_hurt= +cod5_molotov_mp= +cod5_mosinrifle_bayonet_mp= +cod5_mosinrifle_gl_mp= +cod5_mosinrifle_mp= +cod5_mosinrifle_scoped_mp= +cod5_mp40_aperture_mp= +cod5_mp40_bigammo_mp= +cod5_mp40_mp= +cod5_mp40_silenced_mp= +cod5_nambu_mp= +cod5_panzer4_gunner_front_mp= +cod5_panzer4_gunner_mp= +cod5_panzer4_mp_explosion_mp= +cod5_panzer4_turret_mp= +cod5_ppsh_aperture_mp= +cod5_ppsh_bigammo_mp= +cod5_ppsh_mp= +cod5_ptrs41_mp= +cod5_satchel_charge_mp= +cod5_shotgun_bayonet_mp= +cod5_shotgun_grip_mp= +cod5_shotgun_mp= +cod5_signal_flare_mp= +cod5_springfield_bayonet_mp= +cod5_springfield_gl_mp= +cod5_springfield_mp= +cod5_springfield_scoped_mp= +cod5_stg44_aperture_mp= +cod5_stg44_flash_mp= +cod5_stg44_mp= +cod5_stg44_telescopic_mp= +cod5_sticky_grenade_mp= +cod5_svt40_aperture_mp= +cod5_svt40_flash_mp= +cod5_svt40_mp= +cod5_svt40_telescopic_mp= +cod5_t34_gunner_front_mp= +cod5_t34_gunner_mp= +cod5_t34_mp_explosion_mp= +cod5_t34_turret_mp= +cod5_tabun_gas_mp= +cod5_thompson_aperture_mp= +cod5_thompson_bigammo_mp= +cod5_thompson_mp= +cod5_thompson_silenced_mp= +cod5_tokarev_mp= +cod5_type100smg_aperture_mp= +cod5_type100smg_bigammo_mp= +cod5_type100smg_mp= +cod5_type100smg_silenced_mp= +cod5_type99_lmg_bipod_crouch_mp= +cod5_type99_lmg_bipod_prone_mp= +cod5_type99_lmg_bipod_stand_mp= +cod5_type99lmg_bayonet_mp= +cod5_type99lmg_bipod_mp= +cod5_type99lmg_mp= +cod5_type99rifle_bayonet_mp= +cod5_type99rifle_gl_mp= +cod5_type99rifle_mp= +cod5_type99rifle_scoped_mp= +cod5_walther_mp= +MOHAA_clubbed= +MOHAA_grenade= +MOHAA_mg= +MOHAA_mine= +MOHAA_pistol= +MOHAA_rifle= +MOHAA_smg= +MOHAA_sniper= +MOHAA_suicide= +WOLFENSTEIN_mod_airstrike= +WOLFENSTEIN_mod_akimbo_colt= +WOLFENSTEIN_mod_akimbo_luger= +WOLFENSTEIN_mod_artillery= +WOLFENSTEIN_mod_arty= +WOLFENSTEIN_mod_browning= +WOLFENSTEIN_mod_carbine= +WOLFENSTEIN_mod_colt= +WOLFENSTEIN_mod_crush= +WOLFENSTEIN_mod_crush_construction= +WOLFENSTEIN_mod_crush_constructiondeath_noattacker= +WOLFENSTEIN_mod_dynamite= +WOLFENSTEIN_mod_dynamite_splash= +WOLFENSTEIN_mod_explosive= +WOLFENSTEIN_mod_falling= +WOLFENSTEIN_mod_fg42= +WOLFENSTEIN_mod_fg42scope= +WOLFENSTEIN_mod_flamethrower= +WOLFENSTEIN_mod_garand= +WOLFENSTEIN_mod_garand_scope= +WOLFENSTEIN_mod_goomba= +WOLFENSTEIN_mod_gpg40= +WOLFENSTEIN_mod_grenade= +WOLFENSTEIN_mod_grenade_launcher= +WOLFENSTEIN_mod_grenade_splash= +WOLFENSTEIN_mod_k43= +WOLFENSTEIN_mod_k43_scope= +WOLFENSTEIN_mod_kar98= +WOLFENSTEIN_mod_kicked= +WOLFENSTEIN_mod_knife= +WOLFENSTEIN_mod_knife_stealth= +WOLFENSTEIN_mod_landmine= +WOLFENSTEIN_mod_luger= +WOLFENSTEIN_mod_m7= +WOLFENSTEIN_mod_machinegun= +WOLFENSTEIN_mod_mauser= +WOLFENSTEIN_mod_mg42= +WOLFENSTEIN_mod_mobile_mg42= +WOLFENSTEIN_mod_mortar= +WOLFENSTEIN_mod_mortar_splash= +WOLFENSTEIN_mod_mp40= +WOLFENSTEIN_mod_panzerfaust= +WOLFENSTEIN_mod_poison= +WOLFENSTEIN_mod_rocket= +WOLFENSTEIN_mod_rocket_splash= +WOLFENSTEIN_mod_satchel= +WOLFENSTEIN_mod_silenced_colt= +WOLFENSTEIN_mod_silencer= +WOLFENSTEIN_mod_sniperrifle= +WOLFENSTEIN_mod_sten= +WOLFENSTEIN_mod_suicide= +WOLFENSTEIN_mod_switchteam= +WOLFENSTEIN_mod_thompson= +WOLFENSTEIN_mod_trigger_hurt= +WOLFENSTEIN_mod_unknown= +WOLFENSTEIN_mod_venom= +WOLFENSTEIN_mod_water= +[LogSubstituteWEAPONAMMO] +COD1_30cal_tank_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_30cal_tank_mpCOD1_MOD_RIFLE_BULLET= +COD1_50cal_tank_mpCOD1_MOD_HEAD_SHOT= +COD1_50cal_tank_mpCOD1_MOD_RIFLE_BULLET= +COD1_bar_mpCOD1_MOD_HEAD_SHOT= +COD1_bar_mpCOD1_MOD_RIFLE_BULLET= +COD1_bar_slow_mpCOD1_MOD_HEAD_SHOT= +COD1_bar_slow_mpCOD1_MOD_RIFLE_BULLET= +COD1_bazooka_mpCOD1_MOD_EXPLOSIVE= +COD1_bazooka_mpCOD1_MOD_PROJECTILE= +COD1_bazooka_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_binoculars_artillery_mpCOD1_MOD_ARTILLERY= +COD1_binoculars_artillery_mpCOD1_MOD_MELEE_BINOCULARS= +COD1_binoculars_mpCOD1_MOD_MELEE_BINOCULARS= +COD1_bren_mpCOD1_MOD_HEAD_SHOT= +COD1_bren_mpCOD1_MOD_RIFLE_BULLET= +COD1_colt_mpCOD1_MOD_HEAD_SHOT= +COD1_colt_mpCOD1_MOD_PISTOL_BULLET= +COD1_dp28_mpCOD1_MOD_HEAD_SHOT= +COD1_dp28_mpCOD1_MOD_RIFLE_BULLET= +COD1_elefant_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_elefant_turret_mpCOD1_MOD_PROJECTILE= +COD1_elefant_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_enfield_mpCOD1_MOD_HEAD_SHOT= +COD1_enfield_mpCOD1_MOD_MELEE= +COD1_enfield_mpCOD1_MOD_RIFLE_BULLET= +COD1_flak88_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_flak88_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_flamethrower_mpCOD1_MOD_FLAME= +COD1_flamethrower_mpCOD1_MOD_MELEE= +COD1_fraggrenade_mpCOD1_MOD_GRENADE_SPLASH= +COD1_gewehr43_mpCOD1_MOD_HEAD_SHOT= +COD1_gewehr43_mpCOD1_MOD_MELEE= +COD1_gewehr43_mpCOD1_MOD_RIFLE_BULLET= +COD1_kar98k_mpCOD1_MOD_HEAD_SHOT= +COD1_kar98k_mpCOD1_MOD_MELEE= +COD1_kar98k_mpCOD1_MOD_RIFLE_BULLET= +COD1_kar98k_sniper_mpCOD1_MOD_HEAD_SHOT= +COD1_kar98k_sniper_mpCOD1_MOD_MELEE= +COD1_kar98k_sniper_mpCOD1_MOD_RIFLE_BULLET= +COD1_luger_mpCOD1_MOD_HEAD_SHOT= +COD1_luger_mpCOD1_MOD_MELEE= +COD1_luger_mpCOD1_MOD_PISTOL_BULLET= +COD1_m1carbine_mpCOD1_MOD_HEAD_SHOT= +COD1_m1carbine_mpCOD1_MOD_MELEE= +COD1_m1carbine_mpCOD1_MOD_RIFLE_BULLET= +COD1_m1garand_mpCOD1_MOD_HEAD_SHOT= +COD1_m1garand_mpCOD1_MOD_MELEE= +COD1_m1garand_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg30cal_mpCOD1_MOD_HEAD_SHOT= +COD1_mg30cal_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg34_mpCOD1_MOD_HEAD_SHOT= +COD1_mg34_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg34_tank_mpCOD1_MOD_HEAD_SHOT= +COD1_mg34_tank_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_mg34_tank_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg42_bipod_duck_mpCOD1_MOD_HEAD_SHOT= +COD1_mg42_bipod_duck_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg42_bipod_stand_mpCOD1_MOD_EXPLOSIVE= +COD1_mg42_bipod_stand_mpCOD1_MOD_GRENADE_SPLASH= +COD1_mg42_bipod_stand_mpCOD1_MOD_HEAD_SHOT= +COD1_mg42_bipod_stand_mpCOD1_MOD_RIFLE_BULLET= +COD1_mg42_turret_mpCOD1_MOD_HEAD_SHOT= +COD1_mg42_turret_mpCOD1_MOD_RIFLE_BULLET= +COD1_mk1britishfrag_mpCOD1_MOD_GRENADE_SPLASH= +COD1_mod_crush_jeepCOD1_MOD_CRUSH_JEEP= +COD1_mod_explosiveCOD1_MOD_EXPLOSIVE= +COD1_mod_fallingCOD1_MOD_FALLING= +COD1_mod_flameCOD1_MOD_FLAME= +COD1_mod_suicideCOD1_MOD_SUICIDE= +COD1_mod_waterCOD1_MOD_WATER= +COD1_mosin_nagant_mpCOD1_MOD_HEAD_SHOT= +COD1_mosin_nagant_mpCOD1_MOD_MELEE= +COD1_mosin_nagant_mpCOD1_MOD_RIFLE_BULLET= +COD1_mosin_nagant_sniper_mpCOD1_MOD_HEAD_SHOT= +COD1_mosin_nagant_sniper_mpCOD1_MOD_MELEE= +COD1_mosin_nagant_sniper_mpCOD1_MOD_RIFLE_BULLET= +COD1_mp40_mpCOD1_MOD_EXPLOSIVE= +COD1_mp40_mpCOD1_MOD_HEAD_SHOT= +COD1_mp40_mpCOD1_MOD_PISTOL_BULLET= +COD1_mp44_mpCOD1_MOD_EXPLOSIVE= +COD1_mp44_mpCOD1_MOD_HEAD_SHOT= +COD1_mp44_mpCOD1_MOD_MELEE= +COD1_mp44_mpCOD1_MOD_PISTOL_BULLET= +COD1_mp44_semi_mpCOD1_MOD_HEAD_SHOT= +COD1_mp44_semi_mpCOD1_MOD_MELEE= +COD1_mp44_semi_mpCOD1_MOD_PISTOL_BULLET= +COD1_panzerfaust_mpCOD1_MOD_EXPLOSIVE= +COD1_panzerfaust_mpCOD1_MOD_PROJECTILE= +COD1_panzerfaust_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_panzeriv_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_panzeriv_turret_mpCOD1_MOD_PROJECTILE= +COD1_panzeriv_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_panzerschreck_mpCOD1_MOD_EXPLOSIVE= +COD1_panzerschreck_mpCOD1_MOD_PROJECTILE= +COD1_panzerschreck_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_ppsh_mpCOD1_MOD_HEAD_SHOT= +COD1_ppsh_mpCOD1_MOD_MELEE= +COD1_ppsh_mpCOD1_MOD_PISTOL_BULLET= +COD1_ppsh_semi_mpCOD1_MOD_HEAD_SHOT= +COD1_ppsh_semi_mpCOD1_MOD_PISTOL_BULLET= +COD1_ptrs41_antitank_rifle_mpCOD1_MOD_EXPLOSIVE= +COD1_ptrs41_antitank_rifle_mpCOD1_MOD_PROJECTILE= +COD1_ptrs41_antitank_rifle_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_rgd_33russianfrag_mpCOD1_MOD_GRENADE_SPLASH= +COD1_satchelcharge_mpCOD1_MOD_EXPLOSIVE= +COD1_satchelcharge_mpCOD1_MOD_GRENADE_SPLASH= +COD1_sg43_tank_mpCOD1_MOD_PROJECTILE= +COD1_sg43_tank_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_sg43_tank_mpCOD1_MOD_RIFLE_BULLET= +COD1_sg43_turret_mpCOD1_MOD_CRUSH_JEEP= +COD1_sg43_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_sg43_turret_mpCOD1_MOD_HEAD_SHOT= +COD1_sg43_turret_mpCOD1_MOD_RIFLE_BULLET= +COD1_sherman_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_sherman_turret_mpCOD1_MOD_PROJECTILE= +COD1_sherman_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_springfield_mpCOD1_MOD_HEAD_SHOT= +COD1_springfield_mpCOD1_MOD_MELEE= +COD1_springfield_mpCOD1_MOD_RIFLE_BULLET= +COD1_sten_mpCOD1_MOD_HEAD_SHOT= +COD1_sten_mpCOD1_MOD_PISTOL_BULLET= +COD1_sten_silenced_mpCOD1_MOD_HEAD_SHOT= +COD1_sten_silenced_mpCOD1_MOD_MELEE= +COD1_sten_silenced_mpCOD1_MOD_PISTOL_BULLET= +COD1_stielhandgranate_mpCOD1_MOD_EXPLOSIVE= +COD1_stielhandgranate_mpCOD1_MOD_GRENADE_SPLASH= +COD1_su152_turret_mpCOD1_MOD_CRUSH_TANK= +COD1_su152_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_su152_turret_mpCOD1_MOD_PROJECTILE= +COD1_su152_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_svt40_mpCOD1_MOD_HEAD_SHOT= +COD1_svt40_mpCOD1_MOD_MELEE= +COD1_svt40_mpCOD1_MOD_RIFLE_BULLET= +COD1_t34_turret_mpCOD1_MOD_EXPLOSIVE= +COD1_t34_turret_mpCOD1_MOD_PROJECTILE= +COD1_t34_turret_mpCOD1_MOD_PROJECTILE_SPLASH= +COD1_thompson_mpCOD1_MOD_HEAD_SHOT= +COD1_thompson_mpCOD1_MOD_MELEE= +COD1_thompson_mpCOD1_MOD_PISTOL_BULLET= +COD1_tt33_mpCOD1_MOD_HEAD_SHOT= +COD1_tt33_mpCOD1_MOD_MELEE= +COD1_tt33_mpCOD1_MOD_PISTOL_BULLET= +COD1_webley_mpCOD1_MOD_HEAD_SHOT= +COD1_webley_mpCOD1_MOD_MELEE= +COD1_webley_mpCOD1_MOD_PISTOL_BULLET= +COD2_30cal_stand_mpCOD2_MOD_EXPLOSIVE= +COD2_30cal_stand_mpCOD2_MOD_GRENADE_SPLASH= +COD2_30cal_stand_mpCOD2_MOD_HEAD_SHOT= +COD2_30cal_stand_mpCOD2_MOD_RIFLE_BULLET= +COD2_bar_mpCOD2_MOD_HEAD_SHOT= +COD2_bar_mpCOD2_MOD_MELEE= +COD2_bar_mpCOD2_MOD_RIFLE_BULLET= +COD2_bren_mpCOD2_MOD_HEAD_SHOT= +COD2_bren_mpCOD2_MOD_MELEE= +COD2_bren_mpCOD2_MOD_RIFLE_BULLET= +COD2_colt_mpCOD2_MOD_HEAD_SHOT= +COD2_colt_mpCOD2_MOD_MELEE= +COD2_colt_mpCOD2_MOD_PISTOL_BULLET= +COD2_cook_frag_grenade_american_mpCOD2_MOD_GRENADE_SPLASH= +COD2_cook_frag_grenade_british_mpCOD2_MOD_GRENADE_SPLASH= +COD2_cook_frag_grenade_german_mpCOD2_MOD_GRENADE_SPLASH= +COD2_cook_frag_grenade_russian_mpCOD2_MOD_GRENADE_SPLASH= +COD2_enfield_mpCOD2_MOD_HEAD_SHOT= +COD2_enfield_mpCOD2_MOD_MELEE= +COD2_enfield_mpCOD2_MOD_RIFLE_BULLET= +COD2_enfield_scope_mpCOD2_MOD_HEAD_SHOT= +COD2_enfield_scope_mpCOD2_MOD_MELEE= +COD2_enfield_scope_mpCOD2_MOD_RIFLE_BULLET= +COD2_frag_grenade_american_mpCOD2_MOD_GRENADE_SPLASH= +COD2_frag_grenade_german_mpCOD2_MOD_GRENADE_SPLASH= +cod2_frag_type1_american_mpcod2_mod_grenade_splash= +cod2_frag_type1_british_mpcod2_mod_grenade_splash= +cod2_frag_type1_german_mpcod2_mod_grenade_splash= +cod2_frag_type1_russian_mpcod2_mod_grenade_splash= +COD2_g43_mpCOD2_MOD_HEAD_SHOT= +COD2_g43_mpCOD2_MOD_MELEE= +COD2_g43_mpCOD2_MOD_RIFLE_BULLET= +COD2_greasegun_mpCOD2_MOD_HEAD_SHOT= +COD2_greasegun_mpCOD2_MOD_MELEE= +COD2_greasegun_mpCOD2_MOD_PISTOL_BULLET= +COD2_kar98k_mpCOD2_MOD_HEAD_SHOT= +COD2_kar98k_mpCOD2_MOD_MELEE= +COD2_kar98k_mpCOD2_MOD_RIFLE_BULLET= +COD2_kar98k_sniper_mpCOD2_MOD_HEAD_SHOT= +COD2_kar98k_sniper_mpCOD2_MOD_MELEE= +COD2_kar98k_sniper_mpCOD2_MOD_RIFLE_BULLET= +COD2_luger_mpCOD2_MOD_HEAD_SHOT= +COD2_luger_mpCOD2_MOD_MELEE= +COD2_luger_mpCOD2_MOD_PISTOL_BULLET= +COD2_m1carbine_mpCOD2_MOD_HEAD_SHOT= +COD2_m1carbine_mpCOD2_MOD_MELEE= +COD2_m1carbine_mpCOD2_MOD_PISTOL_BULLET= +COD2_m1garand_mpCOD2_MOD_HEAD_SHOT= +COD2_m1garand_mpCOD2_MOD_MELEE= +COD2_m1garand_mpCOD2_MOD_RIFLE_BULLET= +COD2_mg42_bipod_duck_mpCOD2_MOD_EXPLOSIVE= +COD2_mg42_bipod_duck_mpCOD2_MOD_GRENADE_SPLASH= +COD2_mg42_bipod_duck_mpCOD2_MOD_HEAD_SHOT= +COD2_mg42_bipod_duck_mpCOD2_MOD_RIFLE_BULLET= +COD2_mg42_bipod_stand_mpCOD2_MOD_EXPLOSIVE= +COD2_mg42_bipod_stand_mpCOD2_MOD_GRENADE_SPLASH= +COD2_mg42_bipod_stand_mpCOD2_MOD_HEAD_SHOT= +COD2_mg42_bipod_stand_mpCOD2_MOD_RIFLE_BULLET= +COD2_mod_explosiveCOD2_MOD_EXPLOSIVE= +COD2_mod_fallingCOD2_MOD_FALLING= +COD2_mod_head_shotCOD2_MOD_HEAD_SHOT= +COD2_mod_rifle_bulletCOD2_MOD_RIFLE_BULLET= +COD2_mod_suicideCOD2_MOD_SUICIDE= +COD2_mod_trigger_hurtCOD2_MOD_TRIGGER_HURT= +COD2_mosin_nagant_mpCOD2_MOD_HEAD_SHOT= +COD2_mosin_nagant_mpCOD2_MOD_MELEE= +COD2_mosin_nagant_mpCOD2_MOD_RIFLE_BULLET= +COD2_mosin_nagant_sniper_mpCOD2_MOD_HEAD_SHOT= +COD2_mosin_nagant_sniper_mpCOD2_MOD_MELEE= +COD2_mosin_nagant_sniper_mpCOD2_MOD_RIFLE_BULLET= +COD2_mp40_mpCOD2_MOD_HEAD_SHOT= +COD2_mp40_mpCOD2_MOD_MELEE= +COD2_mp40_mpCOD2_MOD_PISTOL_BULLET= +COD2_mp44_mpCOD2_MOD_HEAD_SHOT= +COD2_mp44_mpCOD2_MOD_MELEE= +COD2_mp44_mpCOD2_MOD_RIFLE_BULLET= +COD2_panzerschreck_mpCOD2_MOD_MELEE= +COD2_panzerschreck_mpCOD2_MOD_PROJECTILE= +COD2_panzerschreck_mpCOD2_MOD_PROJECTILE_SPLASH= +COD2_pps42_mpCOD2_MOD_HEAD_SHOT= +COD2_pps42_mpCOD2_MOD_MELEE= +COD2_pps42_mpCOD2_MOD_PISTOL_BULLET= +COD2_ppsh_mpCOD2_MOD_HEAD_SHOT= +COD2_ppsh_mpCOD2_MOD_MELEE= +COD2_ppsh_mpCOD2_MOD_PISTOL_BULLET= +COD2_shotgun_mpCOD2_MOD_HEAD_SHOT= +COD2_shotgun_mpCOD2_MOD_MELEE= +COD2_shotgun_mpCOD2_MOD_PISTOL_BULLET= +COD2_springfield_mpCOD2_MOD_HEAD_SHOT= +COD2_springfield_mpCOD2_MOD_MELEE= +COD2_springfield_mpCOD2_MOD_RIFLE_BULLET= +COD2_sten_mpCOD2_MOD_HEAD_SHOT= +COD2_sten_mpCOD2_MOD_MELEE= +COD2_sten_mpCOD2_MOD_PISTOL_BULLET= +COD2_svt40_mpCOD2_MOD_HEAD_SHOT= +COD2_svt40_mpCOD2_MOD_MELEE= +COD2_svt40_mpCOD2_MOD_RIFLE_BULLET= +COD2_thompson_mpCOD2_MOD_HEAD_SHOT= +COD2_thompson_mpCOD2_MOD_MELEE= +COD2_thompson_mpCOD2_MOD_PISTOL_BULLET= +COD2_tt30_mpCOD2_MOD_HEAD_SHOT= +COD2_tt30_mpCOD2_MOD_MELEE= +COD2_tt30_mpCOD2_MOD_PISTOL_BULLET= +COD2_webley_mpCOD2_MOD_HEAD_SHOT= +COD2_webley_mpCOD2_MOD_MELEE= +COD2_webley_mpCOD2_MOD_PISTOL_BULLET= +COD4_ak47_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_ak47_acog_mpCOD4_MOD_MELEE= +COD4_ak47_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak47_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_ak47_gl_mpCOD4_MOD_MELEE= +COD4_ak47_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak47_mpCOD4_MOD_HEAD_SHOT= +COD4_ak47_mpCOD4_MOD_MELEE= +COD4_ak47_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak47_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_ak47_reflex_mpCOD4_MOD_MELEE= +COD4_ak47_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak47_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_ak47_silencer_mpCOD4_MOD_MELEE= +COD4_ak47_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak74u_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_ak74u_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak74u_mpCOD4_MOD_HEAD_SHOT= +COD4_ak74u_mpCOD4_MOD_MELEE= +COD4_ak74u_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak74u_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_ak74u_reflex_mpCOD4_MOD_MELEE= +COD4_ak74u_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_ak74u_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_ak74u_silencer_mpCOD4_MOD_MELEE= +COD4_ak74u_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_artillery_mpCOD4_MOD_PROJECTILE_SPLASH= +COD4_barrett_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_barrett_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_barrett_mpCOD4_MOD_HEAD_SHOT= +COD4_barrett_mpCOD4_MOD_MELEE= +COD4_barrett_mpCOD4_MOD_RIFLE_BULLET= +COD4_beretta_mpCOD4_MOD_HEAD_SHOT= +COD4_beretta_mpCOD4_MOD_MELEE= +COD4_beretta_mpCOD4_MOD_PISTOL_BULLET= +COD4_beretta_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_beretta_silencer_mpCOD4_MOD_MELEE= +COD4_beretta_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_c4_mpCOD4_MOD_GRENADE_SPLASH= +COD4_claymore_mpCOD4_MOD_GRENADE_SPLASH= +COD4_claymore_mpCOD4_MOD_MELEE= +COD4_cobra_20mm_mpCOD4_MOD_HEAD_SHOT= +COD4_cobra_20mm_mpCOD4_MOD_PISTOL_BULLET= +COD4_cobra_ffar_mpCOD4_MOD_PROJECTILE_SPLASH= +COD4_colt45_mpCOD4_MOD_HEAD_SHOT= +COD4_colt45_mpCOD4_MOD_MELEE= +COD4_colt45_mpCOD4_MOD_PISTOL_BULLET= +COD4_colt45_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_colt45_silencer_mpCOD4_MOD_MELEE= +COD4_colt45_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_concussion_grenade_mpCOD4_MOD_GRENADE_SPLASH= +COD4_concussion_grenade_mpCOD4_MOD_IMPACT= +COD4_deserteagle_mpCOD4_MOD_HEAD_SHOT= +COD4_deserteagle_mpCOD4_MOD_MELEE= +COD4_deserteagle_mpCOD4_MOD_PISTOL_BULLET= +COD4_deserteaglegold_mpCOD4_MOD_HEAD_SHOT= +COD4_deserteaglegold_mpCOD4_MOD_MELEE= +COD4_deserteaglegold_mpCOD4_MOD_PISTOL_BULLET= +COD4_destructible_carCOD4_MOD_EXPLOSIVE= +COD4_dragunov_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_dragunov_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_dragunov_mpCOD4_MOD_HEAD_SHOT= +COD4_dragunov_mpCOD4_MOD_MELEE= +COD4_dragunov_mpCOD4_MOD_RIFLE_BULLET= +COD4_flash_grenade_mpCOD4_MOD_IMPACT= +COD4_frag_grenade_mpCOD4_MOD_GRENADE= +COD4_frag_grenade_mpCOD4_MOD_GRENADE_SPLASH= +COD4_frag_grenade_mpCOD4_MOD_IMPACT= +COD4_frag_grenade_mpCOD4_MOD_SUICIDE= +COD4_frag_grenade_short_mpCOD4_MOD_GRENADE_SPLASH= +COD4_g36c_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_g36c_acog_mpCOD4_MOD_MELEE= +COD4_g36c_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_g36c_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_g36c_gl_mpCOD4_MOD_MELEE= +COD4_g36c_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_g36c_mpCOD4_MOD_HEAD_SHOT= +COD4_g36c_mpCOD4_MOD_MELEE= +COD4_g36c_mpCOD4_MOD_RIFLE_BULLET= +COD4_g36c_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_g36c_reflex_mpCOD4_MOD_MELEE= +COD4_g36c_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_g36c_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_g36c_silencer_mpCOD4_MOD_MELEE= +COD4_g36c_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_g3_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_g3_acog_mpCOD4_MOD_MELEE= +COD4_g3_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_g3_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_g3_gl_mpCOD4_MOD_MELEE= +COD4_g3_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_g3_mpCOD4_MOD_HEAD_SHOT= +COD4_g3_mpCOD4_MOD_MELEE= +COD4_g3_mpCOD4_MOD_RIFLE_BULLET= +COD4_g3_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_g3_reflex_mpCOD4_MOD_MELEE= +COD4_g3_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_g3_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_g3_silencer_mpCOD4_MOD_MELEE= +COD4_g3_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_gl_ak47_mpCOD4_MOD_GRENADE= +COD4_gl_ak47_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_ak47_mpCOD4_MOD_IMPACT= +COD4_gl_ak47_mpCOD4_MOD_MELEE= +COD4_gl_g36c_mpCOD4_MOD_GRENADE= +COD4_gl_g36c_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_g36c_mpCOD4_MOD_IMPACT= +COD4_gl_g36c_mpCOD4_MOD_MELEE= +COD4_gl_g3_mpCOD4_MOD_GRENADE= +COD4_gl_g3_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_g3_mpCOD4_MOD_IMPACT= +COD4_gl_g3_mpCOD4_MOD_MELEE= +COD4_gl_m14_mpCOD4_MOD_GRENADE= +COD4_gl_m14_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_m14_mpCOD4_MOD_IMPACT= +COD4_gl_m14_mpCOD4_MOD_MELEE= +COD4_gl_m16_mpCOD4_MOD_GRENADE= +COD4_gl_m16_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_m16_mpCOD4_MOD_IMPACT= +COD4_gl_m16_mpCOD4_MOD_MELEE= +COD4_gl_m4_mpCOD4_MOD_GRENADE= +COD4_gl_m4_mpCOD4_MOD_GRENADE_SPLASH= +COD4_gl_m4_mpCOD4_MOD_IMPACT= +COD4_gl_m4_mpCOD4_MOD_MELEE= +COD4_hind_ffar_mpCOD4_MOD_PROJECTILE= +COD4_hind_ffar_mpCOD4_MOD_PROJECTILE_SPLASH= +COD4_m1014_grip_mpCOD4_MOD_HEAD_SHOT= +COD4_m1014_grip_mpCOD4_MOD_MELEE= +COD4_m1014_grip_mpCOD4_MOD_PISTOL_BULLET= +COD4_m1014_mpCOD4_MOD_HEAD_SHOT= +COD4_m1014_mpCOD4_MOD_MELEE= +COD4_m1014_mpCOD4_MOD_PISTOL_BULLET= +COD4_m1014_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_m1014_reflex_mpCOD4_MOD_MELEE= +COD4_m1014_reflex_mpCOD4_MOD_PISTOL_BULLET= +COD4_m14_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m14_acog_mpCOD4_MOD_MELEE= +COD4_m14_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m14_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_m14_gl_mpCOD4_MOD_MELEE= +COD4_m14_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_m14_mpCOD4_MOD_HEAD_SHOT= +COD4_m14_mpCOD4_MOD_MELEE= +COD4_m14_mpCOD4_MOD_RIFLE_BULLET= +COD4_m14_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_m14_reflex_mpCOD4_MOD_MELEE= +COD4_m14_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_m14_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_m14_silencer_mpCOD4_MOD_MELEE= +COD4_m14_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_m16_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m16_acog_mpCOD4_MOD_MELEE= +COD4_m16_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m16_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_m16_gl_mpCOD4_MOD_MELEE= +COD4_m16_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_m16_mpCOD4_MOD_HEAD_SHOT= +COD4_m16_mpCOD4_MOD_MELEE= +COD4_m16_mpCOD4_MOD_RIFLE_BULLET= +COD4_m16_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_m16_reflex_mpCOD4_MOD_MELEE= +COD4_m16_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_m16_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_m16_silencer_mpCOD4_MOD_MELEE= +COD4_m16_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_m21_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m21_acog_mpCOD4_MOD_MELEE= +COD4_m21_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m21_mpCOD4_MOD_HEAD_SHOT= +COD4_m21_mpCOD4_MOD_MELEE= +COD4_m21_mpCOD4_MOD_RIFLE_BULLET= +COD4_m40a3_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m40a3_acog_mpCOD4_MOD_MELEE= +COD4_m40a3_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m40a3_mpCOD4_MOD_HEAD_SHOT= +COD4_m40a3_mpCOD4_MOD_MELEE= +COD4_m40a3_mpCOD4_MOD_RIFLE_BULLET= +COD4_m4_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m4_acog_mpCOD4_MOD_MELEE= +COD4_m4_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m4_gl_mpCOD4_MOD_HEAD_SHOT= +COD4_m4_gl_mpCOD4_MOD_MELEE= +COD4_m4_gl_mpCOD4_MOD_RIFLE_BULLET= +COD4_m4_mpCOD4_MOD_HEAD_SHOT= +COD4_m4_mpCOD4_MOD_MELEE= +COD4_m4_mpCOD4_MOD_RIFLE_BULLET= +COD4_m4_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_m4_reflex_mpCOD4_MOD_MELEE= +COD4_m4_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_m4_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_m4_silencer_mpCOD4_MOD_MELEE= +COD4_m4_silencer_mpCOD4_MOD_RIFLE_BULLET= +COD4_m60e4_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_m60e4_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_m60e4_grip_mpCOD4_MOD_HEAD_SHOT= +COD4_m60e4_grip_mpCOD4_MOD_RIFLE_BULLET= +COD4_m60e4_mpCOD4_MOD_HEAD_SHOT= +COD4_m60e4_mpCOD4_MOD_MELEE= +COD4_m60e4_mpCOD4_MOD_RIFLE_BULLET= +COD4_m60e4_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_m60e4_reflex_mpCOD4_MOD_MELEE= +COD4_m60e4_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_mod_explosiveCOD4_MOD_EXPLOSIVE= +COD4_mod_fallingCOD4_MOD_FALLING= +COD4_mod_head_shotCOD4_MOD_HEAD_SHOT= +COD4_mod_meleeCOD4_MOD_MELEE= +COD4_mod_pistol_bulletCOD4_MOD_PISTOL_BULLET= +COD4_mod_rifle_bulletCOD4_MOD_RIFLE_BULLET= +COD4_mod_suicideCOD4_MOD_SUICIDE= +COD4_mod_trigger_hurtCOD4_MOD_TRIGGER_HURT= +COD4_mp44_mpCOD4_MOD_HEAD_SHOT= +COD4_mp44_mpCOD4_MOD_MELEE= +COD4_mp44_mpCOD4_MOD_RIFLE_BULLET= +COD4_mp5_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_mp5_acog_mpCOD4_MOD_MELEE= +COD4_mp5_acog_mpCOD4_MOD_PISTOL_BULLET= +COD4_mp5_mpCOD4_MOD_HEAD_SHOT= +COD4_mp5_mpCOD4_MOD_MELEE= +COD4_mp5_mpCOD4_MOD_PISTOL_BULLET= +COD4_mp5_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_mp5_reflex_mpCOD4_MOD_MELEE= +COD4_mp5_reflex_mpCOD4_MOD_PISTOL_BULLET= +COD4_mp5_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_mp5_silencer_mpCOD4_MOD_MELEE= +COD4_mp5_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_p90_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_p90_acog_mpCOD4_MOD_MELEE= +COD4_p90_acog_mpCOD4_MOD_PISTOL_BULLET= +COD4_p90_mpCOD4_MOD_HEAD_SHOT= +COD4_p90_mpCOD4_MOD_MELEE= +COD4_p90_mpCOD4_MOD_PISTOL_BULLET= +COD4_p90_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_p90_reflex_mpCOD4_MOD_MELEE= +COD4_p90_reflex_mpCOD4_MOD_PISTOL_BULLET= +COD4_p90_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_p90_silencer_mpCOD4_MOD_MELEE= +COD4_p90_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_remington700_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_remington700_acog_mpCOD4_MOD_MELEE= +COD4_remington700_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_remington700_mpCOD4_MOD_HEAD_SHOT= +COD4_remington700_mpCOD4_MOD_MELEE= +COD4_remington700_mpCOD4_MOD_RIFLE_BULLET= +COD4_rpd_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_rpd_acog_mpCOD4_MOD_MELEE= +COD4_rpd_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_rpd_grip_mpCOD4_MOD_HEAD_SHOT= +COD4_rpd_grip_mpCOD4_MOD_MELEE= +COD4_rpd_grip_mpCOD4_MOD_RIFLE_BULLET= +COD4_rpd_mpCOD4_MOD_HEAD_SHOT= +COD4_rpd_mpCOD4_MOD_MELEE= +COD4_rpd_mpCOD4_MOD_RIFLE_BULLET= +COD4_rpd_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_rpd_reflex_mpCOD4_MOD_MELEE= +COD4_rpd_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_rpg_mpCOD4_MOD_MELEE= +COD4_rpg_mpCOD4_MOD_PROJECTILE= +COD4_rpg_mpCOD4_MOD_PROJECTILE_SPLASH= +COD4_saw_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_saw_acog_mpCOD4_MOD_MELEE= +COD4_saw_acog_mpCOD4_MOD_RIFLE_BULLET= +COD4_saw_bipod_crouch_mpCOD4_MOD_RIFLE_BULLET= +COD4_saw_bipod_stand_mpCOD4_MOD_RIFLE_BULLET= +COD4_saw_grip_mpCOD4_MOD_HEAD_SHOT= +COD4_saw_grip_mpCOD4_MOD_MELEE= +COD4_saw_grip_mpCOD4_MOD_RIFLE_BULLET= +COD4_saw_mpCOD4_MOD_HEAD_SHOT= +COD4_saw_mpCOD4_MOD_MELEE= +COD4_saw_mpCOD4_MOD_RIFLE_BULLET= +COD4_saw_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_saw_reflex_mpCOD4_MOD_MELEE= +COD4_saw_reflex_mpCOD4_MOD_RIFLE_BULLET= +COD4_skorpion_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_skorpion_acog_mpCOD4_MOD_MELEE= +COD4_skorpion_acog_mpCOD4_MOD_PISTOL_BULLET= +COD4_skorpion_mpCOD4_MOD_HEAD_SHOT= +COD4_skorpion_mpCOD4_MOD_MELEE= +COD4_skorpion_mpCOD4_MOD_PISTOL_BULLET= +COD4_skorpion_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_skorpion_reflex_mpCOD4_MOD_MELEE= +COD4_skorpion_reflex_mpCOD4_MOD_PISTOL_BULLET= +COD4_skorpion_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_skorpion_silencer_mpCOD4_MOD_MELEE= +COD4_skorpion_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_smoke_grenade_mpCOD4_MOD_IMPACT= +COD4_usp_mpCOD4_MOD_HEAD_SHOT= +COD4_usp_mpCOD4_MOD_MELEE= +COD4_usp_mpCOD4_MOD_PISTOL_BULLET= +COD4_usp_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_usp_silencer_mpCOD4_MOD_MELEE= +COD4_usp_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_uzi_acog_mpCOD4_MOD_HEAD_SHOT= +COD4_uzi_acog_mpCOD4_MOD_PISTOL_BULLET= +COD4_uzi_mpCOD4_MOD_HEAD_SHOT= +COD4_uzi_mpCOD4_MOD_MELEE= +COD4_uzi_mpCOD4_MOD_PISTOL_BULLET= +COD4_uzi_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_uzi_reflex_mpCOD4_MOD_MELEE= +COD4_uzi_reflex_mpCOD4_MOD_PISTOL_BULLET= +COD4_uzi_silencer_mpCOD4_MOD_HEAD_SHOT= +COD4_uzi_silencer_mpCOD4_MOD_MELEE= +COD4_uzi_silencer_mpCOD4_MOD_PISTOL_BULLET= +COD4_winchester1200_grip_mpCOD4_MOD_HEAD_SHOT= +COD4_winchester1200_grip_mpCOD4_MOD_MELEE= +COD4_winchester1200_grip_mpCOD4_MOD_PISTOL_BULLET= +COD4_winchester1200_mpCOD4_MOD_HEAD_SHOT= +COD4_winchester1200_mpCOD4_MOD_MELEE= +COD4_winchester1200_mpCOD4_MOD_PISTOL_BULLET= +COD4_winchester1200_reflex_mpCOD4_MOD_HEAD_SHOT= +COD4_winchester1200_reflex_mpCOD4_MOD_MELEE= +COD4_winchester1200_reflex_mpCOD4_MOD_PISTOL_BULLET= +cod5_30cal_bipod_crouch_mpcod5_mod_head_shot= +cod5_30cal_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_30cal_bipod_mpcod5_mod_head_shot= +cod5_30cal_bipod_mpcod5_mod_melee= +cod5_30cal_bipod_mpcod5_mod_rifle_bullet= +cod5_30cal_bipod_prone_mpcod5_mod_head_shot= +cod5_30cal_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_30cal_bipod_stand_mpcod5_mod_head_shot= +cod5_30cal_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_30cal_mpcod5_mod_head_shot= +cod5_30cal_mpcod5_mod_melee= +cod5_30cal_mpcod5_mod_rifle_bullet= +cod5_357magnum_mpcod5_mod_burned= +cod5_357magnum_mpcod5_mod_head_shot= +cod5_357magnum_mpcod5_mod_melee= +cod5_357magnum_mpcod5_mod_pistol_bullet= +cod5_artillery_mpcod5_mod_projectile= +cod5_artillery_mpcod5_mod_projectile_splash= +cod5_bar_bipod_crouch_mpcod5_mod_head_shot= +cod5_bar_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_bar_bipod_mpcod5_mod_head_shot= +cod5_bar_bipod_mpcod5_mod_melee= +cod5_bar_bipod_mpcod5_mod_rifle_bullet= +cod5_bar_bipod_prone_mpcod5_mod_head_shot= +cod5_bar_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_bar_bipod_stand_mpcod5_mod_head_shot= +cod5_bar_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_bar_mpcod5_mod_head_shot= +cod5_bar_mpcod5_mod_melee= +cod5_bar_mpcod5_mod_rifle_bullet= +cod5_bazooka_mpcod5_mod_melee= +cod5_bazooka_mpcod5_mod_projectile= +cod5_bazooka_mpcod5_mod_projectile_splash= +cod5_briefcase_bomb_mpcod5_mod_explosive= +cod5_colt_mpcod5_mod_burned= +cod5_colt_mpcod5_mod_head_shot= +cod5_colt_mpcod5_mod_melee= +cod5_colt_mpcod5_mod_pistol_bullet= +cod5_destructible_carcod5_mod_explosive= +cod5_dog_bite_mpcod5_mod_pistol_bullet= +cod5_doublebarreledshotgun_grip_mpcod5_mod_head_shot= +cod5_doublebarreledshotgun_grip_mpcod5_mod_melee= +cod5_doublebarreledshotgun_grip_mpcod5_mod_pistol_bullet= +cod5_doublebarreledshotgun_mpcod5_mod_head_shot= +cod5_doublebarreledshotgun_mpcod5_mod_melee= +cod5_doublebarreledshotgun_mpcod5_mod_pistol_bullet= +cod5_doublebarreledshotgun_sawoff_mpcod5_mod_head_shot= +cod5_doublebarreledshotgun_sawoff_mpcod5_mod_melee= +cod5_doublebarreledshotgun_sawoff_mpcod5_mod_pistol_bullet= +cod5_dp28_bipod_crouch_mpcod5_mod_head_shot= +cod5_dp28_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_dp28_bipod_mpcod5_mod_head_shot= +cod5_dp28_bipod_mpcod5_mod_melee= +cod5_dp28_bipod_mpcod5_mod_rifle_bullet= +cod5_dp28_bipod_prone_mpcod5_mod_head_shot= +cod5_dp28_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_dp28_bipod_stand_mpcod5_mod_head_shot= +cod5_dp28_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_dp28_mpcod5_mod_head_shot= +cod5_dp28_mpcod5_mod_melee= +cod5_dp28_mpcod5_mod_rifle_bullet= +cod5_explodable_barrelcod5_mod_explosive= +cod5_fg42_bipod_crouch_mpcod5_mod_head_shot= +cod5_fg42_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_fg42_bipod_mpcod5_mod_head_shot= +cod5_fg42_bipod_mpcod5_mod_melee= +cod5_fg42_bipod_mpcod5_mod_rifle_bullet= +cod5_fg42_bipod_prone_mpcod5_mod_head_shot= +cod5_fg42_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_fg42_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_fg42_mpcod5_mod_head_shot= +cod5_fg42_mpcod5_mod_melee= +cod5_fg42_mpcod5_mod_rifle_bullet= +cod5_fg42_telescopic_mpcod5_mod_head_shot= +cod5_fg42_telescopic_mpcod5_mod_melee= +cod5_fg42_telescopic_mpcod5_mod_rifle_bullet= +cod5_frag_grenade_mpcod5_mod_grenade= +cod5_frag_grenade_mpcod5_mod_grenade_splash= +cod5_frag_grenade_mpcod5_mod_impact= +cod5_frag_grenade_mpcod5_mod_suicide= +cod5_frag_grenade_short_mpcod5_mod_grenade_splash= +cod5_frag_grenade_short_mpcod5_mod_impact= +cod5_gewehr43_aperture_mpcod5_mod_head_shot= +cod5_gewehr43_aperture_mpcod5_mod_melee= +cod5_gewehr43_aperture_mpcod5_mod_rifle_bullet= +cod5_gewehr43_gl_mpcod5_mod_head_shot= +cod5_gewehr43_gl_mpcod5_mod_melee= +cod5_gewehr43_gl_mpcod5_mod_rifle_bullet= +cod5_gewehr43_mpcod5_mod_head_shot= +cod5_gewehr43_mpcod5_mod_melee= +cod5_gewehr43_mpcod5_mod_rifle_bullet= +cod5_gewehr43_silenced_mpcod5_mod_head_shot= +cod5_gewehr43_silenced_mpcod5_mod_melee= +cod5_gewehr43_silenced_mpcod5_mod_rifle_bullet= +cod5_gewehr43_telescopic_mpcod5_mod_head_shot= +cod5_gewehr43_telescopic_mpcod5_mod_melee= +cod5_gewehr43_telescopic_mpcod5_mod_rifle_bullet= +cod5_gl_gewehr43_mpcod5_mod_grenade= +cod5_gl_gewehr43_mpcod5_mod_grenade_splash= +cod5_gl_gewehr43_mpcod5_mod_melee= +cod5_gl_kar98k_mpcod5_mod_grenade= +cod5_gl_kar98k_mpcod5_mod_grenade_splash= +cod5_gl_kar98k_mpcod5_mod_melee= +cod5_gl_m1garand_mpcod5_mod_grenade= +cod5_gl_m1garand_mpcod5_mod_grenade_splash= +cod5_gl_m1garand_mpcod5_mod_melee= +cod5_gl_mosinrifle_mpcod5_mod_grenade= +cod5_gl_mosinrifle_mpcod5_mod_grenade_splash= +cod5_gl_mosinrifle_mpcod5_mod_melee= +cod5_gl_springfield_mpcod5_mod_grenade= +cod5_gl_springfield_mpcod5_mod_grenade_splash= +cod5_gl_springfield_mpcod5_mod_melee= +cod5_gl_type99rifle_mpcod5_mod_grenade= +cod5_gl_type99rifle_mpcod5_mod_grenade_splash= +cod5_kar98k_bayonet_mpcod5_mod_bayonet= +cod5_kar98k_bayonet_mpcod5_mod_head_shot= +cod5_kar98k_bayonet_mpcod5_mod_rifle_bullet= +cod5_kar98k_gl_mpcod5_mod_head_shot= +cod5_kar98k_gl_mpcod5_mod_melee= +cod5_kar98k_gl_mpcod5_mod_rifle_bullet= +cod5_kar98k_mpcod5_mod_head_shot= +cod5_kar98k_mpcod5_mod_melee= +cod5_kar98k_mpcod5_mod_rifle_bullet= +cod5_kar98k_scoped_mpcod5_mod_head_shot= +cod5_kar98k_scoped_mpcod5_mod_melee= +cod5_kar98k_scoped_mpcod5_mod_rifle_bullet= +cod5_m1carbine_aperture_mpcod5_mod_head_shot= +cod5_m1carbine_aperture_mpcod5_mod_melee= +cod5_m1carbine_aperture_mpcod5_mod_rifle_bullet= +cod5_m1carbine_bayonet_mpcod5_mod_head_shot= +cod5_m1carbine_bayonet_mpcod5_mod_melee= +cod5_m1carbine_bayonet_mpcod5_mod_rifle_bullet= +cod5_m1carbine_bigammo_mpcod5_mod_head_shot= +cod5_m1carbine_bigammo_mpcod5_mod_melee= +cod5_m1carbine_bigammo_mpcod5_mod_rifle_bullet= +cod5_m1carbine_flash_mpcod5_mod_head_shot= +cod5_m1carbine_flash_mpcod5_mod_melee= +cod5_m1carbine_flash_mpcod5_mod_rifle_bullet= +cod5_m1carbine_mpcod5_mod_head_shot= +cod5_m1carbine_mpcod5_mod_melee= +cod5_m1carbine_mpcod5_mod_rifle_bullet= +cod5_m1garand_bayonet_mpcod5_mod_bayonet= +cod5_m1garand_bayonet_mpcod5_mod_head_shot= +cod5_m1garand_bayonet_mpcod5_mod_rifle_bullet= +cod5_m1garand_flash_mpcod5_mod_head_shot= +cod5_m1garand_flash_mpcod5_mod_melee= +cod5_m1garand_flash_mpcod5_mod_rifle_bullet= +cod5_m1garand_gl_mpcod5_mod_head_shot= +cod5_m1garand_gl_mpcod5_mod_melee= +cod5_m1garand_gl_mpcod5_mod_rifle_bullet= +cod5_m1garand_mpcod5_mod_head_shot= +cod5_m1garand_mpcod5_mod_melee= +cod5_m1garand_mpcod5_mod_rifle_bullet= +cod5_m1garand_scoped_mpcod5_mod_head_shot= +cod5_m1garand_scoped_mpcod5_mod_melee= +cod5_m1garand_scoped_mpcod5_mod_rifle_bullet= +cod5_m2_flamethrower_mpcod5_mod_burned= +cod5_m2_flamethrower_mpcod5_mod_melee= +cod5_m8_white_smoke_mpcod5_mod_impact= +cod5_mg42_bipod_crouch_mpcod5_mod_head_shot= +cod5_mg42_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_mg42_bipod_mpcod5_mod_head_shot= +cod5_mg42_bipod_mpcod5_mod_melee= +cod5_mg42_bipod_mpcod5_mod_rifle_bullet= +cod5_mg42_bipod_prone_mpcod5_mod_head_shot= +cod5_mg42_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_mg42_bipod_stand_mpcod5_mod_head_shot= +cod5_mg42_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_mg42_mpcod5_mod_head_shot= +cod5_mg42_mpcod5_mod_melee= +cod5_mg42_mpcod5_mod_rifle_bullet= +cod5_mine_bouncing_betty_mpcod5_mod_grenade_splash= +cod5_mine_bouncing_betty_mpcod5_mod_melee= +cod5_mod_burnedcod5_mod_burned= +cod5_mod_explosivecod5_mod_explosive= +cod5_mod_fallingcod5_mod_falling= +cod5_mod_meleecod5_mod_melee= +cod5_mod_suicidecod5_mod_suicide= +cod5_mod_trigger_hurtcod5_mod_trigger_hurt= +cod5_molotov_mpcod5_mod_grenade= +cod5_molotov_mpcod5_mod_grenade_splash= +cod5_mosinrifle_bayonet_mpcod5_mod_bayonet= +cod5_mosinrifle_bayonet_mpcod5_mod_head_shot= +cod5_mosinrifle_bayonet_mpcod5_mod_rifle_bullet= +cod5_mosinrifle_gl_mpcod5_mod_head_shot= +cod5_mosinrifle_gl_mpcod5_mod_melee= +cod5_mosinrifle_gl_mpcod5_mod_rifle_bullet= +cod5_mosinrifle_mpcod5_mod_head_shot= +cod5_mosinrifle_mpcod5_mod_melee= +cod5_mosinrifle_mpcod5_mod_rifle_bullet= +cod5_mosinrifle_scoped_mpcod5_mod_head_shot= +cod5_mosinrifle_scoped_mpcod5_mod_melee= +cod5_mosinrifle_scoped_mpcod5_mod_rifle_bullet= +cod5_mp40_aperture_mpcod5_mod_head_shot= +cod5_mp40_aperture_mpcod5_mod_melee= +cod5_mp40_aperture_mpcod5_mod_rifle_bullet= +cod5_mp40_bigammo_mpcod5_mod_head_shot= +cod5_mp40_bigammo_mpcod5_mod_melee= +cod5_mp40_bigammo_mpcod5_mod_rifle_bullet= +cod5_mp40_mpcod5_mod_head_shot= +cod5_mp40_mpcod5_mod_melee= +cod5_mp40_mpcod5_mod_rifle_bullet= +cod5_mp40_silenced_mpcod5_mod_head_shot= +cod5_mp40_silenced_mpcod5_mod_melee= +cod5_mp40_silenced_mpcod5_mod_rifle_bullet= +cod5_nambu_mpcod5_mod_head_shot= +cod5_nambu_mpcod5_mod_melee= +cod5_nambu_mpcod5_mod_pistol_bullet= +cod5_panzer4_gunner_front_mpcod5_mod_rifle_bullet= +cod5_panzer4_gunner_mpcod5_mod_head_shot= +cod5_panzer4_gunner_mpcod5_mod_rifle_bullet= +cod5_panzer4_mp_explosion_mpcod5_mod_explosive= +cod5_panzer4_turret_mpcod5_mod_crush= +cod5_panzer4_turret_mpcod5_mod_projectile= +cod5_panzer4_turret_mpcod5_mod_projectile_splash= +cod5_panzer4_turret_mpcod5_mod_unknown= +cod5_ppsh_aperture_mpcod5_mod_head_shot= +cod5_ppsh_aperture_mpcod5_mod_melee= +cod5_ppsh_aperture_mpcod5_mod_pistol_bullet= +cod5_ppsh_bigammo_mpcod5_mod_head_shot= +cod5_ppsh_bigammo_mpcod5_mod_melee= +cod5_ppsh_bigammo_mpcod5_mod_pistol_bullet= +cod5_ppsh_mpcod5_mod_head_shot= +cod5_ppsh_mpcod5_mod_melee= +cod5_ppsh_mpcod5_mod_pistol_bullet= +cod5_ptrs41_mpcod5_mod_head_shot= +cod5_ptrs41_mpcod5_mod_melee= +cod5_ptrs41_mpcod5_mod_rifle_bullet= +cod5_satchel_charge_mpcod5_mod_grenade= +cod5_satchel_charge_mpcod5_mod_grenade_splash= +cod5_satchel_charge_mpcod5_mod_melee= +cod5_shotgun_bayonet_mpcod5_mod_bayonet= +cod5_shotgun_bayonet_mpcod5_mod_head_shot= +cod5_shotgun_bayonet_mpcod5_mod_pistol_bullet= +cod5_shotgun_grip_mpcod5_mod_head_shot= +cod5_shotgun_grip_mpcod5_mod_melee= +cod5_shotgun_grip_mpcod5_mod_pistol_bullet= +cod5_shotgun_mpcod5_mod_head_shot= +cod5_shotgun_mpcod5_mod_melee= +cod5_shotgun_mpcod5_mod_pistol_bullet= +cod5_signal_flare_mpcod5_mod_impact= +cod5_springfield_bayonet_mpcod5_mod_bayonet= +cod5_springfield_bayonet_mpcod5_mod_head_shot= +cod5_springfield_bayonet_mpcod5_mod_rifle_bullet= +cod5_springfield_gl_mpcod5_mod_head_shot= +cod5_springfield_gl_mpcod5_mod_melee= +cod5_springfield_gl_mpcod5_mod_rifle_bullet= +cod5_springfield_mpcod5_mod_head_shot= +cod5_springfield_mpcod5_mod_melee= +cod5_springfield_mpcod5_mod_rifle_bullet= +cod5_springfield_scoped_mpcod5_mod_head_shot= +cod5_springfield_scoped_mpcod5_mod_melee= +cod5_springfield_scoped_mpcod5_mod_rifle_bullet= +cod5_stg44_aperture_mpcod5_mod_head_shot= +cod5_stg44_aperture_mpcod5_mod_melee= +cod5_stg44_aperture_mpcod5_mod_rifle_bullet= +cod5_stg44_flash_mpcod5_mod_head_shot= +cod5_stg44_flash_mpcod5_mod_melee= +cod5_stg44_flash_mpcod5_mod_rifle_bullet= +cod5_stg44_mpcod5_mod_head_shot= +cod5_stg44_mpcod5_mod_melee= +cod5_stg44_mpcod5_mod_rifle_bullet= +cod5_stg44_telescopic_mpcod5_mod_head_shot= +cod5_stg44_telescopic_mpcod5_mod_melee= +cod5_stg44_telescopic_mpcod5_mod_rifle_bullet= +cod5_sticky_grenade_mpcod5_mod_grenade= +cod5_sticky_grenade_mpcod5_mod_grenade_splash= +cod5_sticky_grenade_mpcod5_mod_impact= +cod5_svt40_aperture_mpcod5_mod_head_shot= +cod5_svt40_aperture_mpcod5_mod_melee= +cod5_svt40_aperture_mpcod5_mod_rifle_bullet= +cod5_svt40_flash_mpcod5_mod_head_shot= +cod5_svt40_flash_mpcod5_mod_melee= +cod5_svt40_flash_mpcod5_mod_rifle_bullet= +cod5_svt40_mpcod5_mod_head_shot= +cod5_svt40_mpcod5_mod_melee= +cod5_svt40_mpcod5_mod_rifle_bullet= +cod5_svt40_telescopic_mpcod5_mod_head_shot= +cod5_svt40_telescopic_mpcod5_mod_melee= +cod5_svt40_telescopic_mpcod5_mod_rifle_bullet= +cod5_t34_gunner_front_mpcod5_mod_rifle_bullet= +cod5_t34_gunner_mpcod5_mod_head_shot= +cod5_t34_gunner_mpcod5_mod_rifle_bullet= +cod5_t34_mp_explosion_mpcod5_mod_explosive= +cod5_t34_turret_mpcod5_mod_crush= +cod5_t34_turret_mpcod5_mod_projectile= +cod5_t34_turret_mpcod5_mod_projectile_splash= +cod5_tabun_gas_mpcod5_mod_impact= +cod5_thompson_aperture_mpcod5_mod_head_shot= +cod5_thompson_aperture_mpcod5_mod_melee= +cod5_thompson_aperture_mpcod5_mod_rifle_bullet= +cod5_thompson_bigammo_mpcod5_mod_head_shot= +cod5_thompson_bigammo_mpcod5_mod_melee= +cod5_thompson_bigammo_mpcod5_mod_rifle_bullet= +cod5_thompson_mpcod5_mod_head_shot= +cod5_thompson_mpcod5_mod_melee= +cod5_thompson_mpcod5_mod_rifle_bullet= +cod5_thompson_silenced_mpcod5_mod_head_shot= +cod5_thompson_silenced_mpcod5_mod_melee= +cod5_thompson_silenced_mpcod5_mod_rifle_bullet= +cod5_tokarev_mpcod5_mod_head_shot= +cod5_tokarev_mpcod5_mod_melee= +cod5_tokarev_mpcod5_mod_pistol_bullet= +cod5_type100smg_aperture_mpcod5_mod_head_shot= +cod5_type100smg_aperture_mpcod5_mod_melee= +cod5_type100smg_aperture_mpcod5_mod_pistol_bullet= +cod5_type100smg_bigammo_mpcod5_mod_head_shot= +cod5_type100smg_bigammo_mpcod5_mod_melee= +cod5_type100smg_bigammo_mpcod5_mod_pistol_bullet= +cod5_type100smg_mpcod5_mod_head_shot= +cod5_type100smg_mpcod5_mod_melee= +cod5_type100smg_mpcod5_mod_pistol_bullet= +cod5_type100smg_silenced_mpcod5_mod_head_shot= +cod5_type100smg_silenced_mpcod5_mod_melee= +cod5_type100smg_silenced_mpcod5_mod_pistol_bullet= +cod5_type99_lmg_bipod_crouch_mpcod5_mod_head_shot= +cod5_type99_lmg_bipod_crouch_mpcod5_mod_rifle_bullet= +cod5_type99_lmg_bipod_prone_mpcod5_mod_head_shot= +cod5_type99_lmg_bipod_prone_mpcod5_mod_rifle_bullet= +cod5_type99_lmg_bipod_stand_mpcod5_mod_rifle_bullet= +cod5_type99lmg_bayonet_mpcod5_mod_bayonet= +cod5_type99lmg_bayonet_mpcod5_mod_head_shot= +cod5_type99lmg_bayonet_mpcod5_mod_rifle_bullet= +cod5_type99lmg_bipod_mpcod5_mod_head_shot= +cod5_type99lmg_bipod_mpcod5_mod_melee= +cod5_type99lmg_bipod_mpcod5_mod_rifle_bullet= +cod5_type99lmg_mpcod5_mod_head_shot= +cod5_type99lmg_mpcod5_mod_melee= +cod5_type99lmg_mpcod5_mod_rifle_bullet= +cod5_type99rifle_bayonet_mpcod5_mod_bayonet= +cod5_type99rifle_bayonet_mpcod5_mod_head_shot= +cod5_type99rifle_bayonet_mpcod5_mod_rifle_bullet= +cod5_type99rifle_gl_mpcod5_mod_head_shot= +cod5_type99rifle_gl_mpcod5_mod_melee= +cod5_type99rifle_gl_mpcod5_mod_rifle_bullet= +cod5_type99rifle_mpcod5_mod_head_shot= +cod5_type99rifle_mpcod5_mod_melee= +cod5_type99rifle_mpcod5_mod_rifle_bullet= +cod5_type99rifle_scoped_mpcod5_mod_head_shot= +cod5_type99rifle_scoped_mpcod5_mod_melee= +cod5_type99rifle_scoped_mpcod5_mod_rifle_bullet= +cod5_walther_mpcod5_mod_burned= +cod5_walther_mpcod5_mod_head_shot= +cod5_walther_mpcod5_mod_melee= +cod5_walther_mpcod5_mod_pistol_bullet= +MOHAA_clubbedMOHAA_= +MOHAA_grenadeMOHAA_= +MOHAA_mgMOHAA_= +MOHAA_mineMOHAA_= +MOHAA_pistolMOHAA_= +MOHAA_rifleMOHAA_= +MOHAA_smgMOHAA_= +MOHAA_sniperMOHAA_= +MOHAA_suicideMOHAA_= +WOLFENSTEIN_mod_airstrikeWOLFENSTEIN_= +WOLFENSTEIN_mod_akimbo_coltWOLFENSTEIN_= +WOLFENSTEIN_mod_akimbo_lugerWOLFENSTEIN_= +WOLFENSTEIN_mod_artilleryWOLFENSTEIN_= +WOLFENSTEIN_mod_artyWOLFENSTEIN_= +WOLFENSTEIN_mod_browningWOLFENSTEIN_= +WOLFENSTEIN_mod_carbineWOLFENSTEIN_= +WOLFENSTEIN_mod_coltWOLFENSTEIN_= +WOLFENSTEIN_mod_crush_constructiondeath_noattackerWOLFENSTEIN_= +WOLFENSTEIN_mod_crush_constructionWOLFENSTEIN_= +WOLFENSTEIN_mod_crushWOLFENSTEIN_= +WOLFENSTEIN_mod_dynamite_splashWOLFENSTEIN_= +WOLFENSTEIN_mod_dynamiteWOLFENSTEIN_= +WOLFENSTEIN_mod_explosiveWOLFENSTEIN_= +WOLFENSTEIN_mod_fallingWOLFENSTEIN_= +WOLFENSTEIN_mod_fg42scopeWOLFENSTEIN_= +WOLFENSTEIN_mod_fg42WOLFENSTEIN_= +WOLFENSTEIN_mod_flamethrowerWOLFENSTEIN_= +WOLFENSTEIN_mod_garand_scopeWOLFENSTEIN_= +WOLFENSTEIN_mod_garandWOLFENSTEIN_= +WOLFENSTEIN_mod_goombaWOLFENSTEIN_= +WOLFENSTEIN_mod_gpg40WOLFENSTEIN_= +WOLFENSTEIN_mod_grenade_launcherWOLFENSTEIN_= +WOLFENSTEIN_mod_grenade_splashWOLFENSTEIN_= +WOLFENSTEIN_mod_grenadeWOLFENSTEIN_= +WOLFENSTEIN_mod_k43_scopeWOLFENSTEIN_= +WOLFENSTEIN_mod_k43WOLFENSTEIN_= +WOLFENSTEIN_mod_kar98WOLFENSTEIN_= +WOLFENSTEIN_mod_kickedWOLFENSTEIN_= +WOLFENSTEIN_mod_knife_stealthWOLFENSTEIN_= +WOLFENSTEIN_mod_knifeWOLFENSTEIN_= +WOLFENSTEIN_mod_landmineWOLFENSTEIN_= +WOLFENSTEIN_mod_lugerWOLFENSTEIN_= +WOLFENSTEIN_mod_m7WOLFENSTEIN_= +WOLFENSTEIN_mod_machinegunWOLFENSTEIN_= +WOLFENSTEIN_mod_mauserWOLFENSTEIN_= +WOLFENSTEIN_mod_mg42WOLFENSTEIN_= +WOLFENSTEIN_mod_mobile_mg42WOLFENSTEIN_= +WOLFENSTEIN_mod_mortar_splashWOLFENSTEIN_= +WOLFENSTEIN_mod_mortarWOLFENSTEIN_= +WOLFENSTEIN_mod_mp40WOLFENSTEIN_= +WOLFENSTEIN_mod_panzerfaustWOLFENSTEIN_= +WOLFENSTEIN_mod_poisonWOLFENSTEIN_= +WOLFENSTEIN_mod_rocket_splashWOLFENSTEIN_= +WOLFENSTEIN_mod_rocketWOLFENSTEIN_= +WOLFENSTEIN_mod_satchelWOLFENSTEIN_= +WOLFENSTEIN_mod_silenced_coltWOLFENSTEIN_= +WOLFENSTEIN_mod_silencerWOLFENSTEIN_= +WOLFENSTEIN_mod_sniperrifleWOLFENSTEIN_= +WOLFENSTEIN_mod_stenWOLFENSTEIN_= +WOLFENSTEIN_mod_suicideWOLFENSTEIN_= +WOLFENSTEIN_mod_switchteamWOLFENSTEIN_= +WOLFENSTEIN_mod_thompsonWOLFENSTEIN_= +WOLFENSTEIN_mod_trigger_hurtWOLFENSTEIN_= +WOLFENSTEIN_mod_unknownWOLFENSTEIN_= +WOLFENSTEIN_mod_venomWOLFENSTEIN_= +WOLFENSTEIN_mod_waterWOLFENSTEIN_= +[LogSubstituteLOCATION] +COD1_head= +COD1_left_arm_lower= +COD1_left_arm_upper= +COD1_left_foot= +COD1_left_hand= +COD1_left_leg_lower= +COD1_left_leg_upper= +COD1_neck= +COD1_none= +COD1_right_arm_lower= +COD1_right_arm_upper= +COD1_right_foot= +COD1_right_hand= +COD1_right_leg_lower= +COD1_right_leg_upper= +COD1_torso_lower= +COD1_torso_upper= +COD2_head= +COD2_left_arm_lower= +COD2_left_arm_upper= +COD2_left_foot= +COD2_left_hand= +COD2_left_leg_lower= +COD2_left_leg_upper= +COD2_neck= +COD2_none= +COD2_right_arm_lower= +COD2_right_arm_upper= +COD2_right_foot= +COD2_right_hand= +COD2_right_leg_lower= +COD2_right_leg_upper= +COD2_torso_lower= +COD2_torso_upper= +COD4_head= +COD4_left_arm_lower= +COD4_left_arm_upper= +COD4_left_foot= +COD4_left_hand= +COD4_left_leg_lower= +COD4_left_leg_upper= +COD4_neck= +COD4_none= +COD4_right_arm_lower= +COD4_right_arm_upper= +COD4_right_foot= +COD4_right_hand= +COD4_right_leg_lower= +COD4_right_leg_upper= +COD4_torso_lower= +COD4_torso_upper= +cod5_head= +cod5_left_arm_lower= +cod5_left_arm_upper= +cod5_left_foot= +cod5_left_hand= +cod5_left_leg_lower= +cod5_left_leg_upper= +cod5_neck= +cod5_none= +cod5_right_arm_lower= +cod5_right_arm_upper= +cod5_right_foot= +cod5_right_hand= +cod5_right_leg_lower= +cod5_right_leg_upper= +cod5_torso_lower= +cod5_torso_upper= +MOHAA_= +WOLFENSTEIN_= +[AWARDLIST] +LISTCOUNT=63 +LISTITEM001=generic_aimless +LISTITEM002=generic_daredevil +LISTITEM003=generic_deaths +LISTITEM004=generic_fall +LISTITEM005=generic_grenade_killer +LISTITEM006=generic_grenade_magnet +LISTITEM007=generic_headshots +LISTITEM008=generic_kills +LISTITEM009=generic_knife +LISTITEM010=generic_speech +LISTITEM011=generic_marksman +LISTITEM012=generic_suicide +LISTITEM013=generic_wrongplace +LISTITEM014=generic_large_caliber +LISTITEM015=generic_shotgun +LISTITEM016=generic_sidearm +LISTITEM017=generic_sniper +LISTITEM018=generic_airstrike +LISTITEM019=generic_ratio +LISTITEM020=generic_rpg +LISTITEM021=generic_silencer +LISTITEM022=admiral_fire +LISTITEM023=admiral_gas +LISTITEM024=admiral_medic +LISTITEM025=admiral_projectile +LISTITEM026=admiral_tnt +LISTITEM027=admiral_purple_heart +LISTITEM028=ww2_american +LISTITEM029=ww2_british +LISTITEM030=ww2_russian +LISTITEM031=ww2_german +LISTITEM032=ww2_bash +LISTITEM033=ww2_bolt_action_rifles +LISTITEM034=ww2_fast_loading_rifles +LISTITEM035=ww2_small_machine_gun +LISTITEM036=quakewars_groundvehicles +LISTITEM037=quakewars_flyingvehicles +LISTITEM038=quakewars_meleeweapons +LISTITEM039=quakewars_sidearms +LISTITEM040=quakewars_primaryweapons +LISTITEM041=quakewars_grenades +LISTITEM042=quakewars_grenademagnet +LISTITEM043=quakewars_defenseturrets +LISTITEM044=quakewars_firesupport +LISTITEM045=quakewars_xpengineer +LISTITEM046=quakewars_xpfieldops +LISTITEM047=quakewars_xpmedic +LISTITEM048=quakewars_xpsoldier +LISTITEM049=quakewars_xpvehicle +LISTITEM050=quakewars_xpweaponhandling +LISTITEM051=quakewars_xpbattlesense +LISTITEM052=quakewars_xpcovertops +LISTITEM053=modern_assault +LISTITEM054=modern_explosives +LISTITEM055=modern_explosives_magnet +LISTITEM056=modern_grenade_launcher +LISTITEM057=modern_grip +LISTITEM058=modern_helicopter +LISTITEM059=modern_heavy_gun +LISTITEM060=modern_red_dot +LISTITEM061=modern_sub_machine_gun +LISTITEM062=modern_acog +LISTITEM063=ww2_large_machine_gun +[AWARDDEFINITIONgeneric_aimless] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardaimless.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=70 +LOCATIONKILLCODESLISTITEM001=+COD1_left_arm_lower +LOCATIONKILLCODESLISTITEM002=+COD1_left_foot +LOCATIONKILLCODESLISTITEM003=+COD1_left_hand +LOCATIONKILLCODESLISTITEM004=+COD1_left_leg_lower +LOCATIONKILLCODESLISTITEM005=+COD1_right_arm_lower +LOCATIONKILLCODESLISTITEM006=+COD1_right_foot +LOCATIONKILLCODESLISTITEM007=+COD1_right_hand +LOCATIONKILLCODESLISTITEM008=+COD1_right_leg_lower +LOCATIONKILLCODESLISTITEM009=+COD2_left_arm_lower +LOCATIONKILLCODESLISTITEM010=+COD2_left_foot +LOCATIONKILLCODESLISTITEM011=+COD2_left_hand +LOCATIONKILLCODESLISTITEM012=+COD2_left_leg_lower +LOCATIONKILLCODESLISTITEM013=+COD2_right_arm_lower +LOCATIONKILLCODESLISTITEM014=+COD2_right_foot +LOCATIONKILLCODESLISTITEM015=+COD2_right_hand +LOCATIONKILLCODESLISTITEM016=+COD2_right_leg_lower +LOCATIONKILLCODESLISTITEM017=+COD4_left_arm_lower +LOCATIONKILLCODESLISTITEM018=+COD4_left_foot +LOCATIONKILLCODESLISTITEM019=+COD4_left_hand +LOCATIONKILLCODESLISTITEM020=+COD4_left_leg_lower +LOCATIONKILLCODESLISTITEM021=+COD4_right_arm_lower +LOCATIONKILLCODESLISTITEM022=+COD4_right_foot +LOCATIONKILLCODESLISTITEM023=+COD4_right_hand +LOCATIONKILLCODESLISTITEM024=+COD4_right_leg_lower +LOCATIONKILLCODESLISTITEM025=-COD1_head +LOCATIONKILLCODESLISTITEM026=-COD1_helmet +LOCATIONKILLCODESLISTITEM027=-COD1_left_arm_upper +LOCATIONKILLCODESLISTITEM028=-COD1_left_leg_upper +LOCATIONKILLCODESLISTITEM029=-COD1_neck +LOCATIONKILLCODESLISTITEM030=-COD1_none +LOCATIONKILLCODESLISTITEM031=-COD1_right_arm_upper +LOCATIONKILLCODESLISTITEM032=-COD1_right_leg_upper +LOCATIONKILLCODESLISTITEM033=-COD1_torso_lower +LOCATIONKILLCODESLISTITEM034=-COD1_torso_upper +LOCATIONKILLCODESLISTITEM035=-COD2_head +LOCATIONKILLCODESLISTITEM036=-COD2_helmet +LOCATIONKILLCODESLISTITEM037=-COD2_left_arm_upper +LOCATIONKILLCODESLISTITEM038=-COD2_left_leg_upper +LOCATIONKILLCODESLISTITEM039=-COD2_neck +LOCATIONKILLCODESLISTITEM040=-COD2_none +LOCATIONKILLCODESLISTITEM041=-COD2_right_arm_upper +LOCATIONKILLCODESLISTITEM042=-COD2_right_leg_upper +LOCATIONKILLCODESLISTITEM043=-COD2_torso_lower +LOCATIONKILLCODESLISTITEM044=-COD2_torso_upper +LOCATIONKILLCODESLISTITEM045=-COD4_head +LOCATIONKILLCODESLISTITEM046=-COD4_left_arm_upper +LOCATIONKILLCODESLISTITEM047=-COD4_left_leg_upper +LOCATIONKILLCODESLISTITEM048=-COD4_neck +LOCATIONKILLCODESLISTITEM049=-COD4_none +LOCATIONKILLCODESLISTITEM050=-COD4_right_arm_upper +LOCATIONKILLCODESLISTITEM051=-COD4_right_leg_upper +LOCATIONKILLCODESLISTITEM052=-COD4_torso_lower +LOCATIONKILLCODESLISTITEM053=-COD4_torso_upper +LOCATIONKILLCODESLISTITEM054=+cod5_left_arm_lower +LOCATIONKILLCODESLISTITEM055=+cod5_left_foot +LOCATIONKILLCODESLISTITEM056=+cod5_left_hand +LOCATIONKILLCODESLISTITEM057=+cod5_left_leg_lower +LOCATIONKILLCODESLISTITEM058=+cod5_right_arm_lower +LOCATIONKILLCODESLISTITEM059=+cod5_right_foot +LOCATIONKILLCODESLISTITEM060=+cod5_right_hand +LOCATIONKILLCODESLISTITEM061=+cod5_right_leg_lower +LOCATIONKILLCODESLISTITEM062=-cod5_head +LOCATIONKILLCODESLISTITEM063=-cod5_left_arm_upper +LOCATIONKILLCODESLISTITEM064=-cod5_left_leg_upper +LOCATIONKILLCODESLISTITEM065=-cod5_neck +LOCATIONKILLCODESLISTITEM066=-cod5_none +LOCATIONKILLCODESLISTITEM067=-cod5_right_arm_upper +LOCATIONKILLCODESLISTITEM068=-cod5_right_leg_upper +LOCATIONKILLCODESLISTITEM069=-cod5_torso_lower +LOCATIONKILLCODESLISTITEM070=-cod5_torso_upper +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Spray And Pray +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_daredevil] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awarddaredevil.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Dare Devil +WEAPONDEATHCODESLISTCOUNT=21 +WEAPONDEATHCODESLISTITEM001=+COD2_MOD_EXPLOSIVE +WEAPONDEATHCODESLISTITEM002=+COD2_MOD_FALLING +WEAPONDEATHCODESLISTITEM003=+COD2_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM004=+COD2_MOD_WATER +WEAPONDEATHCODESLISTITEM005=+COD4_mod_explosive +WEAPONDEATHCODESLISTITEM006=+COD4_mod_falling +WEAPONDEATHCODESLISTITEM007=+COD4_mod_trigger_hurt +WEAPONDEATHCODESLISTITEM008=+MOHAA_explode +WEAPONDEATHCODESLISTITEM009=+MOHAA_telefragged +WEAPONDEATHCODESLISTITEM010=+WOLFENSTEIN_MOD_CRUSH +WEAPONDEATHCODESLISTITEM011=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION +WEAPONDEATHCODESLISTITEM012=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER +WEAPONDEATHCODESLISTITEM013=+WOLFENSTEIN_MOD_EXPLOSIVE +WEAPONDEATHCODESLISTITEM014=+WOLFENSTEIN_MOD_FALLING +WEAPONDEATHCODESLISTITEM015=+WOLFENSTEIN_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM016=+WOLFENSTEIN_MOD_WATER +WEAPONDEATHCODESLISTITEM017=+cod5_explodable_barrel +WEAPONDEATHCODESLISTITEM018=+cod5_mod_explosive +WEAPONDEATHCODESLISTITEM019=+cod5_mod_falling +WEAPONDEATHCODESLISTITEM020=+cod5_destructible_car +WEAPONDEATHCODESLISTITEM021=+cod5_mod_trigger_hurt +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_deaths] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awarddeaths.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=1 +MISCCODESLISTITEM001=+Deaths +Name=Deaths +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_fall] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardfall.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Fallen Soldier +WEAPONDEATHCODESLISTCOUNT=5 +WEAPONDEATHCODESLISTITEM001=+COD1_MOD_FALLING +WEAPONDEATHCODESLISTITEM002=+COD2_MOD_FALLING +WEAPONDEATHCODESLISTITEM003=+COD4_mod_falling +WEAPONDEATHCODESLISTITEM004=+WOLFENSTEIN_MOD_FALLING +WEAPONDEATHCODESLISTITEM005=+cod5_mod_falling +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_grenade_killer] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgrenadekiller.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Grenade Killer +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_grenade +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_grenade_magnet] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgrenademagnet.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Grenade Magnet +WEAPONDEATHCODESLISTCOUNT=1 +WEAPONDEATHCODESLISTITEM001=+weapongroup_grenade +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_headshots] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardheadshot.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=4 +LOCATIONKILLCODESLISTITEM001=+COD1_head +LOCATIONKILLCODESLISTITEM002=+COD2_head +LOCATIONKILLCODESLISTITEM003=+COD4_head +LOCATIONKILLCODESLISTITEM004=+cod5_head +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Headshots +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_kills] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardkills.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=1 +MISCCODESLISTITEM001=+Kills +Name=Kills +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_knife] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardknife.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Knife +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=5 +WEAPONKILLCODESLISTITEM001=+COD2_knife_mp +WEAPONKILLCODESLISTITEM002=+COD4_BASH +WEAPONKILLCODESLISTITEM003=+WOLFENSTEIN_MOD_KNIFE +WEAPONKILLCODESLISTITEM004=+WOLFENSTEIN_MOD_KNIFE_STEALTH +WEAPONKILLCODESLISTITEM005=+cod5_bayonet +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_speech] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardloudmouth.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=1 +MISCCODESLISTITEM001=+Speech +Name=Loud Mouth +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_marksman] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardmarksman.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=46 +LOCATIONKILLCODESLISTITEM001=+COD1_head +LOCATIONKILLCODESLISTITEM002=+COD1_helmet +LOCATIONKILLCODESLISTITEM003=+COD1_neck +LOCATIONKILLCODESLISTITEM004=+COD2_head +LOCATIONKILLCODESLISTITEM005=+COD2_helmet +LOCATIONKILLCODESLISTITEM006=+COD2_neck +LOCATIONKILLCODESLISTITEM007=+COD4_head +LOCATIONKILLCODESLISTITEM008=+COD4_neck +LOCATIONKILLCODESLISTITEM009=-COD2_left_arm_lower +LOCATIONKILLCODESLISTITEM010=-COD2_left_arm_upper +LOCATIONKILLCODESLISTITEM011=-COD2_left_foot +LOCATIONKILLCODESLISTITEM012=-COD2_left_hand +LOCATIONKILLCODESLISTITEM013=-COD2_left_leg_lower +LOCATIONKILLCODESLISTITEM014=-COD2_left_leg_upper +LOCATIONKILLCODESLISTITEM015=-COD2_right_arm_lower +LOCATIONKILLCODESLISTITEM016=-COD2_right_arm_upper +LOCATIONKILLCODESLISTITEM017=-COD2_right_foot +LOCATIONKILLCODESLISTITEM018=-COD2_right_hand +LOCATIONKILLCODESLISTITEM019=-COD2_right_leg_lower +LOCATIONKILLCODESLISTITEM020=-COD2_right_leg_upper +LOCATIONKILLCODESLISTITEM021=-COD4_left_arm_lower +LOCATIONKILLCODESLISTITEM022=-COD4_left_arm_upper +LOCATIONKILLCODESLISTITEM023=-COD4_left_foot +LOCATIONKILLCODESLISTITEM024=-COD4_left_hand +LOCATIONKILLCODESLISTITEM025=-COD4_left_leg_lower +LOCATIONKILLCODESLISTITEM026=-COD4_left_leg_upper +LOCATIONKILLCODESLISTITEM027=-COD4_right_arm_lower +LOCATIONKILLCODESLISTITEM028=-COD4_right_arm_upper +LOCATIONKILLCODESLISTITEM029=-COD4_right_foot +LOCATIONKILLCODESLISTITEM030=-COD4_right_hand +LOCATIONKILLCODESLISTITEM031=-COD4_right_leg_lower +LOCATIONKILLCODESLISTITEM032=-COD4_right_leg_upper +LOCATIONKILLCODESLISTITEM033=+cod5_head +LOCATIONKILLCODESLISTITEM034=+cod5_neck +LOCATIONKILLCODESLISTITEM035=-cod5_left_arm_lower +LOCATIONKILLCODESLISTITEM036=-cod5_left_arm_upper +LOCATIONKILLCODESLISTITEM037=-cod5_left_foot +LOCATIONKILLCODESLISTITEM038=-cod5_left_hand +LOCATIONKILLCODESLISTITEM039=-cod5_left_leg_lower +LOCATIONKILLCODESLISTITEM040=-cod5_left_leg_upper +LOCATIONKILLCODESLISTITEM041=-cod5_right_arm_lower +LOCATIONKILLCODESLISTITEM042=-cod5_right_arm_upper +LOCATIONKILLCODESLISTITEM043=-cod5_right_foot +LOCATIONKILLCODESLISTITEM044=-cod5_right_hand +LOCATIONKILLCODESLISTITEM045=-cod5_right_leg_lower +LOCATIONKILLCODESLISTITEM046=-cod5_right_leg_upper +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Marksman +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_suicide] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsuicide.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Suicidal Tendencies +WEAPONDEATHCODESLISTCOUNT=16 +WEAPONDEATHCODESLISTITEM001=+COD1_MOD_FALLING +WEAPONDEATHCODESLISTITEM002=+COD1_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM003=+COD1_MOD_WATER +WEAPONDEATHCODESLISTITEM004=+COD2_MOD_FALLING +WEAPONDEATHCODESLISTITEM005=+COD2_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM006=+COD2_MOD_WATER +WEAPONDEATHCODESLISTITEM007=+COD4_mod_falling +WEAPONDEATHCODESLISTITEM008=+COD4_mod_trigger_hurt +WEAPONDEATHCODESLISTITEM009=+MOHAA_suicide +WEAPONDEATHCODESLISTITEM010=+MOHAA_telefragged +WEAPONDEATHCODESLISTITEM011=+WOLFENSTEIN_MOD_CRUSH +WEAPONDEATHCODESLISTITEM012=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION +WEAPONDEATHCODESLISTITEM013=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER +WEAPONDEATHCODESLISTITEM014=+WOLFENSTEIN_MOD_FALLING +WEAPONDEATHCODESLISTITEM015=+WOLFENSTEIN_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM016=+cod5_mod_falling +WEAPONDEATHCODESLISTITEM017=-cod5_mod_trigger_hurt +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_wrongplace] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardwrongplace.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Wrong Place Wrong Time +WEAPONDEATHCODESLISTCOUNT=11 +WEAPONDEATHCODESLISTITEM001=+COD1_MOD_CRUSH_JEEP +WEAPONDEATHCODESLISTITEM002=+COD1_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM003=+COD2_MOD_CRUSH_JEEP +WEAPONDEATHCODESLISTITEM004=+COD2_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM005=+COD4_mod_trigger_hurt +WEAPONDEATHCODESLISTITEM006=+MOHAA_telefragged +WEAPONDEATHCODESLISTITEM007=+WOLFENSTEIN_MOD_CRUSH +WEAPONDEATHCODESLISTITEM008=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTION +WEAPONDEATHCODESLISTITEM009=+WOLFENSTEIN_MOD_CRUSH_CONSTRUCTIONDEATH_NOATTACKER +WEAPONDEATHCODESLISTITEM010=+WOLFENSTEIN_MOD_TRIGGER_HURT +WEAPONDEATHCODESLISTITEM011=+cod5_mod_trigger_hurt +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_large_caliber] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardmg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Large Caliber Guns +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_large_machine_gun +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_shotgun] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardshotgun.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Shotgun +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_shotgun +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_sidearm] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsidearm.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Side Arm +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_pistol +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_sniper] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsniper.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Sniper +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_sniper +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_airstrike] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardairstrike.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Airstrike +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=8 +WEAPONKILLCODESLISTITEM001=+COD1_binoculars_artillery_mp +WEAPONKILLCODESLISTITEM002=+COD1_binoculars_mp +WEAPONKILLCODESLISTITEM003=+COD2_artillery_mp +WEAPONKILLCODESLISTITEM004=+COD2_binoculars_artillery_mp +WEAPONKILLCODESLISTITEM005=+COD4_artillery_mp +WEAPONKILLCODESLISTITEM006=+WOLFENSTEIN_MOD_ARTILLERY +WEAPONKILLCODESLISTITEM007=+WOLFENSTEIN_MOD_ARTY +WEAPONKILLCODESLISTITEM008=+cod5_artillery_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_ratio] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardratio.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=4 +MISCCODESLISTITEM001=+Kills +MISCCODESLISTITEM002=-Deaths +MISCCODESLISTITEM003=-Team Kills +MISCCODESLISTITEM004=-Suicides +Name=Ratio Reward +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_rpg] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardrpg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=RPG +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_bazooka +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONgeneric_silencer] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardstealth.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Silent But Deadly +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=23 +WEAPONKILLCODESLISTITEM001=+COD1_sten_silenced_mp +WEAPONKILLCODESLISTITEM002=+COD2_sten_silenced_mp +WEAPONKILLCODESLISTITEM003=+COD4_ak47_silencer_mp +WEAPONKILLCODESLISTITEM004=+COD4_ak74u_silencer_mp +WEAPONKILLCODESLISTITEM005=+COD4_beretta_silencer_mp +WEAPONKILLCODESLISTITEM006=+COD4_colt45_silencer_mp +WEAPONKILLCODESLISTITEM007=+COD4_g36c_silencer_mp +WEAPONKILLCODESLISTITEM008=+COD4_g3_silencer_mp +WEAPONKILLCODESLISTITEM009=+COD4_m14_silencer_mp +WEAPONKILLCODESLISTITEM010=+COD4_m16_silencer_mp +WEAPONKILLCODESLISTITEM011=+COD4_m4_silencer_mp +WEAPONKILLCODESLISTITEM012=+COD4_mp5_silencer_mp +WEAPONKILLCODESLISTITEM013=+COD4_p90_silencer_mp +WEAPONKILLCODESLISTITEM014=+COD4_skorpion_silencer_mp +WEAPONKILLCODESLISTITEM015=+COD4_usp_silencer_mp +WEAPONKILLCODESLISTITEM016=+COD4_uzi_silencer_mp +WEAPONKILLCODESLISTITEM017=+WOLFENSTEIN_MOD_KNIFE_STEALTH +WEAPONKILLCODESLISTITEM018=+WOLFENSTEIN_MOD_SILENCER +WEAPONKILLCODESLISTITEM019=+WOLFENSTEIN_MOD_SILENCED_COLT +WEAPONKILLCODESLISTITEM020=+cod5_gewehr43_silenced_mp +WEAPONKILLCODESLISTITEM021=+cod5_mp40_silenced_mp +WEAPONKILLCODESLISTITEM022=+cod5_sten_silenced_mp +WEAPONKILLCODESLISTITEM023=+cod5_thompson_silenced_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_fire] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardfire.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Admiral Mod: Fire Starter +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+COD2_fire_grenade_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_gas] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgas.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Gas Grenade +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+COD2_gas_grenade_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_medic] +ACTIONCODESLISTCOUNT=1 +ACTIONCODESLISTITEM001=+COD2_heal +GAMETYPECODESLISTCOUNT=0 +Image=awardmedic.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Doctor In The House +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_projectile] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardprojectile.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Projectile Professional +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=3 +WEAPONKILLCODESLISTITEM001=+COD2_artillery_mp +WEAPONKILLCODESLISTITEM002=+COD2_binoculars_artillery_mp +WEAPONKILLCODESLISTITEM003=+COD2_panzerschreck_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_tnt] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardtnt.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=TNT Mastermind +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+COD2_tnt_bomb_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONadmiral_purple_heart] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardheart.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Purple Heart +WEAPONDEATHCODESLISTCOUNT=4 +WEAPONDEATHCODESLISTITEM001=+COD2_MOD_GRENADE_SPLASH +WEAPONDEATHCODESLISTITEM002=+COD2_mod_head_shot +WEAPONDEATHCODESLISTITEM003=+COD2_MOD_PISTOL_BULLET +WEAPONDEATHCODESLISTITEM004=+COD2_MOD_RIFLE_BULLET +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_american] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardamerican.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=American +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=28 +WEAPONKILLCODESLISTITEM001=+COD1_bar_mp +WEAPONKILLCODESLISTITEM002=+COD1_bar_slow_mp +WEAPONKILLCODESLISTITEM003=+COD1_bazooka_mp +WEAPONKILLCODESLISTITEM004=+COD1_colt_mp +WEAPONKILLCODESLISTITEM005=+COD1_fraggrenade_mp +WEAPONKILLCODESLISTITEM006=+COD1_m1carbine_gfm_mp +WEAPONKILLCODESLISTITEM007=+COD1_m1carbine_mp +WEAPONKILLCODESLISTITEM008=+COD1_m1garand_mp +WEAPONKILLCODESLISTITEM009=+COD1_sherman_turret_mp +WEAPONKILLCODESLISTITEM010=+COD1_springfield_mp +WEAPONKILLCODESLISTITEM011=+COD1_thompson_mp +WEAPONKILLCODESLISTITEM012=+COD1_thompson_semi_mp +WEAPONKILLCODESLISTITEM013=+COD2_bar_mp +WEAPONKILLCODESLISTITEM014=+COD2_bar_slow_mp +WEAPONKILLCODESLISTITEM015=+COD2_bazooka_mp +WEAPONKILLCODESLISTITEM016=+COD2_colt_mp +WEAPONKILLCODESLISTITEM017=+COD2_frag_grenade_american_mp +WEAPONKILLCODESLISTITEM018=+COD2_frag_type1_american_mp +WEAPONKILLCODESLISTITEM019=+COD2_m1carbine_mp +WEAPONKILLCODESLISTITEM020=+COD2_m1garand_mp +WEAPONKILLCODESLISTITEM021=+COD2_thompson_mp +WEAPONKILLCODESLISTITEM022=+WOLFENSTEIN_MOD_AKIMBO_COLT +WEAPONKILLCODESLISTITEM023=+WOLFENSTEIN_MOD_COLT +WEAPONKILLCODESLISTITEM024=+WOLFENSTEIN_MOD_GARAND +WEAPONKILLCODESLISTITEM025=+WOLFENSTEIN_MOD_GARAND_SCOPE +WEAPONKILLCODESLISTITEM026=+WOLFENSTEIN_MOD_GRENADE +WEAPONKILLCODESLISTITEM027=+WOLFENSTEIN_MOD_SILENCED_COLT +WEAPONKILLCODESLISTITEM028=+WOLFENSTEIN_MOD_THOMPSON +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_british] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardbritish.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=British +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=14 +WEAPONKILLCODESLISTITEM001=+COD1_bren_mp +WEAPONKILLCODESLISTITEM002=+COD1_enfield_mp +WEAPONKILLCODESLISTITEM003=+COD1_mk1britishfrag_mp +WEAPONKILLCODESLISTITEM004=+COD1_sten_mp +WEAPONKILLCODESLISTITEM005=+COD1_sten_silenced_mp +WEAPONKILLCODESLISTITEM006=+COD1_webley_mp +WEAPONKILLCODESLISTITEM007=+COD2_bren_mp +WEAPONKILLCODESLISTITEM008=+COD2_enfield_mp +WEAPONKILLCODESLISTITEM009=+COD2_enfield_scope_mp +WEAPONKILLCODESLISTITEM010=+COD2_frag_grenade_british_mp +WEAPONKILLCODESLISTITEM011=+COD2_m1garand_mp +WEAPONKILLCODESLISTITEM012=+COD2_shotgun_mp +WEAPONKILLCODESLISTITEM013=+COD2_sten_mp +WEAPONKILLCODESLISTITEM014=+COD2_webley_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_russian] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardrussian.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Russian +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=18 +WEAPONKILLCODESLISTITEM001=+COD1_mosin_nagant_mp +WEAPONKILLCODESLISTITEM002=+COD1_mosin_nagant_sniper_mp +WEAPONKILLCODESLISTITEM003=+COD1_ppsh_mp +WEAPONKILLCODESLISTITEM004=+COD1_ppsh_semi_mp +WEAPONKILLCODESLISTITEM005=+COD1_rgd-33russianfrag_mp +WEAPONKILLCODESLISTITEM006=+COD1_sg43_tank_mp +WEAPONKILLCODESLISTITEM007=+COD1_sg43_turret_mp +WEAPONKILLCODESLISTITEM008=+COD1_svt40_mp +WEAPONKILLCODESLISTITEM009=+COD1_t34_turret_mp +WEAPONKILLCODESLISTITEM010=+COD1_tt33_mp +WEAPONKILLCODESLISTITEM011=+COD2_frag_grenade_russian_mp +WEAPONKILLCODESLISTITEM012=+COD2_frag_type1_russian_mp +WEAPONKILLCODESLISTITEM013=+COD2_mosin_nagant_mp +WEAPONKILLCODESLISTITEM014=+COD2_mosin_nagant_sniper_mp +WEAPONKILLCODESLISTITEM015=+COD2_ppsh_mp +WEAPONKILLCODESLISTITEM016=+COD2_shotgun_mp +WEAPONKILLCODESLISTITEM017=+COD2_SVT40_mp +WEAPONKILLCODESLISTITEM018=+COD2_TT30_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_german] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgerman.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=German +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=14 +WEAPONKILLCODESLISTITEM001=+COD1_elefant_turret_mp +WEAPONKILLCODESLISTITEM002=+COD1_gewehr43_mp +WEAPONKILLCODESLISTITEM003=+COD1_kar98k_mp +WEAPONKILLCODESLISTITEM004=+COD1_kar98k_sniper_mp +WEAPONKILLCODESLISTITEM005=+COD1_luger_mp +WEAPONKILLCODESLISTITEM006=+COD1_mp40_mp +WEAPONKILLCODESLISTITEM007=+COD1_mp44_mp +WEAPONKILLCODESLISTITEM008=+COD1_mp44_semi_mp +WEAPONKILLCODESLISTITEM009=+COD1_panther_turret_mp +WEAPONKILLCODESLISTITEM010=+COD1_panzerfaust_mp +WEAPONKILLCODESLISTITEM011=+COD1_panzeriv_turret_mp +WEAPONKILLCODESLISTITEM012=+COD1_panzerschreck_mp +WEAPONKILLCODESLISTITEM013=+COD1_ptrs41_antitank_rifle_mp +WEAPONKILLCODESLISTITEM014=+COD1_stielhandgranate_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_bash] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardbash.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Bash +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=4 +WEAPONKILLCODESLISTITEM001=+COD1_BASH +WEAPONKILLCODESLISTITEM002=+COD2_BASH +WEAPONKILLCODESLISTITEM003=+MOHAA_clubbed +WEAPONKILLCODESLISTITEM004=+cod5_bash +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_bolt_action_rifles] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardrifle.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Bolt Action Rifles +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=8 +WEAPONKILLCODESLISTITEM001=+MOHAA_rifle +WEAPONKILLCODESLISTITEM002=+WOLFENSTEIN_MOD_K43 +WEAPONKILLCODESLISTITEM003=+WOLFENSTEIN_MOD_MAUSER +WEAPONKILLCODESLISTITEM004=+weapongroup_kar98k +WEAPONKILLCODESLISTITEM005=+weapongroup_lee_enfield +WEAPONKILLCODESLISTITEM006=+weapongroup_mosin_nagant +WEAPONKILLCODESLISTITEM007=+weapongroup_springfield +WEAPONKILLCODESLISTITEM008=+weapongroup_type99_rifle +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_fast_loading_rifles] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsemirifle.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Fast Loading Rifles +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=5 +WEAPONKILLCODESLISTITEM001=+WOLFENSTEIN_MOD_GOOMBA +WEAPONKILLCODESLISTITEM002=+weapongroup_gewehr43 +WEAPONKILLCODESLISTITEM003=+weapongroup_m1carbine +WEAPONKILLCODESLISTITEM004=+weapongroup_m1garand +WEAPONKILLCODESLISTITEM005=+weapongroup_svt40 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_small_machine_gun] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsmg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Small Machine Gun Master +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=7 +WEAPONKILLCODESLISTITEM001=+COD2_greasegun_mp +WEAPONKILLCODESLISTITEM002=+MOHAA_smg +WEAPONKILLCODESLISTITEM003=+weapongroup_mp40 +WEAPONKILLCODESLISTITEM004=+weapongroup_ppsh +WEAPONKILLCODESLISTITEM005=+weapongroup_sten +WEAPONKILLCODESLISTITEM006=+weapongroup_thompson +WEAPONKILLCODESLISTITEM007=+weapongroup_type100smg +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_groundvehicles] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwgroundvehicles.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Ground Vehicles +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=10 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_desecrator +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_husky +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_titan +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_trojan +WEAPONKILLCODESLISTITEM005=+QUAKEWARS_platypus +WEAPONKILLCODESLISTITEM006=+QUAKEWARS_armadillo +WEAPONKILLCODESLISTITEM007=+QUAKEWARS_cyclops +WEAPONKILLCODESLISTITEM008=+QUAKEWARS_hog +WEAPONKILLCODESLISTITEM009=+QUAKEWARS_mcp +WEAPONKILLCODESLISTITEM010=+QUAKEWARS_tank_gun +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_flyingvehicles] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwflyingvehicles.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Flying Vehicles +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=3 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_anansi +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_flyer_drone +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_tormentor +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_meleeweapons] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwmelee.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Melee Weapons +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - Quake Wars: Melee Weapons +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=4 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_knife +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_knife_backstab +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_spikes +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_spikes_backstab +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_sidearms] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwsidearms.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Side Arms +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - Quake Wars: Side Arms +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=6 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_blaster +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_lightning_pistol +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_machine_pistol +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_pistol +WEAPONKILLCODESLISTITEM005=+QUAKEWARS_silenced_machine_pistol +WEAPONKILLCODESLISTITEM006=+QUAKEWARS_silenced_pistol +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_primaryweapons] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwprimaryweapons.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Primary Weapons +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - Quake Wars: Primary Weapons +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=12 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_assault_rifle +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_gpmg +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_hyperblaster +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_lacerator +WEAPONKILLCODESLISTITEM005=+QUAKEWARS_mg +WEAPONKILLCODESLISTITEM006=+QUAKEWARS_minigun +WEAPONKILLCODESLISTITEM007=+QUAKEWARS_nailgun +WEAPONKILLCODESLISTITEM008=+QUAKEWARS_obliterator +WEAPONKILLCODESLISTITEM009=+QUAKEWARS_railgun +WEAPONKILLCODESLISTITEM010=+QUAKEWARS_scoped_assault_rifle +WEAPONKILLCODESLISTITEM011=+QUAKEWARS_shotgun +WEAPONKILLCODESLISTITEM012=+QUAKEWARS_sniper_rifle +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_grenades] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwgrenades.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Explosives +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - Quake Wars: Explosives +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=9 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_emp_grenade +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_frag_grenade +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_grenade_launcher +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_he_charge +WEAPONKILLCODESLISTITEM005=+QUAKEWARS_proximity_mine +WEAPONKILLCODESLISTITEM006=+QUAKEWARS_scrambler_grenade +WEAPONKILLCODESLISTITEM007=+QUAKEWARS_shrap_grenade +WEAPONKILLCODESLISTITEM008=+QUAKEWARS_stroybomb +WEAPONKILLCODESLISTITEM009=+QUAKEWARS_tripmine +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_grenademagnet] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwgrenademagnet.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Grenade Magnet +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - Quake Wars: Grenade Magnet +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=8 +WEAPONDEATHCODESLISTITEM001=+QUAKEWARS_emp_grenade +WEAPONDEATHCODESLISTITEM002=+QUAKEWARS_frag_grenade +WEAPONDEATHCODESLISTITEM003=+QUAKEWARS_grenade_launcher +WEAPONDEATHCODESLISTITEM004=+QUAKEWARS_proximity_mine +WEAPONDEATHCODESLISTITEM005=+QUAKEWARS_scrambler_grenade +WEAPONDEATHCODESLISTITEM006=+QUAKEWARS_shrap_grenade +WEAPONDEATHCODESLISTITEM007=+QUAKEWARS_stroybomb +WEAPONDEATHCODESLISTITEM008=+QUAKEWARS_tripmine +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_defenseturrets] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwgrounddefense.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Ground Defense +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=4 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_aa_missile +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_airstrike_marker +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_artillery +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_rocket_artillery +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_firesupport] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardqwfiresupport.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Quake Wars: Fire Support +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=5 +WEAPONKILLCODESLISTITEM001=+QUAKEWARS_artillery +WEAPONKILLCODESLISTITEM002=+QUAKEWARS_hammer +WEAPONKILLCODESLISTITEM003=+QUAKEWARS_plasma_mortar +WEAPONKILLCODESLISTITEM004=+QUAKEWARS_rail_howitzer +WEAPONKILLCODESLISTITEM005=+QUAKEWARS_rocket_artillery +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONquakewars_xpengineer] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpengineeraward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Engineer +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Engineer +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_engineer +[AWARDDEFINITIONquakewars_xpfieldops] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpfieldopsaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Field Ops +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Field Ops +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_fieldops +[AWARDDEFINITIONquakewars_xpmedic] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpmedicaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Medic +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Medic +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_medic +[AWARDDEFINITIONquakewars_xpsoldier] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpsoldieraward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Soldier +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Soldier +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_soldier +[AWARDDEFINITIONquakewars_xpvehicle] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpvehiclehandlingaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Vehicle Handling +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Vehicle Handling +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_vehicle +[AWARDDEFINITIONquakewars_xpweaponhandling] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpweaponhandlingaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Weapon Handling +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Weapon Handling +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_weapon_handling +[AWARDDEFINITIONquakewars_xpbattlesense] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpbattletsenseaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Battle Sense +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Battle Sense +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_battlesense +[AWARDDEFINITIONquakewars_xpcovertops] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=xpcovertopsaward.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=XP Covert Ops +UPGRADEANSWERTYPE=1 +UPGRADEDESCRIPTION=Award - XP Covert Ops +UPGRADERECOMMENDATION= +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=N +XPCODESLISTCOUNT=1 +XPCODESLISTITEM001=+QUAKEWARS_covertops +[AWARDDEFINITIONmodern_assault] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardassault.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Assault Expert +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=7 +WEAPONKILLCODESLISTITEM001=+COD4_mp44_mp +WEAPONKILLCODESLISTITEM002=+weapongroup_ak47 +WEAPONKILLCODESLISTITEM003=+weapongroup_g3 +WEAPONKILLCODESLISTITEM004=+weapongroup_g36c +WEAPONKILLCODESLISTITEM005=+weapongroup_m14 +WEAPONKILLCODESLISTITEM006=+weapongroup_m16 +WEAPONKILLCODESLISTITEM007=+weapongroup_m4 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_explosives] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardexplosives.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Explosives Expert +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=4 +WEAPONKILLCODESLISTITEM001=+COD4_c4_mp +WEAPONKILLCODESLISTITEM002=+COD4_claymore_mp +WEAPONKILLCODESLISTITEM003=+COD4_destructible_car +WEAPONKILLCODESLISTITEM004=+COD4_mod_explosive +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_explosives_magnet] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardexplosivesmagnet.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Explosives Magnet +WEAPONDEATHCODESLISTCOUNT=4 +WEAPONDEATHCODESLISTITEM001=+COD4_c4_mp +WEAPONDEATHCODESLISTITEM002=+COD4_claymore_mp +WEAPONDEATHCODESLISTITEM003=+COD4_destructible_car +WEAPONDEATHCODESLISTITEM004=+COD4_mod_explosive +WEAPONKILLCODESLISTCOUNT=0 +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_grenade_launcher] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgrenadelauncher.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Grenade Launcher +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_noob_tubes +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_grip] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardgrip.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Grip Gunner +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=5 +WEAPONKILLCODESLISTITEM001=+COD4_m1014_grip_mp +WEAPONKILLCODESLISTITEM002=+COD4_m60e4_grip_mp +WEAPONKILLCODESLISTITEM003=+COD4_rpd_grip_mp +WEAPONKILLCODESLISTITEM004=+COD4_saw_grip_mp +WEAPONKILLCODESLISTITEM005=+COD4_winchester1200_grip_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_helicopter] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardhelicopter.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Helicopter Hero +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=1 +WEAPONKILLCODESLISTITEM001=+weapongroup_helicopter +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_heavy_gun] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardlmg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Heavy Guns Expert +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=3 +WEAPONKILLCODESLISTITEM001=+weapongroup_m60e4 +WEAPONKILLCODESLISTITEM002=+weapongroup_rpd +WEAPONKILLCODESLISTITEM003=+weapongroup_saw +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_red_dot] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardreddot.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Royal Red Dot +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=16 +WEAPONKILLCODESLISTITEM001=+COD4_ak47_reflex_mp +WEAPONKILLCODESLISTITEM002=+COD4_ak74u_reflex_mp +WEAPONKILLCODESLISTITEM003=+COD4_g36c_reflex_mp +WEAPONKILLCODESLISTITEM004=+COD4_g3_reflex_mp +WEAPONKILLCODESLISTITEM005=+COD4_m1014_reflex_mp +WEAPONKILLCODESLISTITEM006=+COD4_m14_reflex_mp +WEAPONKILLCODESLISTITEM007=+COD4_m16_reflex_mp +WEAPONKILLCODESLISTITEM008=+COD4_m4_reflex_mp +WEAPONKILLCODESLISTITEM009=+COD4_m60e4_reflex_mp +WEAPONKILLCODESLISTITEM010=+COD4_mp5_reflex_mp +WEAPONKILLCODESLISTITEM011=+COD4_p90_reflex_mp +WEAPONKILLCODESLISTITEM012=+COD4_rpd_reflex_mp +WEAPONKILLCODESLISTITEM013=+COD4_saw_reflex_mp +WEAPONKILLCODESLISTITEM014=+COD4_skorpion_reflex_mp +WEAPONKILLCODESLISTITEM015=+COD4_uzi_reflex_mp +WEAPONKILLCODESLISTITEM016=+COD4_winchester1200_reflex_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_sub_machine_gun] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardsmg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=SMG Master +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=5 +WEAPONKILLCODESLISTITEM001=+weapongroup_ak74u +WEAPONKILLCODESLISTITEM002=+weapongroup_mp5 +WEAPONKILLCODESLISTITEM003=+weapongroup_p90 +WEAPONKILLCODESLISTITEM004=+weapongroup_skorpion +WEAPONKILLCODESLISTITEM005=+weapongroup_uzi +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONmodern_acog] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardacog.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=ACOG Master +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=19 +WEAPONKILLCODESLISTITEM001=+COD4_ak47_acog_mp +WEAPONKILLCODESLISTITEM002=+COD4_ak74u_acog_mp +WEAPONKILLCODESLISTITEM003=+COD4_barrett_acog_mp +WEAPONKILLCODESLISTITEM004=+COD4_dragunov_acog_mp +WEAPONKILLCODESLISTITEM005=+COD4_g36c_acog_mp +WEAPONKILLCODESLISTITEM006=+COD4_g3_acog_mp +WEAPONKILLCODESLISTITEM007=+COD4_m14_acog_mp +WEAPONKILLCODESLISTITEM008=+COD4_m16_acog_mp +WEAPONKILLCODESLISTITEM009=+COD4_m21_acog_mp +WEAPONKILLCODESLISTITEM010=+COD4_m40a3_acog_mp +WEAPONKILLCODESLISTITEM011=+COD4_m4_acog_mp +WEAPONKILLCODESLISTITEM012=+COD4_m60e4_acog_mp +WEAPONKILLCODESLISTITEM013=+COD4_mp5_acog_mp +WEAPONKILLCODESLISTITEM014=+COD4_p90_acog_mp +WEAPONKILLCODESLISTITEM015=+COD4_remington700_acog_mp +WEAPONKILLCODESLISTITEM016=+COD4_rpd_acog_mp +WEAPONKILLCODESLISTITEM017=+COD4_saw_acog_mp +WEAPONKILLCODESLISTITEM018=+COD4_skorpion_acog_mp +WEAPONKILLCODESLISTITEM019=+COD4_uzi_acog_mp +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[AWARDDEFINITIONww2_large_machine_gun] +ACTIONCODESLISTCOUNT=0 +GAMETYPECODESLISTCOUNT=0 +Image=awardlmg.jpg +LOCATIONDEATHCODESLISTCOUNT=0 +LOCATIONKILLCODESLISTCOUNT=0 +LOCATIONTKCODESLISTCOUNT=0 +MISCCODESLISTCOUNT=0 +Name=Large Machine Guns +WEAPONDEATHCODESLISTCOUNT=0 +WEAPONKILLCODESLISTCOUNT=6 +WEAPONKILLCODESLISTITEM001=+weapongroup_bar +WEAPONKILLCODESLISTITEM002=+weapongroup_bren +WEAPONKILLCODESLISTITEM003=+weapongroup_dp28 +WEAPONKILLCODESLISTITEM004=+weapongroup_fg42 +WEAPONKILLCODESLISTITEM005=+weapongroup_mp44 +WEAPONKILLCODESLISTITEM006=+weapongroup_type99lmg +WEAPONTKCODESLISTCOUNT=0 +Weighted=Y +XPCODESLISTCOUNT=0 +[weapongroup_ak47] +COD4_ak47_acog_mp= +COD4_ak47_gl_mp= +COD4_ak47_mp= +COD4_ak47_reflex_mp= +COD4_ak47_silencer_mp= +[weapongroup_ak74u] +COD4_ak74u_acog_mp= +COD4_ak74u_mp= +COD4_ak74u_reflex_mp= +COD4_ak74u_silencer_mp= +[weapongroup_bar] +COD1_bar_mp= +COD1_bar_slow_mp= +COD2_bar_mp= +COD2_bar_slow_mp= +cod5_bar_bipod_crouch_mp= +cod5_bar_bipod_mp= +cod5_bar_bipod_prone_mp= +cod5_bar_bipod_stand_mp= +cod5_bar_mp= +[weapongroup_bazooka] +COD1_bazooka_mp= +COD1_panzerfaust_mp= +COD1_panzerschreck_mp= +COD2_bazooka_mp= +COD2_panzerschreck_mp= +COD4_rpg_mp= +cod5_bazooka_mp= +WOLFENSTEIN_MOD_PANZERFAUST= +WOLFENSTEIN_MOD_ROCKET= +WOLFENSTEIN_MOD_ROCKET_SPLASH= +[weapongroup_bolt_action_rifle] +COD4_barrett_acog_mp= +COD4_m21_acog_mp= +COD4_m40a3_acog_mp= +weapongroup_kar98k= +weapongroup_lee_enfield= +weapongroup_mosin_nagant= +weapongroup_springfield= +weapongroup_type99_rifle= +[weapongroup_bren] +COD1_bren_mp= +COD2_bren_mp= +cod5_bren_bipod_mp= +cod5_bren_mp= +[weapongroup_dp28] +COD1_dp28_mp= +cod5_dp28_bipod_crouch_mp= +cod5_dp28_bipod_mp= +cod5_dp28_bipod_prone_mp= +cod5_dp28_bipod_stand_mp= +cod5_dp28_mp= +[weapongroup_fast_loading_rifle] +weapongroup_g3= +weapongroup_gewehr43= +weapongroup_m1carbine= +weapongroup_m1garand= +weapongroup_svt40= +[weapongroup_fg42] +COD1_fg42_mp= +COD1_fg42_semi_mp= +cod5_fg42_bipod_crouch_mp= +cod5_fg42_bipod_mp= +cod5_fg42_bipod_prone_mp= +cod5_fg42_bipod_stand_mp= +cod5_fg42_mp= +[weapongroup_flamethrower] +COD1_flamethrower_mp= +COD1_MOD_FLAME= +COD2_flamethrower_mp= +cod5_m2_flamethrower_mp= +cod5_mod_burned= +WOLFENSTEIN_MOD_FLAMETHROWER= +[weapongroup_g3] +COD4_g3_acog_mp= +COD4_g3_gl_mp= +COD4_g3_mp= +COD4_g3_reflex_mp= +COD4_g3_silencer_mp= +[weapongroup_g36c] +COD4_g36c_acog_mp= +COD4_g36c_gl_mp= +COD4_g36c_mp= +COD4_g36c_reflex_mp= +COD4_g36c_silencer_mp= +[weapongroup_gewehr43] +COD1_gewehr43_mp= +COD2_g43_mp= +cod5_gewehr43_aperture_mp= +cod5_gewehr43_gl_mp= +cod5_gewehr43_mp= +cod5_gewehr43_silenced_mp= +[weapongroup_grenade] +COD1_fraggrenade_mp= +COD1_mk1britishfrag_mp= +COD1_rgd-33russianfrag_mp= +COD1_rgd_33russianfrag_mp= +COD1_smokegrenade_mp= +COD1_stielhandgranate_mp= +COD2_cook_frag_grenade_american_mp= +COD2_cook_frag_grenade_british_mp= +COD2_cook_frag_grenade_german_mp= +COD2_cook_frag_grenade_russian_mp= +COD2_fire_grenade_mp= +COD2_frag_grenade_american_mp= +COD2_frag_grenade_british_mp= +COD2_frag_grenade_german_mp= +COD2_frag_grenade_russian_mp= +COD2_frag_type1_american_mp= +COD2_frag_type1_british_mp= +COD2_frag_type1_german_mp= +COD2_frag_type1_russian_mp= +COD2_fraggrenade_mp= +COD2_gas_grenade_mp= +COD2_mk1britishfrag_mp= +COD2_MOD_GRENADE_SPLASH= +COD2_rgd-33russianfrag_mp= +COD2_sticky_bomb_mp= +COD4_concussion_grenade_mp= +COD4_flash_grenade_mp= +COD4_frag_grenade_mp= +COD4_frag_grenade_short_mp= +COD4_smoke_grenade_mp= +cod5_frag_grenade_mp= +cod5_frag_grenade_short_mp= +cod5_m8_white_smoke_mp= +cod5_molotov_mp= +cod5_signal_flare_mp= +cod5_sticky_grenade_mp= +cod5_tabun_gas_mp= +MOHAA_grenade= +WOLFENSTEIN_MOD_GRENADE= +WOLFENSTEIN_MOD_GRENADE_SPLASH= +[weapongroup_helicopter] +COD4_cobra_20mm_mp= +COD4_cobra_ffar_mp= +COD4_hind_ffar_mp= +[weapongroup_kar98k] +COD1_kar98k_mp= +COD2_kar98k_mp= +cod5_kar98k_bayonet_mp= +cod5_kar98k_gl_mp= +cod5_kar98k_mp= +WOLFENSTEIN_MOD_KAR98= +[weapongroup_landmine] +COD2_tnt_bomb_mp= +COD4_claymore_mp= +cod5_mine_bouncing_betty_mp= +MOHAA_mine= +[weapongroup_large_machine_gun] +weapongroup_m60e4= +weapongroup_mg42= +weapongroup_rpd= +weapongroup_saw= +weapongroup_type99lmg= +[weapongroup_lee_enfield] +COD1_enfield_mp= +COD2_enfield_mp= +cod5_lee_enfield_bayonet_mp= +cod5_lee_enfield_mp= +[weapongroup_m1014] +COD4_m1014_grip_mp= +COD4_m1014_mp= +COD4_m1014_reflex_mp= +[weapongroup_m14] +COD4_m14_acog_mp= +COD4_m14_gl_mp= +COD4_m14_mp= +COD4_m14_reflex_mp= +COD4_m14_silencer_mp= +[weapongroup_m16] +COD4_m16_acog_mp= +COD4_m16_gl_mp= +COD4_m16_mp= +COD4_m16_reflex_mp= +COD4_m16_silencer_mp= +[weapongroup_m1carbine] +COD1_m1carbine_gfm_mp= +COD1_m1carbine_mp= +COD1_medic_m1carbine_mp= +COD2_m1carbine_mp= +cod5_m1carbine_aperture_mp= +cod5_m1carbine_bayonet_mp= +cod5_m1carbine_bigammo_mp= +cod5_m1carbine_flash_mp= +cod5_m1carbine_gl_mp= +cod5_m1carbine_mp= +WOLFENSTEIN_MOD_CARBINE= +[weapongroup_m1garand] +COD1_m1garand_mp= +COD2_m1garand_mp= +cod5_m1garand_bayonet_mp= +cod5_m1garand_flash_mp= +cod5_m1garand_gl_mp= +cod5_m1garand_mp= +WOLFENSTEIN_MOD_GARAND= +WOLFENSTEIN_MOD_GARAND_SCOPE= +[weapongroup_m4] +COD4_m4_acog_mp= +COD4_m4_gl_mp= +COD4_m4_mp= +COD4_m4_reflex_mp= +COD4_m4_silencer_mp= +[weapongroup_m40a3] +COD4_m40a3_acog_mp= +COD4_m40a3_mp= +[weapongroup_m60e4] +COD4_m60e4_acog_mp= +COD4_m60e4_grip_mp= +COD4_m60e4_mp= +COD4_m60e4_reflex_mp= +[weapongroup_machine_gun] +MOHAA_mg= +weapongroup_ak47= +weapongroup_bar= +weapongroup_bren= +weapongroup_dp28= +weapongroup_fg42= +weapongroup_g36c= +weapongroup_m14= +weapongroup_m16= +weapongroup_m4= +weapongroup_mp44= +[weapongroup_mg30] +COD1_mg30cal_mp= +COD2_30cal_prone_mp= +COD2_30cal_stand_mp= +cod5_30cal_bipod_crouch_mp= +cod5_30cal_bipod_mp= +cod5_30cal_bipod_prone_mp= +cod5_30cal_bipod_stand_mp= +cod5_30cal_mp= +[weapongroup_mg42] +COD1_mg42_bipod_duck_mp= +COD1_mg42_bipod_prone_mp= +COD1_mg42_bipod_stand_mp= +COD1_mg42_mp= +COD2_mg42_bipod_duck_mp= +COD2_mg42_bipod_prone_mp= +COD2_mg42_bipod_stand_mp= +cod5_mg42_bipod_crouch_mp= +cod5_mg42_bipod_mp= +cod5_mg42_bipod_prone_mp= +cod5_mg42_bipod_stand_mp= +cod5_mg42_mp= +WOLFENSTEIN_MOD_MG42= +WOLFENSTEIN_MOD_MOBILE_MG42= +[weapongroup_mosin_nagant] +COD1_mosin_nagant_mp= +COD2_mosin_nagant_mp= +cod5_mosinrifle_bayonet_mp= +cod5_mosinrifle_gl_mp= +cod5_mosinrifle_mp= +[weapongroup_mp40] +COD1_mp40_mp= +COD2_mp40_mp= +cod5_mp40_aperture_mp= +cod5_mp40_bigammo_mp= +cod5_mp40_mp= +cod5_mp40_silenced_mp= +WOLFENSTEIN_MOD_MP40= +[weapongroup_mp44] +COD1_mp44_mp= +COD1_mp44_semi_mp= +COD2_am_mp44_mp= +COD2_mp44_mp= +COD4_mp44_mp= +[weapongroup_mp5] +COD4_mp5_acog_mp= +COD4_mp5_mp= +COD4_mp5_reflex_mp= +COD4_mp5_silencer_mp= +[weapongroup_noob_tubes] +COD4_gl_ak47_mp= +COD4_gl_g36c_mp= +COD4_gl_g3_mp= +COD4_gl_m14_mp= +COD4_gl_m16_mp= +COD4_gl_m4_mp= +cod5_gl_gewehr43_mp= +cod5_gl_kar98k_mp= +cod5_gl_m1carbine_mp= +cod5_gl_m1garand_mp= +cod5_gl_mosinrifle_mp= +cod5_gl_springfield_mp= +cod5_gl_type99rifle_mp= +[weapongroup_p90] +COD4_p90_acog_mp= +COD4_p90_mp= +COD4_p90_reflex_mp= +COD4_p90_silencer_mp= +[weapongroup_pistol] +COD1_colt_mp= +COD1_luger_mp= +COD2_colt_mp= +COD2_luger_mp= +COD2_TT30_mp= +COD2_webley_mp= +COD4_beretta_mp= +COD4_beretta_silencer_mp= +COD4_colt45_mp= +COD4_colt45_silencer_mp= +COD4_deserteagle_mp= +COD4_deserteaglegold_mp= +COD4_mod_pistol_bullet= +cod5_357_mp= +cod5_357magnum_mp= +cod5_colt_mp= +cod5_nambu_mp= +cod5_tokarev_mp= +cod5_walther_mp= +MOHAA_pistol= +WOLFENSTEIN_MOD_AKIMBO_COLT= +WOLFENSTEIN_MOD_AKIMBO_LUGER= +WOLFENSTEIN_MOD_COLT= +WOLFENSTEIN_MOD_LUGER= +WOLFENSTEIN_MOD_SILENCED_COLT= +[weapongroup_ppsh] +COD1_ppsh_mp= +COD1_ppsh_semi_mp= +COD2_ppsh_mp= +cod5_ppsh_aperture_mp= +cod5_ppsh_bigammo_mp= +cod5_ppsh_mp= +[weapongroup_rpd] +COD4_rpd_acog_mp= +COD4_rpd_grip_mp= +COD4_rpd_mp= +COD4_rpd_reflex_mp= +[weapongroup_satchelcharge] +COD1_satchelcharge_mp= +COD2_satchelcharge_mp= +COD4_c4_mp= +cod5_briefcase_bomb_mp= +cod5_satchel_charge_mp= +WOLFENSTEIN_MOD_SATCHEL= +[weapongroup_saw] +COD4_saw_acog_mp= +COD4_saw_bipod_crouch_mp= +COD4_saw_bipod_stand_mp= +COD4_saw_grip_mp= +COD4_saw_mp= +COD4_saw_reflex_mp= +[weapongroup_shotgun] +COD2_shotgun_mp= +COD4_winchester1200_grip_mp= +COD4_winchester1200_mp= +COD4_winchester1200_reflex_mp= +cod5_doublebarreledshotgun_grip_mp= +cod5_doublebarreledshotgun_mp= +cod5_doublebarreledshotgun_sawoff_mp= +cod5_shotgun_bayonet_mp= +cod5_shotgun_grip_mp= +cod5_shotgun_mp= +MOHAA_shotgun= +weapongroup_m1014= +[weapongroup_skorpion] +COD4_skorpion_acog_mp= +COD4_skorpion_mp= +COD4_skorpion_reflex_mp= +COD4_skorpion_silencer_mp= +[weapongroup_sniper] +COD1_kar98k_sniper_mp= +COD1_mosin_nagant_sniper_mp= +COD1_springfield_mp= +COD2_enfield_scope_mp= +COD2_kar98k_sniper_mp= +COD2_mosin_nagant_sniper_mp= +COD4_barrett_mp= +COD4_dragunov_mp= +COD4_m21_mp= +COD4_m40a3_mp= +COD4_remington700_mp= +COD4_usp_mp= +COD4_usp_silencer_mp= +cod5_fg42_scoped_mp= +cod5_fg42_telescopic_mp= +cod5_gewehr43_telescopic_mp= +cod5_kar98k_scoped_mp= +cod5_lee_enfield_scoped_mp= +cod5_m1garand_scoped_mp= +cod5_mosinrifle_scoped_mp= +cod5_springfield_scoped_mp= +cod5_stg44_telescopic_mp= +cod5_svt40_telescopic_mp= +cod5_type99rifle_scoped_mp= +MOHAA_sniper= +WOLFENSTEIN_MOD_GARAND_SCOPE= +WOLFENSTEIN_MOD_K43_SCOPE= +WOLFENSTEIN_MOD_SNIPERRIFLE= +[weapongroup_springfield] +cod5_springfield_bayonet_mp= +cod5_springfield_gl_mp= +cod5_springfield_mp= +[weapongroup_sten] +COD1_sten_mp= +COD1_sten_silenced_mp= +COD2_sten_mp= +cod5_sten_mp= +cod5_sten_silenced_mp= +WOLFENSTEIN_MOD_STEN= +[weapongroup_sub_machine_guns] +MOHAA_smg= +weapongroup_ak74u= +weapongroup_mp40= +weapongroup_mp5= +weapongroup_p90= +weapongroup_ppsh= +weapongroup_skorpion= +weapongroup_sten= +weapongroup_thompson= +weapongroup_type100smg= +weapongroup_uzi= +[weapongroup_svt40] +COD1_svt40_mp= +COD2_SVT40_mp= +cod5_svt40_aperture_mp= +cod5_svt40_flash_mp= +cod5_svt40_mp= +[weapongroup_tank] +COD1_30cal_tank_mp= +COD1_50cal_tank_mp= +COD1_elefant_turret_mp= +COD1_mg42_turret_mp= +COD1_pak40_turret_mp= +COD1_panther_turret_mp= +COD1_panzeriv_turret_mp= +COD1_sg43_tank_mp= +COD1_sg43_turret_mp= +COD1_sherman_turret_mp= +COD1_su152_turret_mp= +COD1_t34_turret_mp= +cod5_panzer4_gunner_front_mp= +cod5_panzer4_gunner_mp= +cod5_panzer4_mp_explosion_mp= +cod5_panzer4_turret_mp= +cod5_t34_gunner_front_mp= +cod5_t34_gunner_mp= +cod5_t34_mp_explosion_mp= +cod5_t34_turret_mp= +[weapongroup_thompson] +COD1_thompson_mp= +COD1_thompson_semi_mp= +COD2_thompson_mp= +cod5_thompson_aperture_mp= +cod5_thompson_bigammo_mp= +cod5_thompson_mp= +cod5_thompson_silenced_mp= +WOLFENSTEIN_MOD_THOMPSON= +[weapongroup_type100smg] +cod5_type100smg_aperture_mp= +cod5_type100smg_bigammo_mp= +cod5_type100smg_mp= +cod5_type100smg_silenced_mp= +[weapongroup_type99_rifle] +cod5_type99rifle_bayonet_mp= +cod5_type99rifle_gl_mp= +cod5_type99rifle_mp= +[weapongroup_type99lmg] +cod5_type99_lmg_bipod_crouch_mp= +cod5_type99_lmg_bipod_prone_mp= +cod5_type99_lmg_bipod_stand_mp= +cod5_type99lmg_bayonet_mp= +cod5_type99lmg_bipod_mp= +cod5_type99lmg_mp= +[weapongroup_uzi] +COD4_uzi_acog_mp= +COD4_uzi_mp= +COD4_uzi_reflex_mp= +COD4_uzi_silencer_mp= diff --git a/statsgen2_private.h b/statsgen2_private.h new file mode 100644 index 0000000..d292ab9 --- /dev/null +++ b/statsgen2_private.h @@ -0,0 +1,23 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT ! */ + +#ifndef STATSGEN2_PRIVATE_H +#define STATSGEN2_PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_STRING "0.1.1.1" +#define VER_MAJOR 0 +#define VER_MINOR 1 +#define VER_RELEASE 1 +#define VER_BUILD 1 +#define COMPANY_NAME "" +#define FILE_VERSION "" +#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE" +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "" +#define PRODUCT_NAME "" +#define PRODUCT_VERSION "" + +#endif /*STATSGEN2_PRIVATE_H*/