Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
    }
  }
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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();
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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);
      }
    }
  }
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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();
}
Exemplo n.º 14
0
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);
  }
  
}
Exemplo n.º 15
0
//	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;
}
Exemplo n.º 16
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;
}