const IDataChannel* CSQLiteLapDB::GetDataChannel(int iLapId, DATA_CHANNEL eChannel) const { AutoLeaveCS _cs(&m_cs); if(eChannel == DATA_CHANNEL_VELOCITY) { // since velocity is stored as part of the points table, it is a bit different than the normal data channels CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select points.time, points.velocity from points where lapid=%d", iLapId); if(sfQuery.Init(szQuery)) { IDataChannel* pChannel = AllocateDataChannel(); pChannel->Init(iLapId,DATA_CHANNEL_VELOCITY); while(sfQuery.Next()) { int iTime = 0; double dVel = 0; if(sfQuery.GetCol(0,&iTime) && sfQuery.GetCol(1,&dVel)) { pChannel->AddPoint(iTime, dVel); } } pChannel->Lock(); return pChannel; } } else { CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select channels._id, channels.lapid, channels.channeltype from channels where channels.lapid = %d and channels.channeltype=%d", iLapId, eChannel); if(sfQuery.Init(szQuery)) { if(sfQuery.Next()) { IDataChannel* pChannel = AllocateDataChannel(); pChannel->Load(m_sfDB,sfQuery,true); // warning: massive memory leaks here return pChannel; } } } return NULL; }
void CSQLiteLapDB::AddComment(int iLapId, LPCTSTR strComment) { CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert or replace into extras (comment,lapid) values (?,?)")) { sfQuery.BindValue(strComment); sfQuery.BindValue(iLapId); if(!sfQuery.Next() && !sfQuery.IsDone()) { DASSERT(FALSE); } } }
bool CSQLiteLapDB::RenameLaps(TCHAR szName[MAX_PATH], int m_iRaceId1) { CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"update races set name = ? where _id = ?")) { sfQuery.BindValue(szName); sfQuery.BindValue(m_iRaceId1); if(sfQuery.Next() || sfQuery.IsDone()) { // data update complete, hooray! return true; } } return false; }
bool CSQLiteLapDB::MergeLaps(int m_iRaceId1, int m_iRaceId2) { CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"Update laps set raceid = ? where raceid = ?")) { sfQuery.BindValue(m_iRaceId1); sfQuery.BindValue(m_iRaceId2); if(sfQuery.Next() || sfQuery.IsDone()) { // data update complete, hooray! return true; } } return false; }
void CSQLiteLapDB::AddDataChannel(const IDataChannel* pChannel) { AutoLeaveCS _cs(&m_cs); m_sfDB.StartTransaction(); bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into channels (lapid,channeltype) values (?,?)")) { sfQuery.BindValue(pChannel->GetLapId()); sfQuery.BindValue((int)pChannel->GetChannelType()); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! long long lastInsert = m_sfDB.GetLastInsertId(); vector<DataPoint> lstPoints = pChannel->GetData(); for(int x = 0;x < lstPoints.size(); x++) { const DataPoint& pt = lstPoints[x]; sfQuery.DeInit(); if(sfQuery.Init(L"insert into data (time,value,channelid) values (?,?,?)")) { sfQuery.BindValue(pt.iTimeMs); sfQuery.BindValue(pt.flValue); sfQuery.BindValue(lastInsert); if(!sfQuery.Next() && !sfQuery.IsDone()) { fSuccess = false; break; } } } } else { fSuccess = false; } } if(fSuccess) { m_pUI->NotifyChange(NOTIFY_NEWDATA,(LPARAM)this); } m_sfDB.StopTransaction(); }
const ILap* CSQLiteLapDB::GetLap(int iLapId) { CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"Select laps._id,laps.laptime, laps.unixtime from laps where laps._id = %d", iLapId); if(sfQuery.Init(szQuery)) { if(sfQuery.Next()) { CSQLiteLap* pLap = (CSQLiteLap*)AllocateLap(false); pLap->Load(m_sfDB,m_rgSF,sfQuery); return pLap; } } return NULL; }
void CSQLiteLapDB::GetComments(int iLapId, vector<wstring>& lstComments) const { CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select extras.comment from extras where extras.lapid = %d", iLapId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { TCHAR szComment[500]; if(sfQuery.GetCol(0,szComment, NUMCHARS(szComment))) { lstComments.push_back(szComment); } } } }
bool CSQLiteLapDB::InitRaceSession(int* piRaceId, LPCTSTR lpszRaceName) { bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into races (name,date) values (?,?)")) { sfQuery.BindValue(lpszRaceName); sfQuery.BindValue(GetSecondsSince1970()); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! long long lastInsert = m_sfDB.GetLastInsertId(); *piRaceId = lastInsert; return true; } } return false; }
int CSQLiteLapDB::GetLapCount(int iRaceId) const { AutoLeaveCS _cs(&m_cs); CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select count(laps._id) from races,laps where races._id = %d and laps.raceid=races._id group by races._id", iRaceId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { int cLaps = 0; if(sfQuery.GetCol(0,&cLaps)) { return cLaps; } } } return 0; }
set<DATA_CHANNEL> CSQLiteLapDB::GetAvailableChannels(int iLapId) const { set<DATA_CHANNEL> setRet; CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select channels.channeltype from channels where channels.lapid = %d", iLapId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { DATA_CHANNEL eType; if(sfQuery.GetCol(0,(int*)&eType)) { setRet.insert(eType); } } } return setRet; }
vector<const ILap*> CSQLiteLapDB::GetLaps(int iRaceId) { vector<const ILap*> lstLaps; // gotta load all the laps that are in the DB, but we don't want to fully load them, just their laptimes and other directly lap-related data CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"Select laps._id,laps.laptime, laps.unixtime,extras.comment from laps left join extras on extras.lapid = laps._id where laps.raceid=%d", iRaceId); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { CSQLiteLap* pLap = (CSQLiteLap*)AllocateLap(false); pLap->Load(m_sfDB,m_rgSF,sfQuery); if(pLap->IsValid()) { lstLaps.push_back(pLap); } } } return lstLaps; }
vector<RACEDATA> CSQLiteLapDB::GetRaces() { AutoLeaveCS _cs(&m_cs); vector<RACEDATA> lstRaces; CSfArtSQLiteQuery sfQuery(m_sfDB); TCHAR szQuery[MAX_PATH]; _snwprintf(szQuery, NUMCHARS(szQuery), L"select races.name,races.date,count(laps._id),races._id from races,laps where laps.raceid=races._id group by races._id"); if(sfQuery.Init(szQuery)) { while(sfQuery.Next()) { RACEDATA raceData; TCHAR szData[1000]; if(sfQuery.GetCol(0,szData,NUMCHARS(szData))) { raceData.strName = szData; int iRaceDate = 0; if(sfQuery.GetCol(1,&iRaceDate)) { raceData.unixtime = iRaceDate; } int cLaps = 0; if(sfQuery.GetCol(2,&cLaps)) { raceData.laps = cLaps; } int iRaceId = 0; if(sfQuery.GetCol(3,&iRaceId)) { raceData.raceId = iRaceId; } lstRaces.push_back(raceData); } } } return lstRaces; }
void CSQLiteLapDB::AddLap(const ILap* pLap, int _iRaceId) { AutoLeaveCS _cs(&m_cs); CARNUMBERCOMBO sfCarNumber = pLap->GetCarNumbers(); int iSaveRaceId = -1; if(mapCarNumberRaceIds.find(sfCarNumber) == mapCarNumberRaceIds.end()) { // we've never seen this car number combo before. Time for a new race. TCHAR szRaceName[200]; if(sfCarNumber.IsOldVersion()) { _snwprintf(szRaceName,NUMCHARS(szRaceName),L"Received from old wifilappers"); } else { _snwprintf(szRaceName,NUMCHARS(szRaceName),L"Received laps (car %d) - (%d)", sfCarNumber.iCarNumber, sfCarNumber.iSecondaryCarNumber); } int iNewRaceId = -1; if(InitRaceSession(&iNewRaceId,szRaceName)) { mapCarNumberRaceIds[sfCarNumber] = iNewRaceId; iSaveRaceId = iNewRaceId; } else { return; } } else { iSaveRaceId = mapCarNumberRaceIds[sfCarNumber]; } m_setReceivingIds.insert(iSaveRaceId); // this race ID received a lap m_iLastRaceId = iSaveRaceId; m_sfDB.StartTransaction(); bool fSuccess = true; CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(L"insert into laps (_id,laptime,unixtime,transmitted,raceid) values (?,?,?,?,?)")) { sfQuery.BindValue(pLap->GetLapId()); sfQuery.BindValue(pLap->GetTime()); sfQuery.BindValue(pLap->GetStartTime()); sfQuery.BindValue(0); sfQuery.BindValue(iSaveRaceId); if(sfQuery.Next() || sfQuery.IsDone()) { // inserted new data, hooray! vector<TimePoint2D> lstPoints = pLap->GetPoints(); for(int x = 0;x < lstPoints.size(); x++) { const TimePoint2D& pt = lstPoints[x]; sfQuery.DeInit(); if(sfQuery.Init(L"insert into points (x,y,time,velocity,lapid) values (?,?,?,?,?)")) { sfQuery.BindValue(pt.flX); sfQuery.BindValue(pt.flY); sfQuery.BindValue(pt.iTime); sfQuery.BindValue(pt.flVelocity); sfQuery.BindValue(pLap->GetLapId()); if(!sfQuery.Next() && !sfQuery.IsDone()) { fSuccess = false; break; } } } } else { fSuccess = false; } } if(fSuccess) { mapLastRaceTimes[iSaveRaceId] = timeGetTime(); m_pUI->NotifyChange(NOTIFY_NEWLAP,(LPARAM)this); } m_sfDB.StopTransaction(); }
bool CSQLiteLapDB::Init(LPCTSTR lpszPath) { if(!DoesFileExist(lpszPath)) { vector<wstring> lstSQL; HRESULT hr = m_sfDB.Open(lpszPath, lstSQL); if(SUCCEEDED(hr)) { for(int x = 0;x < 6; x++) { hr = E_FAIL; CSfArtSQLiteQuery sfInsert(m_sfDB); if(sfInsert.Init(rgSchemaList[iMaxSupportedVersion][x])) { if(sfInsert.Next()) { hr = S_OK; } if(sfInsert.IsDone()) { hr = S_OK; } } if(FAILED(hr)) break; } } return SUCCEEDED(hr); } else { int iFindFailures = 0; int ixFoundVersion = -1; vector<wstring> lstSQL; HRESULT hr = m_sfDB.Open(lpszPath, lstSQL); if(SUCCEEDED(hr)) { // find a schema version that matches for(int ixVersion = iMaxSupportedVersion; ixVersion >= iMinSupportedVersion; ixVersion--) { bool fFoundAll = true; for(int x = 0; x < 6 && fFoundAll; x++) { // we want to find rgSchemaList[ixVersion][x] in the lstSQL that we got from the DB. if(!rgSchemaList[ixVersion][x]) continue; // don't need to find this one bool fFound = false; for(int y = 0; y < lstSQL.size(); y++) { if(wcsstr(lstSQL[y].c_str(),L"android_metadata") != NULL) continue; // don't care about this table if(nospacecompare(lstSQL[y].c_str(),rgSchemaList[ixVersion][x]) == 0) { fFound = true; break; } } if(!fFound) { iFindFailures++; } fFoundAll = fFoundAll && fFound; } if(fFoundAll) { ixFoundVersion = ixVersion; break; } } if(ixFoundVersion < 0) { DASSERT(FALSE); // we didn't find or create all our required tables... hr = E_FAIL; } if(SUCCEEDED(hr) && ixFoundVersion < 23) { // upgrade! CSfArtSQLiteQuery sfQuery(m_sfDB); if(sfQuery.Init(CREATE_EXTRA_SQL)) { while(sfQuery.Next()) { } DASSERT(sfQuery.IsDone()); } } /*if(ixFoundVersion < ...) future upgrades... { }*/ } return SUCCEEDED(hr); } }
// Function updates the HotLap screen for HPDE's and track days, based upon user choices for Race Sessions selected DWORD* CDlgTimingScoring::TimingScoringProc(LPVOID pv, HWND hWnd) { LPCTSTR lpszPath = (LPCTSTR)pv; CSfArtSQLiteDB sfDB; vector<wstring> lstTables; // HL_hWnd = GetDlgItem(hWnd, IDC_TIMINGSCORING); if(SUCCEEDED(sfDB.Open(lpszPath, lstTables, true))) { // Race ID's are stored in the sfResult.m_RaceId structure int z = 0; int z_RaceId[50] = {-1}; while (m_sfResult->m_RaceId[z] >= 0 && z < 50) { z_RaceId[z] = m_sfResult->m_RaceId[z]; z++; } vector<wstring> lstPos; vector<wstring> lstRaceName; vector<wstring> lstComment; vector<wstring> lstLapTimes; CSfArtSQLiteQuery sfQuery(sfDB); TCHAR szTmp[1080] = {NULL}; // Now cycle through all selected RaceId's and get their laptimes and sort them TCHAR szTemp[1080] = L"select races.name,laps.laptime,extras.comment from laps,races left join extras on extras.lapid = laps._id where laps.raceid=races._id and ("; for (int y = 0; y < z; y++) { int s_RaceId = z_RaceId[y]; if (s_RaceId != 0) { _snwprintf(szTemp, NUMCHARS(szTemp), L"%sraces._id = %i or ", szTemp, s_RaceId); } } swprintf(szTmp, wcslen(szTemp) - 3, L"%s", szTemp); _snwprintf(szTemp, NUMCHARS(szTemp), L"%s) order by laptime asc limit 40", szTmp); if(sfQuery.Init(szTemp)) { SYSTEMTIME st; GetSystemTime(&st); int z = 1; TCHAR szPos[MAX_PATH] = {NULL}; TCHAR szRaceName[300] = {NULL}; TCHAR szComment[300] = {NULL}; TCHAR szLap[300] = {NULL}; // Load up all of the HL vectors with data from the database while(sfQuery.Next()) { float flLapTime = 0; sfQuery.GetCol(0,szRaceName,NUMCHARS(szRaceName)); sfQuery.GetCol(1,&flLapTime); sfQuery.GetCol(2,szComment,NUMCHARS(szComment)); ::FormatTimeMinutesSecondsMs(flLapTime,szLap,NUMCHARS(szLap)); _snwprintf(szPos,NUMCHARS(szPos),L"%i",z); lstPos.push_back(szPos); lstRaceName.push_back(szRaceName); lstComment.push_back(szComment); lstLapTimes.push_back(szLap); z++; } // HWND HL_hWnd = GetDlgItem(hWnd, IDC_TIMINGSCORING); ListView_DeleteAllItems(HL_hWnd); // Clear the list before displaying the update ClearHotLaps(); // Clear the Top 40 Hot Laps list before updating TCHAR szText[MAX_PATH] = {NULL}; // set up list view items int nItem; // LVITEM p_HLlvi; LPWSTR result; for (nItem = 0; nItem < z - 1; ++nItem) { p_HLlvi.mask = LVIF_TEXT | LVIF_PARAM; p_HLlvi.iItem = nItem; p_HLlvi.iSubItem = 0; p_HLlvi.lParam = nItem; std::wstring strPos(lstPos[nItem]); result = (LPWSTR)strPos.c_str(); p_HLlvi.pszText = result; p_HLlvi.cchTextMax = wcslen(result); ListView_InsertItem(HL_hWnd, &p_HLlvi); // set up subitems p_HLlvi.mask = LVIF_TEXT; p_HLlvi.iItem = nItem; p_HLlvi.iSubItem = 1; std::wstring strRace(lstRaceName[nItem]); result = (LPWSTR)strRace.c_str(); //From TCHAR to DWORD. // DWORD dwSomeNum; // dwSomeNum = wcstod(result, _T('\0')); // p_HLlvi.lParam = (LPARAM) dwSomeNum; // Try this for LPARAM p_HLlvi.lParam = nItem; p_HLlvi.pszText = result; p_HLlvi.cchTextMax = wcslen(result); ListView_SetItem(HL_hWnd, &p_HLlvi); p_HLlvi.iSubItem = 2; std::wstring strComment(lstComment[nItem]); result = (LPWSTR)strComment.c_str(); //From TCHAR to DWORD. // dwSomeNum = wcstod(result, _T('\0')); // p_HLlvi.lParam = (LPARAM) dwSomeNum; // Try this for LPARAM p_HLlvi.lParam = nItem; p_HLlvi.pszText = result; p_HLlvi.cchTextMax = wcslen(result); ListView_SetItem(HL_hWnd, &p_HLlvi); p_HLlvi.iSubItem = 3; p_HLlvi.pszText = (LPWSTR)&lstLapTimes[nItem]; std::wstring strLapTimes(lstLapTimes[nItem]); result = (LPWSTR)strLapTimes.c_str(); //From TCHAR to DWORD. // dwSomeNum = wcstod(result, _T('\0')); // p_HLlvi.lParam = (LPARAM) dwSomeNum; // Try this for LPARAM p_HLlvi.lParam = nItem; p_HLlvi.pszText = result; p_HLlvi.cchTextMax = wcslen(result); ListView_SetItem(HL_hWnd, &p_HLlvi); } // Now load the RACERESULTS vectors with the Top 40 Hot Laps for saving to a text file for (int y = 0; y < z -1; y++) { std::wstring strPos(lstPos[y]); result = (LPWSTR)strPos.c_str(); _snwprintf(m_ScoringData[y].lstPos, NUMCHARS(m_ScoringData[y].lstPos), result); std::wstring strRace(lstRaceName[y]); result = (LPWSTR)strRace.c_str(); _snwprintf(m_ScoringData[y].lstRaceName, NUMCHARS(m_ScoringData[y].lstRaceName), result); std::wstring strComment(lstComment[y]); result = (LPWSTR)strComment.c_str(); _snwprintf(m_ScoringData[y].lstComment, NUMCHARS(m_ScoringData[y].lstComment), result); std::wstring strLapTimes(lstLapTimes[y]); result = (LPWSTR)strLapTimes.c_str(); _snwprintf(m_ScoringData[y].lstLapTimes, NUMCHARS(m_ScoringData[y].lstLapTimes), result); } } lstPos.clear(); lstRaceName.clear(); lstComment.clear(); lstLapTimes.clear(); sfDB.Close(); } return 0; }
// Function calculates the current laps and elapsed time since the race started DWORD* CDlgTimingScoring::CRaceScoring(LPVOID pv, HWND hWnd, int tmStartRace, int tmEndRace) { LPCTSTR lpszPath = (LPCTSTR)pv; CSfArtSQLiteDB sfDB; vector<wstring> lstTables; // HWND DlgScoring_hWnd = GetDlgItem(hWnd, IDC_RACESCORING); // TS_hWnd = GetDlgItem(hWnd, IDC_RACESCORING); if(SUCCEEDED(sfDB.Open(lpszPath, lstTables, true))) { // Race ID's are stored in the sfResult.m_RaceId structure int z = 0; while (m_sfResult->m_RaceId[z] >= 0 && z < 50) { m_ScoringData[z].db_iRaceId = m_sfResult->m_RaceId[z]; z++; } // First query for the total number of laps for each car TCHAR szTmStartRace[MAX_PATH] = {NULL}; TCHAR szTmEndRace[MAX_PATH] = {NULL}; // First let's make the strings for Start and End times long long iTmStartRace = 0; long long iTmEndRace = 0; iTmStartRace = tmStartRace; swprintf(szTmStartRace, NUMCHARS(szTmEndRace), L"%d", iTmStartRace); iTmEndRace = tmEndRace; if (iTmEndRace <= 0) { swprintf(szTmEndRace, NUMCHARS(szTmEndRace), L"5555555555"); } else { swprintf(szTmEndRace, NUMCHARS(szTmEndRace), L"%d", iTmEndRace); } // Now cycle through all selected RaceId's and get the number of laps completed CSfArtSQLiteQuery sfQuery(sfDB); TCHAR szTmp[2080] = {NULL}; TCHAR szTemp[1080] = L"select count(laps._id) from laps,races where laps.raceid=races._id and races._id = "; //? and laps.unixtime > ? and laps.unixtime < ?"; for (int y = 0; y < z; y++) { _snwprintf(szTmp, NUMCHARS(szTmp), L"%s%i and laps.unixtime > %s and laps.unixtime < %s", szTemp, m_ScoringData[y].db_iRaceId, szTmStartRace, szTmEndRace); if(sfQuery.Init(szTmp)) { while(sfQuery.Next()) { // sfQuery.BindValue(m_ScoringData[y].db_iRaceId); // sfQuery.BindValue((int)iTmStartRace); // sfQuery.BindValue((int)iTmEndRace); int cLaps = 0; if(sfQuery.GetCol(0,&cLaps)) { m_ScoringData[y].db_iTotLaps = cLaps; // Store the lap count value in the data structure } } } } // Now let's get their lap time information, so that we can figure out between-lap time differences // Right now we are just getting the time difference between EndRace time and the last lap time // First, cycle through all selected RaceId's and get all of their laptimes and sort them by race name and then by time collected in the given timespan _snwprintf(szTmp, NUMCHARS(szTmp), L""); _snwprintf(szTemp, NUMCHARS(szTemp), L"select races.name,laps.unixtime,laps._id from laps,races where laps.raceid=races._id and ("); for (int y = 0; y < z; y++) { int s_RaceId = m_ScoringData[y].db_iRaceId; if (s_RaceId != 0) { _snwprintf(szTemp, NUMCHARS(szTemp), L"%sraces._id = %i or ", szTemp, s_RaceId); } } swprintf(szTmp, wcslen(szTemp) - 3, L"%s", szTemp); _snwprintf(szTemp, NUMCHARS(szTemp), L"%s) and laps.unixtime > %s and laps.unixtime < %s order by name and unixtime", szTmp, szTmStartRace, szTmEndRace); int rec = 0, recFlag = 0; if(sfQuery.Init(szTemp)) { int db_iUnixFirstTimeStart = -1; int db_iUnixLastTimeStart = -1; TCHAR szLapsIdStart[MAX_PATH] = {NULL}; TCHAR szRaceNameStart[300] = {NULL}; long long flStartLapTime = -1; long long flFinishLapTime = -1; TCHAR szPos[MAX_PATH] = {NULL}; TCHAR szRaceName[300] = {NULL}; TCHAR szLap[300] = {NULL}; long long flLapTime = 0, flLapTemp = 0; while(sfQuery.Next()) { if (sfQuery.GetCol(0,szRaceName,NUMCHARS(szRaceName))) { if (recFlag == 0) swprintf(szRaceNameStart, NUMCHARS(szRaceNameStart), szRaceName); } if (sfQuery.GetCol(1,&flLapTemp)) { int flTemp = _wtoi(szTmStartRace); flLapTime = flLapTemp - (long long)flTemp; if (recFlag == 0) { // Initialize times for first data point flStartLapTime = flLapTime; flFinishLapTime = flLapTime; recFlag = 1; } else if (flLapTemp > flFinishLapTime && wcscmp(szRaceNameStart, szRaceName) == 0) { flFinishLapTime = flLapTemp; } else { // We have gone past the last lap for this Race_Id // Store the results in the data structure and reset the indicies m_ScoringData[rec].db_iUnixFirstTime = (int)flStartLapTime; swprintf(m_ScoringData[rec].db_strRaceName, NUMCHARS(m_ScoringData[rec].db_strRaceName), szRaceNameStart); flFinishLapTime = iTmEndRace - flFinishLapTime; m_ScoringData[rec].db_iUnixLastTime = (int)flFinishLapTime; int iTotTime = m_ScoringData[rec].db_iUnixFirstTime + m_ScoringData[rec].db_iUnixLastTime; TCHAR szText[MAX_PATH] = {NULL}; ::FormatTimeMinutesSecondsMs((float)iTotTime,szText,NUMCHARS(szText)); if (iTmEndRace > 0) { _snwprintf(m_ScoringData[rec].db_szTotTime, NUMCHARS(m_ScoringData[rec].db_szTotTime), L"%i / %s", m_ScoringData[rec].db_iTotLaps, szText); } else { _snwprintf(m_ScoringData[rec].db_szTotTime, NUMCHARS(m_ScoringData[rec].db_szTotTime), L"%i / TBD", m_ScoringData[rec].db_iTotLaps); } swprintf(szRaceNameStart, NUMCHARS(szRaceNameStart), szRaceName); flStartLapTime = flLapTime; flFinishLapTime = flLapTime; rec++; // Go to the next summary record and continue } } } // We have gone to the last lap data record // Put the final time difference into the data structure m_ScoringData[rec].db_iUnixFirstTime = (int)flStartLapTime; swprintf(m_ScoringData[rec].db_strRaceName, NUMCHARS(m_ScoringData[rec].db_strRaceName), szRaceNameStart); flFinishLapTime = iTmEndRace - flFinishLapTime; m_ScoringData[rec].db_iUnixLastTime = (int)flFinishLapTime; int iTotTime = m_ScoringData[rec].db_iUnixFirstTime + m_ScoringData[rec].db_iUnixLastTime; TCHAR szText[MAX_PATH] = {NULL}; ::FormatTimeMinutesSecondsMs((float)iTotTime,szText,NUMCHARS(szText)); if (iTmEndRace > 0) { _snwprintf(m_ScoringData[rec].db_szTotTime, NUMCHARS(m_ScoringData[rec].db_szTotTime), L"%i / %s", m_ScoringData[rec].db_iTotLaps, szText); } else { _snwprintf(m_ScoringData[rec].db_szTotTime, NUMCHARS(m_ScoringData[rec].db_szTotTime), L"%i / TBD", m_ScoringData[rec].db_iTotLaps); } rec++; // Keep the counter correct } sfDB.Close(); // Close the file // set up List view items ListView_DeleteAllItems(TS_hWnd); // Clear the list before displaying the update TCHAR szText[MAX_PATH] = {NULL}; int nItem; // LVITEM lvi; LPWSTR result; for (nItem = 0; nItem < rec; ++nItem) { p_TSlvi.mask = LVIF_TEXT | LVIF_PARAM; p_TSlvi.iItem = nItem; p_TSlvi.iSubItem = 0; p_TSlvi.lParam = nItem; swprintf(szTemp, NUMCHARS(szTemp), L"%i", m_ScoringData[nItem].db_iRaceId); std::wstring strTemp(szTemp); result = (LPWSTR)strTemp.c_str(); p_TSlvi.pszText = result; p_TSlvi.cchTextMax = wcslen(result); ListView_InsertItem(TS_hWnd, &p_TSlvi); // set up subitems p_TSlvi.mask = LVIF_TEXT; p_TSlvi.iItem = nItem; p_TSlvi.iSubItem = 1; std::wstring strRace(m_ScoringData[nItem].db_strRaceName); result = (LPWSTR)strRace.c_str(); // p_TSlvi.lParam = (LPARAM) result; // Try this for LPARAM p_TSlvi.lParam = nItem; p_TSlvi.pszText = result; p_TSlvi.cchTextMax = wcslen(result); ListView_SetItem(TS_hWnd, &p_TSlvi); p_TSlvi.iSubItem = 2; std::wstring strTotTimes(m_ScoringData[nItem].db_szTotTime); result = (LPWSTR)strTotTimes.c_str(); // p_TSlvi.lParam = (LPARAM) result; // Try this for LPARAM p_TSlvi.lParam = nItem; p_TSlvi.pszText = result; p_TSlvi.cchTextMax = wcslen(result); ListView_SetItem(TS_hWnd, &p_TSlvi); } } return 0; }