Re #313 (Split Windows installer) Make SD work again with only 1 track for QuickRace and Practice ; still crashes for Network and Single event races

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@3397 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 38d5d9b41b2d778de5a17c64fb57544f36637a7d
Former-commit-id: 11f5ae49160ff40e5d836748f176f5bbff40a147
This commit is contained in:
pouillot 2011-02-26 13:41:59 +00:00
parent 7852a5c91e
commit 49c335d1dd
6 changed files with 191 additions and 32 deletions

View file

@ -222,6 +222,14 @@ ReRaceRestore(void* hparmResults)
void
ReStartNewRace(void * /* dummy */)
{
// Save the race settings to the race manager file is anything changed.
GfLogDebug("ReStartNewRace: _reName='%s', dirty=%d\n", ReInfo->_reName, PReRace->isDirty());
if (PReRace->isDirty())
{
ReGetRace()->store(); // Save data to params.
GfParmWriteFile(NULL, ReInfo->params, ReInfo->_reName); // Save params to disk.
}
// Initialize the result system (different way for the Career mode).
if (!strcmp(GfParmGetStr(ReInfo->params, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO),
RM_VAL_NO))
@ -451,10 +459,8 @@ initPits(void)
}
break;
case TR_PIT_ON_SEPARATE_PATH:
break;
case TR_PIT_NONE:
break;
}

View file

@ -46,11 +46,14 @@ class GfRace::Private
{
public:
Private() : pRaceMan(0), nMaxCompetitors(0), nFocusedItfIndex(-1),
Private() : bIsDirty(false), pRaceMan(0), nMaxCompetitors(0), nFocusedItfIndex(-1),
nEventInd(0), nSessionInd(0), hparmResults(0) {};
public:
// True if no change occurred since last reset().
bool bIsDirty;
// The "parent" race manager.
GfRaceManager* pRaceMan;
@ -474,6 +477,9 @@ void GfRace::load(GfRaceManager* pRaceMan, void* hparmResults)
GfParmGetStr(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
_pPrivate->nFocusedItfIndex =
(int)GfParmGetNum(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0);
// Now we are consistent with the race params (in memory).
_pPrivate->bIsDirty = false;
}
void GfRace::store()
@ -643,6 +649,14 @@ void GfRace::store()
_pPrivate->strFocusedModuleName.c_str());
GfParmSetNum(hparmRaceMan, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL,
(tdble)_pPrivate->nFocusedItfIndex);
// Now we are consistent with the race params (in memory).
_pPrivate->bIsDirty = false;
}
bool GfRace::isDirty() const
{
return _pPrivate->bIsDirty || (_pPrivate->pRaceMan && _pPrivate->pRaceMan->isDirty());
}
GfRaceManager* GfRace::getManager() const
@ -786,6 +800,9 @@ bool GfRace::appendCompetitor(GfDriver* pComp)
const std::pair<std::string, int> compKey(pComp->getModuleName(),
pComp->getInterfaceIndex());
_pPrivate->mapCompetitorsByKey[compKey] = pComp;
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
}
return bAppended;
@ -799,7 +816,12 @@ bool GfRace::removeCompetitor(GfDriver* pComp)
std::vector<GfDriver*>::iterator itVComp =
std::find(_pPrivate->vecCompetitors.begin(), _pPrivate->vecCompetitors.end(), pComp);
if (itVComp != _pPrivate->vecCompetitors.end())
{
_pPrivate->vecCompetitors.erase(itVComp);
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
}
else
bRemoved = false;
@ -808,7 +830,12 @@ bool GfRace::removeCompetitor(GfDriver* pComp)
Private::TMapCompetitorsByKey::iterator itMComp =
_pPrivate->mapCompetitorsByKey.find(compKey);
if (itMComp != _pPrivate->mapCompetitorsByKey.end())
{
_pPrivate->mapCompetitorsByKey.erase(itMComp);
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
}
else
bRemoved = false;
@ -842,6 +869,9 @@ bool GfRace::moveCompetitor(GfDriver* pComp, int nDeltaPlace)
// Insert it at his new place.
_pPrivate->vecCompetitors.insert(itComp, pComp);
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
return true;
}
@ -852,6 +882,9 @@ bool GfRace::removeAllCompetitors()
_pPrivate->vecCompetitors.clear();
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
return true;
}
@ -882,6 +915,9 @@ bool GfRace::shuffleCompetitors()
// Put the last competitor at the end of the new list.
_pPrivate->vecCompetitors.push_back(vecCompetitors[0]);
// Now we are no more consistent with the race params (in memory).
_pPrivate->bIsDirty = true;
return true;
}

View file

@ -53,6 +53,9 @@ public:
//! Store to the race manager params file.
void store();
//! Is the race data consistent with the params from which it was loaded ?
bool isDirty() const;
GfRaceManager* getManager() const;
enum EDisplayMode { eDisplayNormal, eDisplayResultsOnly,

View file

@ -133,7 +133,7 @@ GfRaceManagers::GfRaceManagers()
std::sort(_pPrivate->vecRaceMans.begin(), _pPrivate->vecRaceMans.end(), hasHigherPriority);
// And log what we've got now.
print();
print(/* bVerbose */false);
}
const std::vector<std::string>& GfRaceManagers::getTypes() const
@ -174,7 +174,7 @@ std::vector<GfRaceManager*> GfRaceManagers::getRaceManagersWithType(const std::s
return vecRaceMans;
}
void GfRaceManagers::print() const
void GfRaceManagers::print(bool bVerbose) const
{
GfLogTrace("Race managers : %d types, %d race managers\n",
_pPrivate->vecTypes.size(), _pPrivate->vecRaceMans.size());
@ -190,7 +190,8 @@ void GfRaceManagers::print() const
{
GfLogTrace(" %s : subtype='%s', name='%s', events=%d\n",
(*itRaceMan)->getId().c_str(), (*itRaceMan)->getSubType().c_str(),
(*itRaceMan)->getName().c_str(), (*itRaceMan)->getEventCount());
(*itRaceMan)->getName().c_str(),
bVerbose ? (*itRaceMan)->getEventCount() : -1);
}
}
}
@ -282,6 +283,19 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
GfParmReleaseHandle(_hparmHandle);
_hparmHandle = hparmHandle;
// Clear the event list
_vecEventTrackIds.clear();
// Clear the session name list
_vecSessionNames.clear();
// No more ready for serialization (in memory, to params) for the moment.
_bIsDirty = false;
}
// This methos is const because we want it to be called by const methods. No other way.
void GfRaceManager::load() const
{
// Determine the race manager file from which to load the events info.
// 1) Simple case : the race manager has no subfiles, use the normal file.
// 2) Career case : the events are defined in "sub-championships" files.
@ -290,6 +304,7 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
// the other "sub-championships", each defined in a career_<sub-champ>.xmls).
// This is not an issue as long as this class is not used in the race engine
// or the event management purpose (most of it is in racecareer.cpp for now).
void* hparmHandle = _hparmHandle;
const char* pszHasSubFiles =
GfParmGetStr(_hparmHandle, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO);
_bHasSubFiles = strcmp(pszHasSubFiles, RM_VAL_YES) ? false : true;
@ -317,29 +332,70 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
// Clear the event list
_vecEventTrackIds.clear();
// And reload it (warning: here, we only check the tracks existence, not their usability).
// And reload it
// (warning: here, we only check the tracks usability when the specified one was not found).
std::ostringstream ossSectionPath;
int nEventNum = 1;
const char* pszTrackId;
do
{
// Get event track name.
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventNum;
pszTrackId = GfParmGetStr(hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME, 0);
// GfLogDebug("GfRaceManager::reset(...): event[%d].track = '%s'\n",
// nEventNum-1, pszTrackId);
GfLogDebug("GfRaceManager::reset(...): event[%d].track = '%s'\n",
nEventNum-1, pszTrackId);
// If not end of event list :
if (pszTrackId)
{
if (GfTracks::self()->getTrack(pszTrackId))
_vecEventTrackIds.push_back(pszTrackId);
else
GfLogWarning("Skipping non-existing track '%s' (event #%d) for %s mode\n",
pszTrackId, nEventNum, _strName.c_str());
// If no such track, try and get the first usable one in the existing categories.
if (!GfTracks::self()->getTrack(pszTrackId))
{
// Get the track category.
const char* pszCatId =
GfParmGetStr(hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_CATEGORY, 0);
// Get the first usable track in the same category,
// or else in the next categories.
GfTrack* pTrack = GfTracks::self()->getFirstUsableTrack(pszCatId, pszTrackId, +1, true);
if (!pTrack)
pTrack = GfTracks::self()->getFirstUsableTrack(pszCatId, +1, true);
// If found, select this one for the the event.
if (pTrack)
{
GfLogWarning("Replacing non-existing track '%s' by first usable '%s' "
"(event #%d) for %s mode\n", pszTrackId,
pTrack->getId().c_str(), nEventNum, _strName.c_str());
pszTrackId = pTrack->getId().c_str();
// Now we are no more consistent with the race managers params (in memory).
_bIsDirty = true;
}
else
{
// Should never happen : no usable track.
GfLogError("Skipping non-existing track '%s' (event #%d) for %s mode"
" and no other usable track ; let's start praying ...\n",
pszTrackId, nEventNum, _strName.c_str());
break;
}
}
// We got it.
_vecEventTrackIds.push_back(pszTrackId);
// Next event.
nEventNum++;
}
}
while (pszTrackId);
// Clear the session name list
_vecSessionNames.clear();
// Session names.
std::ostringstream ossSecPath;
int nSessionInd = 1;
@ -349,14 +405,13 @@ void GfRaceManager::reset(void* hparmHandle, bool bClosePrevHdle)
ossSecPath << RM_SECT_RACES << '/' << nSessionInd;
const char* pszSessionName =
GfParmGetStr(hparmHandle, ossSecPath.str().c_str(), RM_ATTR_NAME, 0);
// GfLogDebug("GfRaceManager::reset(...): session '%s'\n", pszSessionName);
GfLogDebug("GfRaceManager::reset(...): session '%s'\n", pszSessionName);
if (pszSessionName && strlen(pszSessionName) > 0)
_vecSessionNames.push_back(pszSessionName);
// Next session.
nSessionInd++;
}
}
void GfRaceManager::store()
@ -377,8 +432,8 @@ void GfRaceManager::store()
std::ostringstream ossSectionPath;
for (unsigned nEventInd = 0; nEventInd < _vecEventTrackIds.size(); nEventInd++)
{
// GfLogDebug("GfRaceManager::store(%s): event[%u].track = '%s'\n",
// _strName.c_str(), nEventInd, _vecEventTrackIds[nEventInd].c_str());
GfLogDebug("GfRaceManager::store(%s): event[%u].track = '%s'\n",
_strName.c_str(), nEventInd, _vecEventTrackIds[nEventInd].c_str());
ossSectionPath.str("");
ossSectionPath << RM_SECT_TRACKS << '/' << nEventInd + 1;
GfParmSetStr(_hparmHandle, ossSectionPath.str().c_str(), RM_ATTR_NAME,
@ -388,6 +443,9 @@ void GfRaceManager::store()
pTrack->getCategoryId().c_str());
}
}
// Now we are consistent with the race managers params (in memory).
_bIsDirty = false;
}
GfRaceManager::~GfRaceManager()
@ -460,16 +518,25 @@ const std::vector<std::string>& GfRaceManager::getAcceptedCarCategoryIds() const
unsigned GfRaceManager::getEventCount() const
{
if (_vecEventTrackIds.empty())
load(); // Lazy loading.
return _vecEventTrackIds.size();
}
bool GfRaceManager::isMultiEvent() const
{
if (_vecEventTrackIds.empty())
load(); // Lazy loading.
return _vecEventTrackIds.size() > 1;
}
GfTrack* GfRaceManager::getEventTrack(unsigned nEventIndex)
{
if (_vecEventTrackIds.empty())
load(); // Lazy loading.
GfTrack* pTrack = 0;
if (!_vecEventTrackIds.empty())
@ -483,15 +550,14 @@ GfTrack* GfRaceManager::getEventTrack(unsigned nEventIndex)
GfTracks::self()->getTrack(_vecEventTrackIds[nEventIndex]);
}
// If the event track could not be found, take the first usable one.
if (!pTrack)
pTrack = GfTracks::self()->getFirstUsableTrack();
return pTrack;
}
void GfRaceManager::setEventTrack(unsigned nEventIndex, GfTrack* pTrack)
{
if (_vecEventTrackIds.empty())
load(); // Lazy loading.
if (!pTrack || _vecEventTrackIds.empty())
return;
@ -501,10 +567,18 @@ void GfRaceManager::setEventTrack(unsigned nEventIndex, GfTrack* pTrack)
nEventIndex = _vecEventTrackIds.size() - 1;
_vecEventTrackIds[nEventIndex] = pTrack->getId();
GfLogDebug("GfRaceManager::setEventTrack(evt #%u, track '%s')\n",
nEventIndex, pTrack->getId().c_str());
// Now we are no more consistent with the race managers params (in memory).
_bIsDirty = true;
}
GfTrack* GfRaceManager::getPreviousEventTrack(unsigned nEventIndex)
{
if (_vecEventTrackIds.empty())
load(); // Lazy loading.
GfTrack* pTrack = 0;
if (!_vecEventTrackIds.empty())
@ -524,16 +598,25 @@ GfTrack* GfRaceManager::getPreviousEventTrack(unsigned nEventIndex)
const std::vector<std::string>& GfRaceManager::getSessionNames() const
{
if (_vecSessionNames.empty())
load(); // Lazy loading.
return _vecSessionNames;
}
unsigned GfRaceManager::getSessionCount() const
{
if (_vecSessionNames.empty())
load(); // Lazy loading.
return _vecSessionNames.size();
}
const std::string& GfRaceManager::getSessionName(unsigned nIndex) const
{
if (_vecSessionNames.empty())
load(); // Lazy loading.
if (_vecSessionNames.empty())
return strEmpty;
@ -595,3 +678,7 @@ bool GfRaceManager::hasResultsFiles() const
return bAnswer;
}
bool GfRaceManager::isDirty() const
{
return _bIsDirty;
}

View file

@ -39,7 +39,7 @@ public:
GfRaceManager(const std::string& strId, void* hparmHandle);
void reset(void* hparmHandle, bool bClosePrevHdle = false);
~GfRaceManager();
const std::string& getId() const;
@ -71,11 +71,19 @@ public:
bool hasSavedConfigsFiles() const;
const std::string& getResultsDir() const;
bool hasResultsFiles() const;
//! Save data to params (in-memory, no file written to disk).
void store();
//! Is the race manager data consistent with the params from which it was loaded ?
bool isDirty() const;
protected:
//! Load remaining info from params (called by accessors, lazy mode).
void load() const;
protected:
std::string _strId; // XML file name (ex: quickrace, singleevent-endurance, championship-sc)
void* _hparmHandle; // Params handle to the descriptor file.
@ -88,14 +96,16 @@ protected:
std::vector<std::string> _vecAcceptedDriverTypes;
std::vector<std::string> _vecAcceptedCarCategoryIds;
bool _bHasSubFiles; // True if multiple configuration files are used (ex: Career mode).
mutable bool _bHasSubFiles; // True if multiple configuration files are used (ex: Career mode).
// Saved configs and results files dirs.
mutable std::string _strSavedConfigsDir;
mutable std::string _strResultsDir;
std::vector<std::string> _vecEventTrackIds; // Id of the track for each scheduled event.
std::vector<std::string> _vecSessionNames; // Name and order of sessions for each event.
mutable std::vector<std::string> _vecEventTrackIds; // Id of the track for each scheduled event.
mutable std::vector<std::string> _vecSessionNames; // Name and order of sessions for each event.
mutable bool _bIsDirty; // True if no change occurred since last reset().
};
class TGFDATA_API GfRaceManagers
@ -112,7 +122,7 @@ public:
std::vector<GfRaceManager*> getRaceManagersWithType(const std::string& strType = "") const;
void print() const;
void print(bool bVerbose = false) const;
protected:

View file

@ -30,6 +30,10 @@
// Private data for GfTracks
class GfTracks::Private
{
public:
Private() : pTrackItf(0) {};
public:
// One GfTrack structure for each track (order = sorted directory one).
@ -301,7 +305,7 @@ GfTrack* GfTracks::getFirstUsableTrack(const std::string& strCatId,
&& std::find(_pPrivate->vecCatIds.begin(), _pPrivate->vecCatIds.end(), strCatId)
== _pPrivate->vecCatIds.end())
{
GfLogError("GfTracks::getFirstUsableTrack : No such category %s\n", strCatId.c_str());
GfLogError("GfTracks::getFirstUsableTrack(1) : No such category %s\n", strCatId.c_str());
return 0;
}
@ -371,8 +375,14 @@ GfTrack* GfTracks::getFirstUsableTrack(const std::string& strFromCatId,
std::find(_pPrivate->vecCatIds.begin(), _pPrivate->vecCatIds.end(), strFromCatId);
if (itFromCat == _pPrivate->vecCatIds.end())
{
GfLogError("GfTracks::getFirstUsableTrack : No such category %s\n", strFromCatId.c_str());
return 0;
if (!bSkipFrom) // No way if no such category and mustn't skip it.
{
GfLogError("GfTracks::getFirstUsableTrack(2) : No such category %s\n",
strFromCatId.c_str());
return 0;
}
else // Otherwise, let's start by the first available category.
itFromCat = _pPrivate->vecCatIds.begin();
}
int nCatInd = itFromCat - _pPrivate->vecCatIds.begin();
@ -565,8 +575,15 @@ void GfTrack::setMaxNumOfPitSlots(int nPitSlots)
bool GfTrack::load() const
{
// Load track data from the XML file.
// Check if the track loader is ready.
tTrackItf* pTrackItf = GfTracks::self()->getTrackInterface();
if (!pTrackItf)
{
GfLogError("Track loader not yet initialized ; failed to load any track\n");
return false;
}
// Load track data from the XML file.
tTrack* pTrack = pTrackItf->trkBuild(_strDescFile.c_str());
if (!pTrack)
{