std::string GetTimeSpanStr(CTimeSpan t)
	{
		std::string strTime;

		if (t.GetDays() > 0)
			strTime = UtilWin::ToUTF8(t.Format(_T("%D, %H:%M:%S")));
		else strTime = UtilWin::ToUTF8(t.Format(_T("%H:%M:%S")));

		return strTime;
	}
예제 #2
0
CString g_GetAppRunningTimePerIteration(bool with_title)
{
	CString str;
	CTime EndTime = CTime::GetCurrentTime();
	CTimeSpan ts = EndTime - g_AppLastIterationStartTime;

	if (with_title)
		str = ts.Format("CPU Clock: %H:%M:%S --");
	else
		str = ts.Format("%H:%M:%S");
	return str;
}
예제 #3
0
LRESULT
CPDImfcDlg::OnDataStopped( WPARAM wP, LPARAM lP )
{
    TRACE0("CPDImfcDlg::OnDataStopped\n");
    CString     msg;

    CTimeSpan  ts = m_timeStop - m_timeStart;
    CString    s = ts.Format("%M:%S");
    msg.Format(_T("WM_PI_DATA_STOPPED: time elapsed %s,  %d frames collected, %d bytes, %d frames dropped, %d frames displayed\r\n"),
               (LPCTSTR)s, m_dwContFrameCount, m_dwContSize, m_dwOverflowCount, m_dwFramesDisplayed);
    AddMsg(msg);

    if (m_bCapture)
    {
        ParseFrame( g_pMotionBuf, m_dwContSize, TRUE );
    }

    if (m_bStyPno)
    {
        ClearStyMode();
    }

    m_bCont = FALSE;
    m_bStyPno = FALSE;
    m_bCapture = FALSE;

    EnableButtons();

    UpdateData(FALSE);

    return 0;
}
예제 #4
0
CString MyTools::GetFormatSpanTime(CTimeSpan span)
{
	CString str;
	//str = span.Format("%D:%H:%M:%S");
	str = span.Format(_T("%H:%M:%S"));
	return str;
}
예제 #5
0
void CProgressThreadDlg::SetFinished()
{
  if (m_uTimerID != 0) {
    KillTimer(m_uTimerID);
  }

  // update button
  CWnd* pWnd = GetDlgItem(IDC_CANCEL);
  ASSERT(pWnd);
  pWnd->SetWindowText("OK");

  char endTitle[80];
  MakeString(endTitle, m_sCaption, " Completed", 80);
  ChangeTitle(endTitle);

  // progress bar to end
  SetProgressStep(m_nSteps);

  // final time label
  pWnd = GetDlgItem(IDC_ELAPSED_TIME);
  ASSERT(pWnd);
  m_timeEnd = CTime::GetCurrentTime();
  CTimeSpan ts = m_timeEnd - m_timeStart;
  CString sText = ts.Format("Total elapsed time  %H:%M:%S");
  pWnd->SetWindowText(sText);

  m_bOkToClose = true;
}
예제 #6
0
void CDialogMistakes::UpdatePossible(){
	m_dTotalPossible = CBjDlg::m_dTotalPossible;
	m_dTotalPossible2 = CBjDlg::m_dTotalPossible;
	//add history
	if (m_pCurrentHistory){
		m_dTotalPossible += m_pCurrentHistory->m_dTotalPossible;
		m_dTotalPossible2 += m_pCurrentHistory->m_dTotalPossible2;
	}

	m_dTotalActual = m_dTotalPossible - m_dTotalMistakes;
	m_dTotalActual2 = m_dTotalPossible2 - m_dTotalMistakes2;
	//update the other stats as well
	m_nHandsPlayed = CBjDlg::m_nHandsPlayed;	
	//add history
	if (m_pCurrentHistory){
		m_nHandsPlayed += m_pCurrentHistory->m_nHandsPlayed;
	}

	m_dWinPerHand = m_dTotalActual/m_nHandsPlayed;
	m_dAvgStandardCount = CBjDlg::m_dAvgStandardCount;	
	m_nActualWin = m_pBjDlg->m_DlgPractice.m_nSessionMoney;
	m_dTheoreticalWin = m_dWinPerHand*m_nHandsPlayed*m_pBjDlg->m_nLowBet;
	//add history
	CTimeSpan total = CBjDlg::m_TotalPlayTime;
	if (m_pCurrentHistory){
		m_dAvgStandardCount = (m_dAvgStandardCount*CBjDlg::m_nHandsPlayed + m_pCurrentHistory->m_dAvgStandardCount*m_pCurrentHistory->m_nHandsPlayed);
		m_dAvgStandardCount /= m_nHandsPlayed;
		total += m_pCurrentHistory->m_TimePlayed;
		m_nActualWin += m_pCurrentHistory->m_nRealWin;
	}
	m_strTimePlayed = total.Format("%D days %H:%M");
	//add history
	UpdateData(FALSE);	
}
예제 #7
0
void DisplayElapsedTime( const CTimeSpan& totalTimeSpan, bool verbose )
{
    if ( verbose )
    {
        std::string s = totalTimeSpan.Format( "Elapsed time: %D days, %H hours, %M minutes, %S seconds" );
        std::cout << s << std::endl;
    }
}
예제 #8
0
파일: ChatDlg.cpp 프로젝트: bugou/test
void CChatDlg::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == IDT_TOTAL_TIME) {
		CTime now = CTime::GetCurrentTime();
		CTimeSpan span = now - startTime;
		SetDlgItemText(IDC_TOTAL_TIME, span.Format("%H:%M:%S"));
	} else
		CDialog::OnTimer(nIDEvent);
}
예제 #9
0
ALERROR CUniverse::InitImages (SDesignLoadCtx &Ctx, CXMLElement *pImages, CResourceDb &Resources)

//	InitImages
//
//	Loads all images

	{
	ALERROR error;

	//	Nothing to do if we don't want to load resources

	if (Ctx.bNoResources)
		return NOERROR;

	//	Figure out if we've got a special folder for the images

	CString sRoot = pImages->GetAttribute(FOLDER_ATTRIB);
	Ctx.sFolder = sRoot;

#ifdef DEBUG_TIME_IMAGE_LOAD
	CTimeDate StartTime(CTimeDate::Now);
#endif

	//	Load all images

	for (int i = 0; i < pImages->GetContentElementCount(); i++)
		{
		CXMLElement *pItem = pImages->GetContentElement(i);

		if (error = LoadImage(Ctx, pItem))
			return error;
		}

	//	Restore folder

	Ctx.sFolder = NULL_STR;

#ifdef DEBUG_TIME_IMAGE_LOAD
	{
	CTimeDate StopTime(CTimeDate::Now);
	CTimeSpan Timing = timeSpan(StartTime, StopTime);
	CString sTime = Timing.Format(CString());
	kernelSetDebugLog("Time to load images: ");
	kernelSetDebugLog(sTime.GetASCIIZPointer());
	kernelSetDebugLog("\n");
	}
#endif

	return NOERROR;
	}
예제 #10
0
void CAddTimer::UpdateDuration()
{
	CTimeSpan aday(1,0,0,0);
	CTimeSpan tempduration;
	CTime end, start;
	UpdateData(TRUE);

	//m_endtime.GetTime(end);
	//m_starttime.GetTime(start);
	end = m_endtimex;
	start = m_starttimex;

	if (end < start) end += aday;

	tempduration = end - start;

	//Only enable ok button if duration is greater than 0
	if((tempduration.GetTotalSeconds() > 0) && (m_channellist.GetCurSel() != LB_ERR)){
		m_ok.EnableWindow(TRUE);
	}else{
		m_ok.EnableWindow(FALSE);
	}

	CString temp;
	if(tempduration.GetHours()>0) temp += tempduration.Format("%Hhr");
	if(tempduration.GetMinutes()>0)  temp += tempduration.Format("%Mmin");
	//temp += duration.Format("%Ssec");
	m_duration = temp;
	
	
	//Get programme name from guide
	CProgGuideDlg pgdlg(NULL,NULL);
	m_progname = pgdlg.getProg(m_channellist.GetCurSel(),m_starttimex);

	UpdateData(FALSE);

}
예제 #11
0
void CProgressThreadDlg::SetTimeLabel()
{
  if (!IsReady()) {
    return;
  }

  CWnd* pWnd = GetDlgItem(IDC_ELAPSED_TIME);
  if (pWnd)
  {
//    ASSERT(pWnd);
    CTimeSpan ts = CTime::GetCurrentTime() - m_timeStart;
    CString sText = ts.Format( "Time elapsed   %H:%M:%S" );
    pWnd->SetWindowText(sText);
  }
}
예제 #12
0
void CDCMasterDlg::UpdateReponseStatus()
{
	for(UINT i=0;i<(UINT)m_collector_list.GetItemCount();i++)
	{
		/*
		char time[32];
		UINT ctime=0;
		m_collector_list.GetItemText(i,SUB_CTIME,time,sizeof(time));
		sscanf(time,"%u",&ctime);
		CTime response = (CTime)ctime;
		//CTime response = (CTime)m_collector_list.GetItemData(i);
		CTimeSpan ts = CTime::GetCurrentTime() - response;
		*/
		CString ip = m_collector_list.GetItemText(i,SUB_COLLECTOR);
		CString network = m_collector_list.GetItemText(i,SUB_NETWORK);
		CTimeSpan ts = CTime::GetCurrentTime() - p_parent->GetLastResponseTime(ip,network);
		CString timestring = ts.Format("%H:%M:%S");
		m_collector_list.SetItemText(i,SUB_PING_TIME, timestring);
	}
}
예제 #13
0
파일: BTools2.cpp 프로젝트: berise/BTools2
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
#ifdef __EXPIRATION__
	// Program Expiration routines
	CTime expirationTime(2010,	// year
		2,					// month
		30,					// date
		23,					// hour 24
		59,					// minute
		59);				// second
	CTime currentTime = CTime::GetCurrentTime();

    CTimeSpan leftTime = expirationTime - currentTime;   

	// 사용 기간이 남았을 경우
	if(leftTime.GetTotalSeconds() > 0)
    {
		 CString msg;
		 msg = L"";
		 msg += L"This is a trial version of BTools2\n";
		 msg += expirationTime.Format(L"Expiration date :\n %Y-%m-%d  %H:%M:%S\n\n");
		 msg += leftTime.Format(L"%D day(s) and\n %H:%M:%S left" );
     
		 // 사용 기간이 3일 미만 남았을 경우
		 if(leftTime.GetDays() < 7)
		 {
			 msg = leftTime.Format(L"This software will expire after %D day(s)");// %H Hour(s) %M Minute(s)");
			 //AtlMessageBox(NULL, msg.GetBuffer(), L"Expiration Warning");
		 }
		 //AfxMessageBox(msg);
    }
    else // 사용 기간이 만료된 경우
    {
		CString msg("This is a trial version of BTools2\n"
				"If you want to use this software more\n"
				"Please contact to me.\[email protected]\n"
				"Thank you for your interest\n");

		msg += expirationTime.Format(L"Expiration date :\n %Y-%m-%d  %H:%M\n\n");
		msg += leftTime.Format(L"%D day(s) and\n %H:%M:%S passed" );
        //msg.Format(L"This software is submitted for the Windows Mobile Contest");
		//AtlMessageBox(NULL, msg.GetBuffer(), L"Warning");
		return FALSE;
	 }

#endif

#ifdef __TSTORE_ARM__0
	// ARM
	T_RETURN ret;
	TAPPID *APPID = TSTORE_APPLICATION_ID;

	bool aSuccess=true;

	T_RETURN res; 
	ARM_PLUGIN_Initialize(&res,APPID);
	if (res.code == ARM_SUCCESS) 
	{
		ARM_PLUGIN_CheckLicense(&res); 
		if (res.code == ARM_SUCCESS) 
		{ 
			ARM_PLUGIN_RequestLicense(&res); 
			if (res.code !=ARM_SUCCESS) 
			{ //실패시 구현 
				aSuccess=false;
				TCHAR wszMsg[1024];
				if(ret.pMsg)
				{
					ansi_to_unicode(ret.pMsg, strlen(ret.pMsg), wszMsg, 1024);
					::AtlMessageBox(NULL, wszMsg, L"[ARM]Request License");
				}
			}
		
		} 
		else 
		{//실패시 메시 구현 
			aSuccess=false;

			TCHAR wszMsg[1024];

			switch(res.code)
			{
			case CLICENSE_DENY:
			case CLICENSE_NOT_EXIST:
			case CLICENSE_EXPIRED:
			case CLICENSE_INVALID:
				{
					if(ret.pMsg)
					{
						ansi_to_unicode(ret.pMsg, strlen(ret.pMsg), wszMsg, 1024);
						::AtlMessageBox(NULL, wszMsg, L"[ARM]Check License");
					}
				}

			default:
				;
			}
		} 
	} 
	else 
	{ 
		aSuccess=false; 
	} 
	ARM_PLUGIN_Uninitialize(&res); 


	//if (! aSuccess) return 0;//PostQuitMessage(0); 

#endif

	//CAboutDlg aboutDlg;	aboutDlg.DoModal();
    //
	HRESULT hRes = CBTools2Frame::ActivatePreviousInstance(hInstance, lpstrCmdLine);

	if(FAILED(hRes) || S_FALSE == hRes)
	{
		return hRes;
	}

	hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
	ATLASSERT(SUCCEEDED(hRes));

	AtlInitCommonControls(ICC_DATE_CLASSES);
	SHInitExtraControls();

	hRes = _Module.Init(NULL, hInstance);
	ATLASSERT(SUCCEEDED(hRes));

	int nRet = CBTools2Frame::AppRun(lpstrCmdLine, nCmdShow);

	_Module.Term();
	::CoUninitialize();

	return nRet;
}
예제 #14
0
파일: MainFrm.cpp 프로젝트: DUNE/kx509
LONG CMainFrame::OnSysTrayMessage(
	WPARAM			uID, 
	LPARAM			lEvent
) 
{
	DWORD			nMenuItem	= -1;
	CTimeSpan		timeLeft	= 0;


	if (uID != IDI_UNAUTH) {
		return(0);
	}
	// You can select which way the Shell should behave by calling Shell_NotifyIcon with dwMessage set to NIM_SETVERSION. 
	// Set the uVersion member of the NOTIFYICONDATA structure to indicate whether you want version 5.0 or pre-version 5.0 behavior.

	switch (lEvent) {
		case (WM_CONTEXTMENU) :			// 
		case (WM_RBUTTONUP) : {
			// Do SysTray Menu stuff
			switch (this->SysTrayMenu())
			{
				case IDS_EXIT_APP:
					PostQuitMessage(0);
					return(1);
				case IDS_SILENT_SELECT:
					SetSilentSelectFlag((bSilentSelect==FALSE) ? TRUE : FALSE);
					break;
				default:
					break;
			}
		}
		case (WM_LBUTTONDBLCLK) : {
			// FORCE RE-FETCH OF CERT (USEFUL IF CHANGED KERB-IDENTITY PRIOR TO CERT EXPIRE)
			char	**argv = NULL;
			int		argc = 0;

			bPwdPrompt = TRUE;
			if (bkx509busy == FALSE) {
				bkx509busy = TRUE;
			    kx509_main(kx509_argc, kx509_argv);
				bkx509busy= FALSE;
			}
			bPwdPrompt = FALSE;

			return(1);
			break;
		}
		case (WM_MOUSEMOVE) : {
			// Show Current User Identity
			CString		sTimeLeft;
			char		*szTimeLeft = NULL;
			char		*szSubj		= NULL;
			char		tip[128]	= {0};
			char		*krbv		= KX509_CLIENT_KRB;


#ifdef USE_KRB5
#  ifdef USE_MSK5
			sprintf(tip, "%s %s: <Lock-Unlock screen or Double-Click Icon to get Certificate>\n\n", krbv, KX509_CLIENT_VERSION);
#  else // !USE_MSK5
			sprintf(tip, "%s %s: <Double-Click Icon to acquire tickets to get Certificate>\n\n", krbv, KX509_CLIENT_VERSION);
#  endif // !USE_MSK5
#else // !USE_KRB5
			sprintf(tip, "%s %s: <Double-Click Icon to acquire tickets to get Certificate>\n\n", krbv, KX509_CLIENT_VERSION);
#endif // !USE_KRB5

			if (strlen(gszHardErrorMsg))
			{
				sprintf(tip, "%s %s: ", krbv, KX509_CLIENT_VERSION);
				strncat(tip, gszHardErrorMsg, 63);
				strcat(tip, "\n\n");
			}
			else if (szStatusMsg)
			{
				sprintf(tip, "%s %s: ", krbv, KX509_CLIENT_VERSION);
				strncat(tip, szStatusMsg, 63);
				strcat(tip, "\n\n");
			}
			else
			{
				szSubj		= get_cert_subj(szCertRealm);
				if (szSubj)
				{
			log_printf("CMainFrame::OnSysTrayMessage: before get_cert_time_left.\n");
					get_cert_time_left(szCertRealm, &timeLeft);
					sTimeLeft	= timeLeft.Format(" %H hours, %M minutes");
					if (szTimeLeft = (char *)malloc(256))
					{
						if (strlen(szSubj) > 30)
							szSubj = szCertRealm;

						strcpy(szTimeLeft, sTimeLeft.GetBuffer(64));

						if (timeLeft.GetTotalMinutes() < 0)
							sprintf(tip, "%s %s: Cert for %s: EXPIRED\n\n", krbv, KX509_CLIENT_VERSION, szSubj);
						else
							sprintf(tip, "%s %s: Cert for %s: %s\n\n", krbv, KX509_CLIENT_VERSION, szSubj, szTimeLeft);
						free(szTimeLeft);
						szTimeLeft = NULL;
					}
			log_printf("CMainFrame::OnSysTrayMessage: before free.\n");
					free(szSubj);
					szSubj = NULL;
				}
			}
		log_printf("CMainFrame::OnSysTrayMessage: before ChangeSysTrayTip.\n");
			m_trayIcon.ChangeSysTrayTip(tip);

			// No "return(1)"  Let the system finish up for us.
			break;
		}
	}
	return(0);
}
예제 #15
0
void CActivityView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
{
bool bInserting = false;
POSITION pos;
int nDocCount;
CListCtrl & pList = GetListCtrl ();

// if we don't want list updated right now, then exit

  if (m_bUpdateLockout)
    return;

//  TRACE ("Activity window being updated\n");

  m_bUpdateLockout = TRUE;

  App.m_bUpdateActivity = FALSE;

  App.m_timeLastActivityUpdate = CTime::GetCurrentTime();

// if the list has the same number of worlds (and they are the same
// worlds), then we can not bother deleting the list and re-adding it

// first, count worlds

 	pos = App.m_pWorldDocTemplate->GetFirstDocPosition();
  for (nDocCount = 0; pos; nDocCount++)
       App.m_pWorldDocTemplate->GetNextDoc(pos);

// if count is the same, check world is the same as in the list

  if (nDocCount == pList.GetItemCount ())
    {
   	pos = App.m_pWorldDocTemplate->GetFirstDocPosition();
    while (pos)
      {
       CMUSHclientDoc* pDoc = (CMUSHclientDoc*) App.m_pWorldDocTemplate->GetNextDoc(pos);
       int nItem = pDoc->m_view_number - 1;
       if (nItem < 0)
         {
         bInserting = true;
         break;
         }
       if ((DWORD) pDoc != pList.GetItemData (nItem))
         {
         bInserting = true;
         break;
         }
      }   // end of looping through each world
    }     // end of world count being same as list count
  else
    bInserting = true;    // different counts, must re-do list

  if (bInserting)
    pList.DeleteAllItems ();

// add all documents to the list

 	pos = App.m_pWorldDocTemplate->GetFirstDocPosition();

	for (int nItem = 0; pos != NULL; nItem++)
	{
    CMUSHclientDoc* pDoc = (CMUSHclientDoc*) App.m_pWorldDocTemplate->GetNextDoc(pos);

    if (bInserting)
      pDoc->m_view_number = nItem + 1;    // so we can use Ctrl+1 etc.
    else
      nItem = pDoc->m_view_number - 1;    // use existing item number

    CString strSeq;
    CString strLines;
    CString strNewLines;
    CString strStatus;
    CString strSince;
    CString strDuration;

    strSeq.Format   ("%ld", pDoc->m_view_number);
    strNewLines.Format ("%ld", pDoc->m_new_lines);
    strLines.Format ("%ld", pDoc->m_total_lines);

// work out world status

    strStatus = GetConnectionStatus (pDoc->m_iConnectPhase);

// when they connected

    if (pDoc->m_iConnectPhase == eConnectConnectedToMud)
      strSince = pDoc->FormatTime (pDoc->m_tConnectTime, "%#I:%M %p, %d %b");
    else
      strSince.Empty ();

// work out world connection duration

    // first time spent in previous connections
    CTimeSpan ts = pDoc->m_tsConnectDuration;
    
    // now time spent connected in this session, if we are connected
    if (pDoc->m_iConnectPhase == eConnectConnectedToMud)
      ts += CTime::GetCurrentTime() - pDoc->m_tConnectTime;
  
    if (ts.GetDays () > 0)
      strDuration = ts.Format ("%Dd %Hh %Mm %Ss");
    else
      if (ts.GetHours () > 0)
        strDuration = ts.Format ("%Hh %Mm %Ss");
      else
        if (ts.GetMinutes () > 0)
          strDuration = ts.Format ("%Mm %Ss");
        else
          strDuration = ts.Format ("%Ss");
	
    // sequence
    if (bInserting)
      pList.InsertItem (nItem, strSeq);  //  eColumnSeq
	  pList.SetItemText(nItem, eColumnMush, pDoc->m_mush_name);
		pList.SetItemText(nItem, eColumnNew, strNewLines);
 		pList.SetItemText(nItem, eColumnLines, strLines);
  	pList.SetItemText(nItem, eColumnStatus, strStatus);
		pList.SetItemText(nItem, eColumnSince, strSince);
		pList.SetItemText(nItem, eColumnDuration, strDuration);

    if (bInserting)
      pList.SetItemData(nItem, (DWORD) pDoc);

    LVITEM lvitem;

    memset (&lvitem, 0, sizeof lvitem);

    // update where tick goes
    lvitem.iImage = 0;
    
    if (pDoc->m_pActiveCommandView || pDoc->m_pActiveOutputView)
      lvitem.iImage = 1;  // show the tick

    lvitem.mask = LVIF_IMAGE;
    lvitem.iItem = nItem;

    pList.SetItem (&lvitem);



   }    // end of searching for all documents

// make sure in same order that we left them

  pList.SortItems (CompareFunc, m_reverse << 8 | m_last_col); 

  m_bUpdateLockout = FALSE;

}     // end of CActivityView::OnUpdate
예제 #16
0
void CPlayerGameStats::GenerateGameStats (CGameStats &Stats, CSpaceObject *pPlayerShip, bool bGameOver) const

//	GenerateGameStats
//
//	Generates a stats for everything we track

	{
	int j;

	CShip *pShip = (pPlayerShip ? pPlayerShip->AsShip() : NULL);
	if (pShip == NULL)
		return;

	CPlayerShipController *pPlayer = (CPlayerShipController *)pShip->GetController();
	if (pPlayer == NULL)
		return;

	CSovereign *pPlayerSovereign = g_pUniverse->FindSovereign(g_PlayerSovereignUNID);
	if (pPlayerSovereign == NULL)
		return;

	//	Base stats

	Stats.Insert(CONSTLIT("Genome"), strCapitalize(GetGenomeName(pPlayer->GetPlayerGenome())));
	Stats.Insert(CONSTLIT("Score"), strFormatInteger(CalcEndGameScore(), -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED));
	Stats.Insert(CONSTLIT("Ship class"), pShip->GetNounPhrase(0));

	CTimeSpan Time = GetPlayTime();
	if (!Time.IsBlank())
		Stats.Insert(CONSTLIT("Time played"), Time.Format(NULL_STR));

#ifdef REAL_TIME
	Time = GetGameTime();
	if (!Time.IsBlank())
		Stats.Insert(CONSTLIT("Time elapsed in game"), Time.Format(NULL_STR));
#endif

	//	Some combat stats

	CString sDestroyed = GetStat(ENEMY_SHIPS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Enemy ships destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(FRIENDLY_SHIPS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Friendly ships destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(ENEMY_STATIONS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Enemy stations destroyed"), sDestroyed, CONSTLIT("combat"));

	sDestroyed = GetStat(FRIENDLY_STATIONS_DESTROYED_STAT);
	if (!sDestroyed.IsBlank())
		Stats.Insert(CONSTLIT("Friendly stations destroyed"), sDestroyed, CONSTLIT("combat"));

	//	Add stat for every station destroyed

	CStatCounterArray CounterArray;

	CMapIterator i;
	m_StationStats.Reset(i);
	while (m_StationStats.HasMore(i))
		{
		SStationTypeStats *pStats;
		DWORD dwUNID = m_StationStats.GetNext(i, &pStats);
		CStationType *pType = g_pUniverse->FindStationType(dwUNID);
		if (pType == NULL)
			continue;

		CString sName = pType->GetNounPhrase(0);
		CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pType->GetLevel(), sName);

		if (pType->GetSovereign()->IsEnemy(pPlayerSovereign))
			CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Enemy stations destroyed"), sSort);
		else
			CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Friendly stations destroyed"), sSort);
		}

	CounterArray.GenerateGameStats(Stats);
		
	//	Add stat for every ship class destroyed

	CounterArray.DeleteAll();
	m_ShipStats.Reset(i);
	while (m_ShipStats.HasMore(i))
		{
		SShipClassStats *pStats;
		DWORD dwUNID = m_ShipStats.GetNext(i, &pStats);
		CShipClass *pClass = g_pUniverse->FindShipClass(dwUNID);
		if (pClass == NULL)
			continue;

		CString sName = pClass->GetNounPhrase(0);
		CString sSort = strPatternSubst(CONSTLIT("%09d%s"), 100000000 - pClass->GetScore(), sName);

		if (pStats->iEnemyDestroyed > 0)
			CounterArray.Insert(sName, pStats->iEnemyDestroyed, CONSTLIT("Enemy ships destroyed"), sSort);

		if (pStats->iFriendDestroyed > 0)
			CounterArray.Insert(sName, pStats->iFriendDestroyed, CONSTLIT("Friendly ships destroyed"), sSort);
		}

	CounterArray.GenerateGameStats(Stats);

	//	Add stat for every weapon fired

	m_ItemStats.Reset(i);
	while (m_ItemStats.HasMore(i))
		{
		SItemTypeStats *pStats;
		DWORD dwUNID = m_ItemStats.GetNext(i, &pStats);
		CItemType *pItemType = g_pUniverse->FindItemType(dwUNID);
		if (pItemType == NULL)
			continue;

		CString sName = pItemType->GetNounPhrase(nounShort);
		CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pItemType->GetLevel(), sName);

		//	Installed items

		if (pStats->dwFirstInstalled != INVALID_TIME)
			Stats.Insert(sName, NULL_STR, CONSTLIT("Items installed"), sSort);

		if (pStats->iCountFired > 0)
			Stats.Insert(sName, 
					strFormatInteger(pStats->iCountFired, -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED), 
					CONSTLIT("Weapons fired"), 
					sSort);
		}

	//	Stats for player equipment (but only if the game is done)

	if (bGameOver)
		{
		TSortMap<CString, CItem> InstalledItems;

		//	First we generate a sorted list of installed items
		//	(We do this in case there are multiple of the same device/armor so that
		//	we can coalesce them together into a single line).

		CItemListManipulator ItemList(pShip->GetItemList());
		ItemList.ResetCursor();
		while (ItemList.MoveCursorForward())
			{
			const CItem &Item(ItemList.GetItemAtCursor());

			if (Item.IsInstalled())
				{
				CString sEnhancement = Item.GetEnhancedDesc(pShip);
				CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly | nounShort);
				CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));

				bool bInserted;
				CItem *pEntry = InstalledItems.SetAt(sLine, &bInserted);
				if (bInserted)
					{
					*pEntry = Item;
					pEntry->SetCount(1);
					}
				else
					pEntry->SetCount(pEntry->GetCount() + 1);
				}
			}

		//	Now add all the installed items to the stats

		for (j = 0; j < InstalledItems.GetCount(); j++)
			{
			//	Redo the line now that we know the proper count

			CString sEnhancement = InstalledItems[j].GetEnhancedDesc(pShip);
			CString sItemName = InstalledItems[j].GetNounPhrase(nounActual | nounCountOnly);
			CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));

			//	Compute the sort order

			int iOrder;
			switch (InstalledItems[j].GetType()->GetCategory())
				{
				case itemcatWeapon:
					iOrder = 0;
					break;

				case itemcatLauncher:
					iOrder = 1;
					break;

				case itemcatShields:
					iOrder = 2;
					break;

				case itemcatArmor:
					iOrder = 3;
					break;

				case itemcatReactor:
					iOrder = 4;
					break;

				case itemcatDrive:
					iOrder = 5;
					break;

				default:
					iOrder = 6;
					break;
				}

			CString sSort = strPatternSubst(CONSTLIT("%d%03d%s"), iOrder, 100 - InstalledItems[j].GetType()->GetLevel(), sLine);
			Stats.Insert(sLine, NULL_STR, CONSTLIT("Final equipment"), sSort);
			}

		//	Add the remaining items

		ItemList.ResetCursor();
		while (ItemList.MoveCursorForward())
			{
			const CItem &Item(ItemList.GetItemAtCursor());

			if (!Item.IsInstalled())
				{
				CString sEnhancement = Item.GetEnhancedDesc(pShip);
				CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly);
				CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement));
				CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - Item.GetType()->GetLevel(), sLine);

				Stats.Insert(sLine, NULL_STR, CONSTLIT("Final items"), sSort);
				}
			}
		}
	}