Esempio n. 1
0
/* return state mode */
int
ReRaceStart(void)
{
	int i;
	int nCars;
	int maxCars;
	const char *raceName = ReInfo->_reRaceName;
	void *params = ReInfo->params;
	void *results = ReInfo->results;
	const int BUFSIZE = 1024;
	char path[BUFSIZE], path2[BUFSIZE];

	FREEZ(ReInfo->_reCarInfo);
	ReInfo->_reCarInfo = (tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo));

	/* Drivers starting order */
	GfParmListClean(params, RM_SECT_DRIVERS_RACING);
	if (ReInfo->s->_raceType == RM_TYPE_QUALIF) {
		i = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1);
		if (i == 1) {
			RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png");
			RmLoadingScreenSetText("Preparing Starting Grid...");
		} else {
			RmShutdownLoadingScreen();
		}

		snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i);
		snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, 1);
		GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, ""));
		GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0));
	} else {
		RmLoadingScreenStart(ReInfo->_reName, "data/img/splash-qrloading.png");
		RmLoadingScreenSetText("Preparing Starting Grid...");

		const char* gridType = GfParmGetStr(params, raceName, RM_ATTR_START_ORDER, RM_VAL_DRV_LIST_ORDER);
		if (!strcmp(gridType, RM_VAL_LAST_RACE_ORDER)) {
			/* Starting grid in the arrival of the previous race */
			nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
			maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100);
			nCars = MIN(nCars, maxCars);
			const char* prevRaceName = ReGetPrevRaceName();
			if (!prevRaceName) {
				return RM_QUIT;
			}
			for (i = 1; i < nCars + 1; i++) {
				snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, i);
				snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i);
				GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, ""));
				GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
			}
		} else if (!strcmp(gridType, RM_VAL_LAST_RACE_RORDER)) {
			/* Starting grid in the reversed arrival order of the previous race */
			nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
			maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100);
			nCars = MIN(nCars, maxCars);
			const char* prevRaceName = ReGetPrevRaceName();
			if (!prevRaceName) {
				return RM_QUIT;
			}
			for (i = 1; i < nCars + 1; i++) {
				snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, nCars - i + 1);
				snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i);
				GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(results, path, RE_ATTR_MODULE, ""));
				GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
			}
		} else {
			/* Starting grid in the drivers list order */
			nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
			maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100);
			nCars = MIN(nCars, maxCars);
			for (i = 1; i < nCars + 1; i++) {
				snprintf(path, BUFSIZE, "%s/%d", RM_SECT_DRIVERS, i);
				snprintf(path2, BUFSIZE, "%s/%d", RM_SECT_DRIVERS_RACING, i);
				GfParmSetStr(params, path2, RM_ATTR_MODULE, GfParmGetStr(params, path, RM_ATTR_MODULE, ""));
				GfParmSetNum(params, path2, RM_ATTR_IDX, NULL, GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0));
			}
		}
	}

	if (ReInfo->_displayMode != RM_DISP_MODE_CONSOLE) {
		if (!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_SPLASH_MENU, RM_VAL_NO), RM_VAL_YES)) {
			RmShutdownLoadingScreen();
			RmDisplayStartRace(ReInfo, StartRaceHookInit(), AbandonRaceHookInit());
			return RM_ASYNC | RM_NEXT_STEP;
		}
	}

	return reRaceRealStart();
}
Esempio n. 2
0
void
SimEngineConfig(tCar *car)
{
    void	*hdle = car->params;
    int		i;
    tdble	maxTq;
    tdble	rpmMaxTq = 0;
    char	idx[64];
    tEngineCurveElem *data;
    struct tEdesc {
	    tdble rpm;
	    tdble tq;
    } *edesc;


	car->engine.lastInterval = 0; // Initialize interval
    car->engine.revsLimiter = GfParmGetNum(hdle, SECT_ENGINE, PRM_REVSLIM, (char*)NULL, 800);
    car->carElt->_enginerpmRedLine = car->engine.revsLimiter;
    car->engine.revsMax     = GfParmGetNum(hdle, SECT_ENGINE, PRM_REVSMAX, (char*)NULL, 1000);
    car->carElt->_enginerpmMax = car->engine.revsMax;
    car->engine.tickover    = GfParmGetNum(hdle, SECT_ENGINE, PRM_TICKOVER, (char*)NULL, 150);
    car->engine.I           = GfParmGetNum(hdle, SECT_ENGINE, PRM_INERTIA, (char*)NULL, 0.2423f);
    car->engine.fuelcons    = GfParmGetNum(hdle, SECT_ENGINE, PRM_FUELCONS, (char*)NULL, 0.0622f);
    car->engine.brakeCoeff  = GfParmGetNum(hdle, SECT_ENGINE, PRM_ENGBRKCOEFF, (char*)NULL, 0.05f);
	car->engine.pressure = 0.0f;
	car->engine.exhaust_pressure = 0.0f;
	car->engine.exhaust_refract = 0.1f;
	car->engine.Tq_response = 0.0f;
    car->engine.I_joint = car->engine.I;
    sprintf(idx, "%s/%s", SECT_ENGINE, ARR_DATAPTS);
    car->engine.curve.nbPts = GfParmGetEltNb(hdle, idx);
    edesc = (struct tEdesc*)malloc((car->engine.curve.nbPts + 1) * sizeof(struct tEdesc));

    for (i = 0; i < car->engine.curve.nbPts; i++) {
		sprintf(idx, "%s/%s/%d", SECT_ENGINE, ARR_DATAPTS, i+1);
		edesc[i].rpm = GfParmGetNum(hdle, idx, PRM_RPM, (char*)NULL, car->engine.revsMax);
		edesc[i].tq  = GfParmGetNum(hdle, idx, PRM_TQ, (char*)NULL, 0);
    }
    edesc[i].rpm = edesc[i - 1].rpm;
    edesc[i].tq  = edesc[i].tq;

    maxTq = 0;
	car->engine.curve.maxPw = 0;
    car->engine.curve.data = (tEngineCurveElem *)malloc(car->engine.curve.nbPts * sizeof(tEngineCurveElem));

    for(i = 0; i < car->engine.curve.nbPts; i++) {
		data = &(car->engine.curve.data[i]);

		data->rads = edesc[i].rpm;
		if ((data->rads>=car->engine.tickover)
			&& (edesc[i].tq > maxTq)
			&& (data->rads < car->engine.revsLimiter)) {
			maxTq = edesc[i].tq;
			rpmMaxTq = data->rads;
		}
		if ((data->rads>=car->engine.tickover)
			&& (data->rads * edesc[i].tq > car->engine.curve.maxPw)
			&& (data->rads < car->engine.revsLimiter)) {
			car->engine.curve.TqAtMaxPw = edesc[i].tq;
			car->engine.curve.maxPw = data->rads * edesc[i].tq;
			car->engine.curve.rpmMaxPw = data->rads;
		}
		data->Tq = edesc[i].tq;
    }
    car->engine.curve.maxTq = maxTq;
    car->carElt->_engineMaxTq = maxTq;
    car->carElt->_enginerpmMaxTq = rpmMaxTq;
    car->carElt->_engineMaxPw = car->engine.curve.maxPw;
    car->carElt->_enginerpmMaxPw = car->engine.curve.rpmMaxPw;
	//printf ("%fNm@%frpm, %fKW@%f rpm\n",
	//  car->carElt->_engineMaxTq,
	//	car->carElt->_enginerpmMaxTq * (30.0 / M_PI),
	//	car->carElt->_engineMaxPw * 0.001,
	//	car->carElt->_enginerpmMaxPw * (30.0 / M_PI)
	//	);
	float X=urandom();
    car->engine.rads = X*car->engine.tickover+(1-X)*car->engine.revsMax;
    
    /*sanity check of rev limits*/
    if (car->engine.revsMax > car->engine.curve.data[car->engine.curve.nbPts-1].rads) {
        car->engine.revsMax = car->engine.curve.data[car->engine.curve.nbPts-1].rads;
        GfLogWarning("Revs maxi bigger than the maximum RPM in the curve data.\nIt is set to %g.\n",car->engine.revsMax);
    }
    if (car->engine.revsLimiter > car->engine.revsMax) {
        car->engine.revsLimiter = car->engine.revsMax;
        GfLogWarning("Revs limiter is bigger than revs maxi.\nIt is set to %g.\n",car->engine.revsLimiter);
    }

#if 0
	// TEST TORQUE FUNCTION
	for (float rads=1.0; rads<car->engine.revsMax; rads+=1.0) {
		float Tq = CalculateTorque(&(car->engine), rads);
		float Tq2 = CalculateTorque2(&(car->engine), rads);
		printf ("%f %f %f %d #TORQUE\n", 30.0*rads/M_PI, Tq, Tq2, engine->lastInterval);
	}
#endif
    free(edesc);
}
Esempio n. 3
0
//==========================================================================*
// Handle module entry for Speed Dreams Interface V1.00 (new fixed name scheme)
//--------------------------------------------------------------------------*
int moduleWelcomeV1_00
  (const tModWelcomeIn* welcomeIn, tModWelcomeOut* welcomeOut)
{
	PLogSimplix = GfLogger::instance("Simplix");
	LogSimplix.debug("\n#Interface Version: %d.%d\n",
		welcomeIn->itfVerMajor,welcomeIn->itfVerMinor);

	// Get filehandle for robot's xml-file
	void* RobotSettings = GetFileHandle(welcomeIn->name);
	// Let's look what we have to provide here
	if (RobotSettings)
	{
		LogSimplix.debug("#Robot name      : %s\n",RobName);
 		LogSimplix.debug("#Robot directory : %s\n",RobPathDirRel);
		LogSimplix.debug("#Robot XML-file  : %s\n",RobPathXMLRel);

		char Buffer[BUFSIZE];
		char *Section = Buffer;

		// To get the number of drivers defined in the
		// robot team definition file we have to count
		// the number of sections within Robots/index!
		snprintf(Buffer, BUFSIZE, "%s/%s", 
			ROB_SECT_ROBOTS, ROB_LIST_INDEX);
		NBBOTS = GfParmGetEltNb(RobotSettings,Buffer);
		LogSimplix.debug("#Nbr of drivers  : %d\n",NBBOTS);

		DriverNames = (char *) calloc(NBBOTS,DRIVERLEN);
		DriverDescs = (char *) calloc(NBBOTS,DESCRPLEN);

		// Setup a path to the first driver section 
		// assuming that it starts with the index 0
		snprintf(Buffer, BUFSIZE, "%s/%s/%d", 
			ROB_SECT_ROBOTS, ROB_LIST_INDEX, 0);

		// Try to get first driver from index 0
		const char *DriverName = GfParmGetStr( RobotSettings, 
			Section, (char *) ROB_ATTR_NAME, undefined);

		// Check wether index 0 is used as start index
		if (strncmp(DriverName,undefined,strlen(undefined)) != 0)
		{
			// Teams xml file uses index 0, 1, ..., N - 1
            IndexOffset = 0; 
		}
		else
		{
			// Teams xml file uses index 1, 2, ..., N
            IndexOffset = 1; 
		}

		// Loop over all possible drivers, clear all buffers, 
		// save defined driver names and desc.
	    int I = 0;
		int N = 0;
		int M = 0;
//		for (I = 0; I < MAXNBBOTS; I++)
		while (N < NBBOTS)
		{
			snprintf(Section, BUFSIZE, "%s/%s/%d", 
				ROB_SECT_ROBOTS, ROB_LIST_INDEX, I + IndexOffset );
			const char *DriverName = GfParmGetStr( RobotSettings, Section, 
				(char *) ROB_ATTR_NAME,undefined);

	        if (strncmp(DriverName,undefined,strlen(undefined)) != 0)
			{   // This driver is defined in robot's xml-file
				strncpy(&DriverNames[I*DRIVERLEN], DriverName, DRIVERLEN-1);
			    const char *DriverDesc = GfParmGetStr(RobotSettings, Section, 
					(char *) ROB_ATTR_DESC, defaultBotDesc[I]);
				strncpy(&DriverDescs[I*DESCRPLEN], DriverDesc, DESCRPLEN-1);
				LogSimplix.debug("#Driver %d: %s (%s)\n",I,DriverName,DriverDesc);
				N++;
			}
			else
			{
				// There is an index skipped in the robots team definition file
				// Therefore we have to get additional memory to store the data
				M++;
				DriverNames = (char *) realloc(DriverNames,(NBBOTS+M)*DRIVERLEN);
				memset(&DriverNames[I*DRIVERLEN], 0, DRIVERLEN);
				DriverDescs = (char *) realloc(DriverDescs,(NBBOTS+M)*DESCRPLEN);
				memset(&DriverDescs[I*DESCRPLEN], 0, DESCRPLEN);
				LogSimplix.debug("#Driver %d: %s (%s)\n",I,&DriverNames[I*DRIVERLEN],&DriverDescs[I*DESCRPLEN]);
			}

			I++;
		}
		GfParmReleaseHandle(RobotSettings);
	}
	else
	{
		// Handle error here
 	    LogSimplix.debug("#Robot XML-Path not found: (%s) or (%s) %s\n\n",
			GetLocalDir(),GetDataDir(),RobPathXMLRel);

		NBBOTS = 0;
		// But this is not considered a real failure of moduleWelcome !
	}

	// Handle additional settings for wellknown identities
	if (strncmp(RobName,"simplix_trb1",strlen("simplix_trb1")) == 0)
		SetUpSimplix_trb1();
	else if (strncmp(RobName,"simplix_sc",strlen("simplix_sc")) == 0)
		SetUpSimplix_sc();
	else if (strncmp(RobName,"simplix_36GP",strlen("simplix_36GP")) == 0)
		SetUpSimplix_36GP();
	else if (strncmp(RobName,"simplix_mpa1",strlen("simplix_mpa1")) == 0)
		SetUpSimplix_mpa1();
	else if (strncmp(RobName,"simplix_ls1",strlen("simplix_ls1")) == 0)
		SetUpSimplix_ls1();
	else if (strncmp(RobName,"simplix_ls2",strlen("simplix_ls2")) == 0)
		SetUpSimplix_ls2();
	else if (strncmp(RobName,"simplix_mp5",strlen("simplix_mp5")) == 0)
		SetUpSimplix_mp5();
	else if (strncmp(RobName,"simplix_lp1", strlen("simplix_lp1")) == 0)
		SetUpSimplix_lp1();
	else if (strncmp(RobName,"simplix_ref", strlen("simplix_ref")) == 0)
		SetUpSimplix_ref();
	else 
		SetUpSimplix();

	// Set max nb of interfaces to return.
	welcomeOut->maxNbItf = NBBOTS;

	return 0;
}
static void
reConfigRunState(void)
{
    int		i;
    int		curConf;
    char	*conf;
    int		numOpt;
    char	*opt;
    void	*params = ReInfo->params;

    curConf = (int)GfParmGetNum(params, RM_SECT_CONF, RM_ATTR_CUR_CONF, NULL, 1);
    if (curConf > GfParmGetEltNb(params, RM_SECT_CONF)) {
        GfOut("End of configuration\n");
        GfParmWriteFile(NULL, ReInfo->params, ReInfo->_reName);
        goto menuback;
    }

    sprintf(path, "%s/%d", RM_SECT_CONF, curConf);
    conf = GfParmGetStr(params, path, RM_ATTR_TYPE, 0);
    if (!conf) {
        GfOut("no %s here %s\n", RM_ATTR_TYPE, path);
        goto menuback;
    }

    GfOut("Configuration step %s\n", conf);
    if (!strcmp(conf, RM_VAL_TRACKSEL)) {
        /* Track Select Menu */
        ts.nextScreen = reConfigHookInit();
        if (curConf == 1) {
            ts.prevScreen = racemanMenuHdle;
        } else {
            ts.prevScreen = reConfigBackHookInit();
        }
        ts.param = ReInfo->params;
        ts.trackItf = ReInfo->_reTrackItf;
        RmTrackSelect(&ts);

    } else if (!strcmp(conf, RM_VAL_DRVSEL)) {
        /* Drivers select menu */
        ds.nextScreen = reConfigHookInit();
        if (curConf == 1) {
            ds.prevScreen = racemanMenuHdle;
        } else {
            ds.prevScreen = reConfigBackHookInit();
        }
        ds.param = ReInfo->params;
        RmDriversSelect(&ds);

    } else if (!strcmp(conf, RM_VAL_RACECONF)) {
        /* Race Options menu */
        rp.nextScreen = reConfigHookInit();
        if (curConf == 1) {
            rp.prevScreen = racemanMenuHdle;
        } else {
            rp.prevScreen = reConfigBackHookInit();
        }
        rp.param = ReInfo->params;
        rp.title = GfParmGetStr(params, path, RM_ATTR_RACE, "Race");
        /* Select options to configure */
        rp.confMask = 0;
        sprintf(path, "%s/%d/%s", RM_SECT_CONF, curConf, RM_SECT_OPTIONS);
        numOpt = GfParmGetEltNb(params, path);
        for (i = 1; i < numOpt + 1; i++) {
            sprintf(path, "%s/%d/%s/%d", RM_SECT_CONF, curConf, RM_SECT_OPTIONS, i);
            opt = GfParmGetStr(params, path, RM_ATTR_TYPE, "");
            if (!strcmp(opt, RM_VAL_CONFRACELEN)) {
                /* Configure race length */
                rp.confMask |= RM_CONF_RACE_LEN;
            } else {
                if (!strcmp(opt, RM_VAL_CONFDISPMODE)) {
                    /* Configure display mode */
                    rp.confMask |= RM_CONF_DISP_MODE;
                }
            }
        }
        RmRaceParamMenu(&rp);
    }

    curConf++;
    GfParmSetNum(params, RM_SECT_CONF, RM_ATTR_CUR_CONF, NULL, curConf);

    return;

    /* Back to the race menu */
menuback:
    GfuiScreenActivate(racemanMenuHdle);
    return;
}
Esempio n. 5
0
static void
NetworkRaceInfo()
{
	NetDriver driver;
	int i = 1;

	NetGetServer()->SetRaceXMLFile("config/raceman/networkrace.xml");

	//Look up race info
	tRmInfo* reInfo = LmRaceEngine().inData();
	reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_STD);

	int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS);

	if (nCars == 0)
	{
		// Add all local humans if there are no drivers already specified
		while (GetHumanDriver(driver,i++)) {
			driver.client = false;
			driver.active = true;
			NetGetServer()->UpdateDriver(driver);
			NetGetServer()->SetDriverName(driver.name);
			GfLogInfo("NetworkRaceInfo: Adding default driver %s\n",driver.name);

		}

		// ensure changes writen to 'networkrace.xml'
		NetGetServer()->GenerateDriversForXML();

		// add drivers so they show up in race config dialogue
		GfDrivers::self()->reload();
		LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true);
	} else {
		// Add the humans which are already in the race
		char	dname[256];

		for (i = 1; i < nCars+1; i++) {
			sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i);

			if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) {
				if (GetHumanDriver(driver,i) > -1) {
					driver.client = false;
					driver.active = true;
					NetGetServer()->UpdateDriver(driver);
					NetGetServer()->SetDriverName(driver.name);
					GfLogInfo("NetworkRaceInfo: Adding default driver %s\n",driver.name);
				}
			}
		}
	}

	// make sure nobody is 'ready to race'
	NetMutexData *pNData = NetGetNetwork()->LockNetworkData();
	for (unsigned int i=0; i < pNData->m_vecReadyStatus.size(); i++)
		pNData->m_vecReadyStatus[i] = false;
	NetGetNetwork()->UnlockNetworkData();
	bRobotsReady = false;

	// ensure the system knows about 'new' network drivers
	reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD);
	reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, "");
}
/** Initialize the cars for a race.
    The car are positionned on the starting grid.
    @return	0 Ok
		-1 Error
 */
int
ReInitCars(void)
{
	int nCars;
	int index;
	int i, j, k;
	char *cardllname;
	int robotIdx;
	tModInfo *curModInfo;
	tRobotItf *curRobot;
	void *handle;
	char *category;
	void *cathdle;
	void *carhdle;
	void *robhdle;
	tCarElt *elt;
	char *focused;
	char *str;
	int focusedIdx;
	void *params = ReInfo->params;

	/* Get the number of cars racing */
	nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS_RACING);
	GfOut("loading %d cars\n", nCars);

	FREEZ(ReInfo->carList);
	ReInfo->carList = (tCarElt*)calloc(nCars, sizeof(tCarElt));
	FREEZ(ReInfo->rules);
	ReInfo->rules = (tRmCarRules*)calloc(nCars, sizeof(tRmCarRules));
	focused = GfParmGetStr(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, "");
	focusedIdx = (int)GfParmGetNum(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0);
	index = 0;

	for (i = 1; i < nCars + 1; i++) {
		/* Get Shared library name */
		sprintf(path, "%s/%d", RM_SECT_DRIVERS_RACING, i);
		cardllname = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, "");
		robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0);
		sprintf(path, "%sdrivers/%s/%s.%s", GetLibDir (), cardllname, cardllname, DLLEXT);

		/* load the robot shared library */
		if (GfModLoad(CAR_IDENT, path, ReInfo->modList)) {
			GfTrace("Pb with loading %s driver\n", path);
			break;
		}

		/* search for corresponding index */
		for (j = 0; j < MAX_MOD_ITF; j++) {
			if ((*(ReInfo->modList))->modInfo[j].index == robotIdx) {
				/* good robot found */
				curModInfo = &((*(ReInfo->modList))->modInfo[j]);
				GfOut("Driver's name: %s\n", curModInfo->name);
				/* retrieve the robot interface (function pointers) */
				curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf));
				curModInfo->fctInit(robotIdx, (void*)(curRobot));
				sprintf(buf, "%sdrivers/%s/%s.xml", GetLocalDir(), cardllname, cardllname);
				robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
				if (!robhdle) {
					sprintf(buf, "drivers/%s/%s.xml", cardllname, cardllname);
					robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD);
				}
				if (robhdle != NULL) {
					elt = &(ReInfo->carList[index]);
					GF_TAILQ_INIT(&(elt->_penaltyList));

					elt->index = index;
					elt->robot = curRobot;
					elt->_paramsHandle = robhdle;
					elt->_driverIndex = robotIdx;
					strncpy(elt->_modName, cardllname, MAX_NAME_LEN - 1);
					elt->_modName[MAX_NAME_LEN - 1] = 0;

					sprintf(path, "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx);
					strncpy(elt->_name, GfParmGetStr(robhdle, path, ROB_ATTR_NAME, "<none>"), MAX_NAME_LEN - 1);
					elt->_name[MAX_NAME_LEN - 1] = 0;
					strncpy(elt->_teamname, GfParmGetStr(robhdle, path, ROB_ATTR_TEAM, "<none>"), MAX_NAME_LEN - 1);
					elt->_teamname[MAX_NAME_LEN - 1] = 0;
					
					strncpy(elt->_carName, GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""), MAX_NAME_LEN - 1);
					elt->_carName[MAX_NAME_LEN - 1] = 0;
					elt->_raceNumber = (int)GfParmGetNum(robhdle, path, ROB_ATTR_RACENUM, (char*)NULL, 0);
					if (strcmp(GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT), ROB_VAL_ROBOT)) {
						elt->_driverType = RM_DRV_HUMAN;
					} else {
						elt->_driverType = RM_DRV_ROBOT;
					}
					elt->_skillLevel = 0;
					str = GfParmGetStr(robhdle, path, ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO);
					for(k = 0; k < (int)(sizeof(level_str)/sizeof(char*)); k++) {
						if (strcmp(level_str[k], str) == 0) {
							elt->_skillLevel = k;
							break;
						}
					}
					elt->_startRank  = index;
					elt->_pos        = index+1;
					elt->_remainingLaps = ReInfo->s->_totLaps;

					/* handle contains the drivers modifications to the car */
					/* Read Car model specifications */
					sprintf(buf, "cars/%s/%s.xml", elt->_carName, elt->_carName);
					GfOut("Car Specification: %s\n", buf);
					carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
					category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL);
					sprintf(buf, "Loading Driver %-20s... Car: %s", curModInfo->name, elt->_carName);
					RmLoadingScreenSetText(buf);
					if (category != 0) {
						strncpy(elt->_category, category, MAX_NAME_LEN - 1);
						elt->_category[MAX_NAME_LEN - 1] = '\0';

						/* Read Car Category specifications */
						sprintf(buf, "categories/%s.xml", category);
						GfOut("Category Specification: %s\n", buf);
						cathdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
						if (GfParmCheckHandle(cathdle, carhdle)) {
							GfTrace("Car %s not in Category %s (driver %s) !!!\n", elt->_carName, category, elt->_name);
							break;
						}
						carhdle = GfParmMergeHandles(cathdle, carhdle,
										GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST);
										curRobot->rbNewTrack(robotIdx, ReInfo->track, carhdle, &handle, ReInfo->s);
						if (handle != NULL) {
							if (GfParmCheckHandle(carhdle, handle)) {
								GfTrace("Bad Car parameters for driver %s\n", elt->_name);
								break;
							}
							handle = GfParmMergeHandles(carhdle, handle,
										GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST);
						} else {
							handle = carhdle;
						}
						elt->_carHandle = handle;
						//GfParmWriteFile("toto.xml", handle, "toto");
					} else {
						elt->_category[0] = '\0';
						GfTrace("Bad Car category for driver %s\n", elt->_name);
						break;
					}
					index ++;
				} else {
					GfTrace("Pb No description file for driver %s\n", cardllname);
				}
				break;
			}
		}
    }

	nCars = index; /* real number of cars */
	if (nCars == 0) {
		GfTrace("No driver for that race...\n");
		return -1;
	} else {
		GfOut("%d drivers ready to race\n", nCars);
	}

	ReInfo->s->_ncars = nCars;
	FREEZ(ReInfo->s->cars);
	ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *));
	for (i = 0; i < nCars; i++) {
		ReInfo->s->cars[i] = &(ReInfo->carList[i]);
	}

	// TODO: reconsider splitting the call into one for cars, track and maybe other objects.
	// I stuff for now anything into one call because collision detection works with the same
	// library on all objects, so it is a bit dangerous to distribute the handling to various
	// locations (because the library maintains global state like a default collision handler etc.).
    ReInfo->_reSimItf.init(nCars, ReInfo->track);

    initStartingGrid();

    initPits();

    return 0;
}
Esempio n. 7
0
/*
 * Function
 *	GetTrackHeader
 *
 * Description
 *	Get the header of the track file
 *	in order to know the number of segments
 * Parameters
 *	
 *
 * Return
 *	
 *
 * Remarks
 *	
 */
static void
GetTrackHeader(void *TrackHandle) {
    // Read header
    theTrack->name = GfParmGetStr(TrackHandle, TRK_SECT_HDR, TRK_ATT_NAME, "no name");
    theTrack->descr = GfParmGetStr(TrackHandle, TRK_SECT_HDR, TRK_ATT_DESCR, "no description");
    theTrack->version = (int)GfParmGetNum(TrackHandle, TRK_SECT_HDR, TRK_ATT_VERSION, (char*)NULL, 0);
    theTrack->width = GfParmGetNum(TrackHandle, TRK_SECT_MAIN, TRK_ATT_WIDTH, (char*)NULL, 15.0);
    theTrack->authors = GfParmGetStr(TrackHandle, TRK_SECT_HDR, TRK_ATT_AUTHOR, "none");
    theTrack->category = GfParmGetStr(TrackHandle, TRK_SECT_HDR, TRK_ATT_CAT, "road");
    theTrack->subcategory = GfParmGetStr(TrackHandle, TRK_SECT_HDR, TRK_ATT_SUBCAT, "none");

    // Read Local Info section
    tTrackLocalInfo *local = &theTrack->local;
    local->station = GfParmGetStr(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_STATION, "LFPG");
    local->timezone = (int)GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_TIMEZONE, (char*)NULL, 0);
    local->anyrainlkhood = GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_ANYRAINLKHD, (char*)NULL, 0);
    local->littlerainlkhood = GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_LITTLERAINLKHD, (char*)NULL, 0);
    local->mediumrainlkhood = GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_MEDIUMRAINLKHD, (char*)NULL, 0);
    local->timeofday = GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_TIMEOFDAY, (char*)NULL, (tdble)(15 * 3600 + 0 * 60 + 0)); // 15:00:00
    local->sunascension = GfParmGetNum(TrackHandle, TRK_SECT_LOCAL, TRK_ATT_SUN_ASCENSION, (char*)NULL, 0.0f);

    // Read Graphic section
    tTrackGraphicInfo *graphic = &theTrack->graphic;
    graphic->model3d = GfParmGetStr(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_3DDESC, 0);
    graphic->background = GfParmGetStr(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_BKGRND, "background.png");
    graphic->bgtype = (int)GfParmGetNum(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_BGTYPE, (char*)NULL, 0.0);

    graphic->bgColor[0] = (float)GfParmGetNum(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_BGCLR_R, (char*)NULL, 0.0f);
    graphic->bgColor[1] = (float)GfParmGetNum(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_BGCLR_G, (char*)NULL, 0.0f);
    graphic->bgColor[2] = (float)GfParmGetNum(TrackHandle, TRK_SECT_GRAPH, TRK_ATT_BGCLR_B, (char*)NULL, 0.1f);

    // Environment map images
    char buf[256];
    sprintf(buf, "%s/%s", TRK_SECT_GRAPH, TRK_LST_ENV);
    graphic->envnb = GfParmGetEltNb(TrackHandle, buf);
    if (graphic->envnb < 1)
      graphic->envnb = 1;

    graphic->env = (const char**)calloc(graphic->envnb, sizeof(const char*));
    const char **env = graphic->env;
    for (int i = 1; i <= graphic->envnb; ++i) {
      sprintf(buf, "%s/%s/%d", TRK_SECT_GRAPH, TRK_LST_ENV, i);
      *env = GfParmGetStr(TrackHandle, buf, TRK_ATT_ENVNAME, "env.png");
      ++env;
    }

    // Track lights
    graphic->nb_lights = GfParmGetEltNb(TrackHandle, TRK_SECT_TRACKLIGHTS );
    GfLogDebug( "Number of lights: %d\n", graphic->nb_lights );
    if (graphic->nb_lights > 0 ) {
      graphic->lights = (tGraphicLightInfo*)malloc( sizeof( tGraphicLightInfo ) * graphic->nb_lights );
      for (int i = 0; i < graphic->nb_lights; ++i) {
        sprintf(buf, "%s/%d/%s", TRK_SECT_TRACKLIGHTS, i + 1, TRK_SECT_TOPLEFT);
        graphic->lights[ i ].topleft.x = GfParmGetNum(TrackHandle, buf, TRK_ATT_X, (char*)NULL, 0.0f);
        graphic->lights[ i ].topleft.y = GfParmGetNum(TrackHandle, buf, TRK_ATT_Y, (char*)NULL, 0.0f);
        graphic->lights[ i ].topleft.z = GfParmGetNum(TrackHandle, buf, TRK_ATT_Z, (char*)NULL, 0.0f);
        sprintf(buf, "%s/%d/%s", TRK_SECT_TRACKLIGHTS, i + 1, TRK_SECT_BOTTOMRIGHT);
        graphic->lights[ i ].bottomright.x = GfParmGetNum(TrackHandle, buf, TRK_ATT_X, (char*)NULL, 0.0f);
        graphic->lights[ i ].bottomright.y = GfParmGetNum(TrackHandle, buf, TRK_ATT_Y, (char*)NULL, 0.0f);
        graphic->lights[ i ].bottomright.z = GfParmGetNum(TrackHandle, buf, TRK_ATT_Z, (char*)NULL, 0.0f);
        sprintf(buf, "%s/%d", TRK_SECT_TRACKLIGHTS, i + 1);
        graphic->lights[ i ].onTexture = strdup(GfParmGetStr(TrackHandle, buf, TRK_ATT_TEXTURE_ON, ""));
        graphic->lights[ i ].offTexture = strdup(GfParmGetStr(TrackHandle, buf, TRK_ATT_TEXTURE_OFF, ""));
        graphic->lights[ i ].index = (int)GfParmGetNum(TrackHandle, buf, TRK_ATT_INDEX, (char*)NULL, 0.0f);
        graphic->lights[ i ].role = 0;
        if( strcmp( GfParmGetStr(TrackHandle, buf, TRK_ATT_ROLE, ""), "st_red" ) == 0 )
          graphic->lights[ i ].role = GR_TRACKLIGHT_START_RED;
        else if( strcmp( GfParmGetStr(TrackHandle, buf, TRK_ATT_ROLE, ""), "st_green" ) == 0 )
          graphic->lights[ i ].role = GR_TRACKLIGHT_START_GREEN;
        else if( strcmp( GfParmGetStr(TrackHandle, buf, TRK_ATT_ROLE, ""), "st_green_st" ) == 0 )
          graphic->lights[ i ].role = GR_TRACKLIGHT_START_GREENSTART;
        else if( strcmp( GfParmGetStr(TrackHandle, buf, TRK_ATT_ROLE, ""), "st_yellow" ) == 0 )
          graphic->lights[ i ].role = GR_TRACKLIGHT_START_YELLOW;
        graphic->lights[ i ].red = GfParmGetNum(TrackHandle, buf, TRK_ATT_RED, (char*)NULL, 1.0f);
        graphic->lights[ i ].green = GfParmGetNum(TrackHandle, buf, TRK_ATT_GREEN, (char*)NULL, 1.0f);
        graphic->lights[ i ].blue = GfParmGetNum(TrackHandle, buf, TRK_ATT_BLUE, (char*)NULL, 1.0f);
      }  // for i
    }  // if nb_lights

    theTrack->nseg = 0;

    // Search for track filename, without any path info, eg: 'foo.xml'
    const char *s = strrchr(theTrack->filename, '/');
    if (s == NULL) {
      s = theTrack->filename;
    } else {
      ++s;
    }

    // Internal name is track filename, without extension, eg: 'foo'
    theTrack->internalname = strdup(s);
    char *cs = strrchr(theTrack->internalname, '.');
    if (cs != NULL) {
      *cs = 0;
    }

    // Default turnmark is 1m*1m, right next to the track
    graphic->turnMarksInfo.height = GfParmGetNum(TrackHandle, TRK_SECT_TURNMARKS, TRK_ATT_HEIGHT, NULL, 1);
    graphic->turnMarksInfo.width  = GfParmGetNum(TrackHandle, TRK_SECT_TURNMARKS, TRK_ATT_WIDTH,  NULL, 1);
    graphic->turnMarksInfo.vSpace = GfParmGetNum(TrackHandle, TRK_SECT_TURNMARKS, TRK_ATT_VSPACE, NULL, 0);
    graphic->turnMarksInfo.hSpace = GfParmGetNum(TrackHandle, TRK_SECT_TURNMARKS, TRK_ATT_HSPACE, NULL, 0);
}  // GetTrackHeader
Esempio n. 8
0
/* return state mode */
int
ReRaceStart(void)
{
	char path[128];
	char path2[128];
	const char *sessionName = ReInfo->_reRaceName;
	void *params = ReInfo->params;
	void *results = ReInfo->results;
	int mode = 0;

	// Trace race session identification (more to say for the Carer mode).
	char pszSessionId[128];
	if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES))
	{
		const char* pszGroup = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, "<no group>");
		snprintf(pszSessionId, sizeof(pszSessionId), "%s %s %s", ReInfo->_reName, pszGroup, sessionName);
	}
	else
		snprintf(pszSessionId, sizeof(pszSessionId), "%s %s", ReInfo->_reName, sessionName);
	
	GfLogInfo("Starting %s session at %s\n", pszSessionId, ReInfo->track->name);

	// Reallocate and reset car info for the race.
	FREEZ(ReInfo->_reCarInfo);
	ReInfo->_reCarInfo =
		(tReCarInfo*)calloc(GfParmGetEltNb(params, RM_SECT_DRIVERS), sizeof(tReCarInfo));

	ReUI().onRaceInitializing();
	
	// Drivers starting order
	int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
	GfParmListClean(params, RM_SECT_DRIVERS_RACING);
	if (nCars == 0)
	{
		// This may happen, when playing with the text-only mode,
		// and forgetting that human are automatically excluded then,
		// or when getting back to the GUI mode, and not reconfiguring the competitors list.
		GfLogError("No competitor in this race : cancelled.\n");
		mode = RM_ERROR;
	}
	else if ((ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE)
		&& ReInfo->s->_totTime < 0.0f /* Timed session? */)
	//Checks if there is only one driver per session allowed, so practice, qualification without timed session. 
	{
		// non-timed Qualification or Practice session => 1 driver at a time = the "current" one.
		int nCurrDrvInd =
			(int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1);
		if (nCurrDrvInd <= 0)
			return RM_ERROR;

		// Propagate competitor drivers info to the real race starting grid
		snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, ReStartingOrderIdx[nCurrDrvInd-1]);
		snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, 1);

		GfParmSetStr(params, path2, RM_ATTR_MODULE,
					 GfParmGetStr(params, path, RM_ATTR_MODULE, ""));
		GfParmSetNum(params, path2, RM_ATTR_IDX, NULL,
					 GfParmGetNum(params, path, RM_ATTR_IDX, NULL, 0));
		GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL,
					 GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0));
		GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL,
					 GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0));
		if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0))
			GfParmSetStr(params, path2, RM_ATTR_SKINNAME,
						 GfParmGetStr(params, path, RM_ATTR_SKINNAME, ""));
	}
	else
	{
		// For a race, add cars to the starting grid in the order stored in ReStartingOrderIdx.
		ReUI().addLoadingMessage("Preparing Starting Grid ...");
		
		int maxCars = (int)GfParmGetNum(params, sessionName, RM_ATTR_MAX_DRV, NULL, 100);
		nCars = MIN(nCars, maxCars);
		int currDriver = -1;
		int aCars = 0;
		
		for (int i = 1; i < nCars + 1; i++)
		{
			currDriver = ReStartingOrderIdx[i-1];
			if (currDriver == -1)
				continue;
			aCars++;
			snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, currDriver);
			snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, i);
			GfParmSetStr(params, path2, RM_ATTR_MODULE,
						 GfParmGetStr(params, path, RE_ATTR_MODULE, ""));
			GfParmSetNum(params, path2, RM_ATTR_IDX, NULL,
						 GfParmGetNum(params, path, RE_ATTR_IDX, NULL, 0));
			GfParmSetNum(params, path2, RM_ATTR_EXTENDED, NULL,
						 GfParmGetNum(params, path, RM_ATTR_EXTENDED, NULL, 0));
			GfParmSetNum(params, path2, RM_ATTR_SKINTARGETS, NULL,
						 GfParmGetNum(params, path, RM_ATTR_SKINTARGETS, NULL, 0));
			if (GfParmGetStr(params, path, RM_ATTR_SKINNAME, 0))
				GfParmSetStr(params, path2, RM_ATTR_SKINNAME,
							 GfParmGetStr(params, path, RM_ATTR_SKINNAME, ""));
		}
		
		//no valid drivers present in the list
		if (aCars == 0)
		{
			GfLogError("No competitor in this race : cancelled.\n");
			mode = RM_ERROR;
		}
	}
	
	//ReTrackUpdate();

	if (!(mode & RM_ERROR))
	{
		// According to what the UI answers, start the race right now or not.
		mode = RM_ASYNC | RM_NEXT_STEP;
		const bool bGoOn = ReUI().onRaceStarting();
		if (bGoOn)
			mode = ReRaceRealStart();
	}
	
	return mode;
}
Esempio n. 9
0
static void
rmShowStandings(void *prevHdle, tRmInfo *info, int start)
{
	int i;
	int x1, x2, x3;
	int y;
	const int BUFSIZE = 1024;
	char buf[BUFSIZE];
	char path[BUFSIZE];
	float fgcolor[4] = {1.0, 0.0, 1.0, 1.0};
	int nbCars;
	int offset;
	void *results = info->results;
	const char *race = info->_reRaceName;
	
	rmScrHdle = GfuiScreenCreate();
	snprintf(buf, BUFSIZE, "%s Results", race);
	GfuiTitleCreate(rmScrHdle, buf, strlen(buf));
	
	GfuiScreenAddBgImg(rmScrHdle, "data/img/splash-result.png");
	
	offset = 200;
	x1 = offset + 30;
	x2 = offset + 60;
	x3 = offset + 240;
	
	y = 400;
	GfuiLabelCreateEx(rmScrHdle, "Rank",      fgcolor, GFUI_FONT_MEDIUM_C, x1, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Driver",    fgcolor, GFUI_FONT_MEDIUM_C, x2+10, y, GFUI_ALIGN_HL_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Points",      fgcolor, GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HR_VB, 0);
	y -= 20;
	
	nbCars = (int)GfParmGetEltNb(results, RE_SECT_STANDINGS);
	for (i = start; i < MIN(start + MAX_LINES, nbCars); i++) {
		snprintf(path, BUFSIZE, "%s/%d", RE_SECT_STANDINGS, i + 1);
		
		snprintf(buf, BUFSIZE, "%d", i+1);
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x1, y, GFUI_ALIGN_HC_VB, 0);
		
		GfuiLabelCreate(rmScrHdle, GfParmGetStr(results, path, RE_ATTR_NAME, ""), GFUI_FONT_MEDIUM_C,
				x2, y, GFUI_ALIGN_HL_VB, 0);
		
		snprintf(buf, BUFSIZE, "%d", (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x3, y, GFUI_ALIGN_HR_VB, 0);
		y -= 15;
	}
	
	
	if (start > 0) {
		RmPrevRace.prevHdle = prevHdle;
		RmPrevRace.info     = info;
		RmPrevRace.start    = start - MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-up.png", "data/img/arrow-up.png",
					"data/img/arrow-up.png", "data/img/arrow-up-pushed.png",
					80, 40, GFUI_ALIGN_HL_VB, 1,
					(void*)&RmPrevRace, rmChgStandingScreen,
					NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_UP,   "Previous Results", (void*)&RmPrevRace, rmChgStandingScreen, NULL);
	}
	
	GfuiButtonCreate(rmScrHdle,
				"Continue",
				GFUI_FONT_LARGE,
				210,
				40,
				150,
				GFUI_ALIGN_HC_VB,
				0,
				prevHdle,
				GfuiScreenReplace,
				NULL,
				(tfuiCallback)NULL,
				(tfuiCallback)NULL);
	
	rmSaveId = GfuiButtonCreate(rmScrHdle,
				"Save",
				GFUI_FONT_LARGE,
				430,
				40,
				150,
				GFUI_ALIGN_HC_VB,
				0,
				info,
				rmSaveRes,
				NULL,
				(tfuiCallback)NULL,
				(tfuiCallback)NULL);
	
	if (i < nbCars) {
		RmNextRace.prevHdle = prevHdle;
		RmNextRace.info     = info;
		RmNextRace.start    = start + MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-down.png", "data/img/arrow-down.png",
					"data/img/arrow-down.png", "data/img/arrow-down-pushed.png",
					540, 40, GFUI_ALIGN_HL_VB, 1,
					(void*)&RmNextRace, rmChgStandingScreen,
					NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_DOWN, "Next Results", (void*)&RmNextRace, rmChgStandingScreen, NULL);
	}
	
	GfuiAddKey(rmScrHdle, (unsigned char)27, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddKey(rmScrHdle, (unsigned char)13, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddSKey(rmScrHdle, GLUT_KEY_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL);
	
	GfuiScreenActivate(rmScrHdle);
}
Esempio n. 10
0
static void
rmPracticeResults(void *prevHdle, tRmInfo *info, int start)
{
	void *results = info->results;
	const char *race = info->_reRaceName;
	int i;
	int x1, x2, x3, x4, x5, x6;
	int offset;
	int y;
	const int BUFSIZE = 1024;
	char buf[BUFSIZE];
	char path[BUFSIZE];
	const int TIMEFMTSIZE = 256;
	char timefmt[TIMEFMTSIZE];
	float fgcolor[4] = {1.0, 0.0, 1.0, 1.0};
	int totLaps;

	rmScrHdle = GfuiScreenCreate();
	snprintf(buf, BUFSIZE, "Practice Results");
	GfuiTitleCreate(rmScrHdle, buf, strlen(buf));
	snprintf(path, BUFSIZE, "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race);
	snprintf(buf, BUFSIZE, "%s on track %s", GfParmGetStr(results, path, RM_ATTR_DRVNAME, ""), info->track->name);
	GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_LARGE_C,
			320, 420, GFUI_ALIGN_HC_VB, 0);
	GfuiScreenAddBgImg(rmScrHdle, "data/img/splash-result.png");
	
	offset = 90;
	
	x1 = offset + 30;
	x2 = offset + 50;
	x3 = offset + 130;
	x4 = offset + 240;
	x5 = offset + 310;
	x6 = offset + 400;
	
	y = 400;
	GfuiLabelCreateEx(rmScrHdle, "Lap",       fgcolor, GFUI_FONT_MEDIUM_C, x1, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Time",      fgcolor, GFUI_FONT_MEDIUM_C, x2+20, y, GFUI_ALIGN_HL_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Best",      fgcolor, GFUI_FONT_MEDIUM_C, x3+20, y, GFUI_ALIGN_HL_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Top Spd",   fgcolor, GFUI_FONT_MEDIUM_C, x4, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Min Spd",   fgcolor, GFUI_FONT_MEDIUM_C, x5, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Damages",  fgcolor, GFUI_FONT_MEDIUM_C, x6, y, GFUI_ALIGN_HC_VB, 0);
	y -= 20;
	
	snprintf(path, BUFSIZE, "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race);
	totLaps = (int)GfParmGetEltNb(results, path);
	for (i = 0 + start; i < MIN(start + MAX_LINES, totLaps); i++) {
		snprintf(path, BUFSIZE, "%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, i + 1);

		/* Lap */
		snprintf(buf, BUFSIZE, "%d", i+1);
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C, x1, y, GFUI_ALIGN_HC_VB, 0);

		/* Time */
		GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0), 0);
		GfuiLabelCreate(rmScrHdle, timefmt, GFUI_FONT_MEDIUM_C, x2, y, GFUI_ALIGN_HL_VB, 0);

		/* Best Lap Time */
		GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), 0);
		GfuiLabelCreate(rmScrHdle, timefmt, GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HL_VB, 0);

		/* Top Spd */
		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_TOP_SPEED, NULL, 0) * 3.6));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C, x4, y, GFUI_ALIGN_HC_VB, 0);

		/* Min Spd */
		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_BOT_SPEED, NULL, 0) * 3.6));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C, x5, y, GFUI_ALIGN_HC_VB, 0);

		/* Damages */
		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_DAMMAGES, NULL, 0)));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C, x6, y, GFUI_ALIGN_HC_VB, 0);

		y -= 15;
	}

	if (start > 0) {
		RmPrevRace.prevHdle = prevHdle;
		RmPrevRace.info     = info;
		RmPrevRace.start    = start - MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-up.png", "data/img/arrow-up.png",
				"data/img/arrow-up.png", "data/img/arrow-up-pushed.png",
				80, 40, GFUI_ALIGN_HL_VB, 1,
				(void*)&RmPrevRace, rmChgPracticeScreen,
				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_UP,   "Previous Results", (void*)&RmPrevRace, rmChgPracticeScreen, NULL);
	}
	
	GfuiButtonCreate(rmScrHdle,
			"Continue",
			GFUI_FONT_LARGE,
			320,
			40,
			150,
			GFUI_ALIGN_HC_VB,
			0,
			prevHdle,
			GfuiScreenReplace,
			NULL,
			(tfuiCallback)NULL,
			(tfuiCallback)NULL);

	if (i < totLaps) {
		RmNextRace.prevHdle = prevHdle;
		RmNextRace.info     = info;
		RmNextRace.start    = start + MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-down.png", "data/img/arrow-down.png",
				"data/img/arrow-down.png", "data/img/arrow-down-pushed.png",
				540, 40, GFUI_ALIGN_HL_VB, 1,
				(void*)&RmNextRace, rmChgPracticeScreen,
				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_DOWN, "Next Results", (void*)&RmNextRace, rmChgPracticeScreen, NULL);
	}

	GfuiAddKey(rmScrHdle, (unsigned char)27, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddKey(rmScrHdle, (unsigned char)13, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddSKey(rmScrHdle, GLUT_KEY_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL);

	GfuiScreenActivate(rmScrHdle);
}
Esempio n. 11
0
static void
rmRaceResults(void *prevHdle, tRmInfo *info, int start)
{
	void *results = info->results;
	const char *race = info->_reRaceName;
	int i;
	int x1, x2, x3, x4, x5, x6, x7, x8, x9;
	int dlap;
	int y;
	const int BUFSIZE = 1024;
	char buf[BUFSIZE];
	char path[BUFSIZE];
	const int TIMEFMTSIZE = 256;
	char timefmt[TIMEFMTSIZE];
	float fgcolor[4] = {1.0, 0.0, 1.0, 1.0};
	int laps, totLaps;
	tdble refTime;
	int nbCars;

	rmScrHdle = GfuiScreenCreate();
	snprintf(buf, BUFSIZE, "Race Results");
	GfuiTitleCreate(rmScrHdle, buf, strlen(buf));
	snprintf(buf, BUFSIZE, "%s", info->track->name);
	GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_LARGE_C,
			320, 420, GFUI_ALIGN_HC_VB, 0);
	GfuiScreenAddBgImg(rmScrHdle, "data/img/splash-result.png");
	
	x1 = 30;
	x2 = 60;
	x3 = 260;
	x4 = 330;
	x5 = 360;
	x6 = 420;
	x7 = 490;
	x8 = 545;
	x9 = 630;
	
	y = 400;
	GfuiLabelCreateEx(rmScrHdle, "Rank",      fgcolor, GFUI_FONT_MEDIUM_C, x1, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Driver",    fgcolor, GFUI_FONT_MEDIUM_C, x2+10, y, GFUI_ALIGN_HL_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Total",     fgcolor, GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HR_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Best",      fgcolor, GFUI_FONT_MEDIUM_C, x4, y, GFUI_ALIGN_HR_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Laps",      fgcolor, GFUI_FONT_MEDIUM_C, x5, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Top Spd",   fgcolor, GFUI_FONT_MEDIUM_C, x6, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Damage",    fgcolor, GFUI_FONT_MEDIUM_C, x7, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Pit",       fgcolor, GFUI_FONT_MEDIUM_C, x8, y, GFUI_ALIGN_HC_VB, 0);
	GfuiLabelCreateEx(rmScrHdle, "Penalty",   fgcolor, GFUI_FONT_MEDIUM_C, x9, y, GFUI_ALIGN_HR_VB, 0);	
	y -= 20;
	
	snprintf(path, BUFSIZE, "%s/%s/%s", info->track->name, RE_SECT_RESULTS, race);
	totLaps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0);
	snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, 1);
	refTime = GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0);
	snprintf(path, BUFSIZE, "%s/%s/%s/%s", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK);
	nbCars = (int)GfParmGetEltNb(results, path);
	for (i = start; i < MIN(start + MAX_LINES, nbCars); i++) {
		snprintf(path, BUFSIZE, "%s/%s/%s/%s/%d", info->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1);
		laps = (int)GfParmGetNum(results, path, RE_ATTR_LAPS, NULL, 0);

		snprintf(buf, BUFSIZE, "%d", i+1);
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x1, y, GFUI_ALIGN_HC_VB, 0);

		GfuiLabelCreate(rmScrHdle, GfParmGetStr(results, path, RE_ATTR_NAME, ""), GFUI_FONT_MEDIUM_C,
				x2, y, GFUI_ALIGN_HL_VB, 0);

		if (laps == totLaps) {
			if (i == 0) {
				GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0), 0);
			} else {
				GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_TIME, NULL, 0) - refTime, 1);
			}
			GfuiLabelCreate(rmScrHdle, timefmt, GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HR_VB, 0);
		} else {
			dlap = totLaps - laps;
			if (dlap == 1) {
				snprintf(buf, BUFSIZE, "+1 Lap");
			} else {
				snprintf(buf, BUFSIZE, "+%d Laps", dlap);
			}
			GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C, x3, y, GFUI_ALIGN_HR_VB, 0);

		}

		GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), 0);
		GfuiLabelCreate(rmScrHdle, timefmt, GFUI_FONT_MEDIUM_C,
				x4, y, GFUI_ALIGN_HR_VB, 0);

		snprintf(buf, BUFSIZE, "%d", laps);
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x5, y, GFUI_ALIGN_HC_VB, 0);

		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_TOP_SPEED, NULL, 0) * 3.6));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x6, y, GFUI_ALIGN_HC_VB, 0);

		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_DAMMAGES, NULL, 0)));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x7, y, GFUI_ALIGN_HC_VB, 0);

		snprintf(buf, BUFSIZE, "%d", (int)(GfParmGetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, 0)));
		GfuiLabelCreate(rmScrHdle, buf, GFUI_FONT_MEDIUM_C,
				x8, y, GFUI_ALIGN_HC_VB, 0);

		GfTime2Str(timefmt, TIMEFMTSIZE, GfParmGetNum(results, path, RE_ATTR_PENALTYTIME, NULL, 0), 0);
		GfuiLabelCreate(rmScrHdle, timefmt, GFUI_FONT_MEDIUM_C, x9, y, GFUI_ALIGN_HR_VB, 0);

		y -= 15;
	}

	if (start > 0) {
		RmPrevRace.prevHdle = prevHdle;
		RmPrevRace.info     = info;
		RmPrevRace.start    = start - MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-up.png", "data/img/arrow-up.png",
				"data/img/arrow-up.png", "data/img/arrow-up-pushed.png",
				80, 40, GFUI_ALIGN_HL_VB, 1,
				(void*)&RmPrevRace, rmChgRaceScreen,
				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_UP,   "Previous Results", (void*)&RmPrevRace, rmChgRaceScreen, NULL);
	}

	GfuiButtonCreate(rmScrHdle,
			"Continue",
			GFUI_FONT_LARGE,
			/* 210, */
			320,
			40,
			150,
			GFUI_ALIGN_HC_VB,
			0,
			prevHdle,
			GfuiScreenReplace,
			NULL,
			(tfuiCallback)NULL,
			(tfuiCallback)NULL);

	if (i < nbCars) {
		RmNextRace.prevHdle = prevHdle;
		RmNextRace.info     = info;
		RmNextRace.start    = start + MAX_LINES;
		GfuiGrButtonCreate(rmScrHdle, "data/img/arrow-down.png", "data/img/arrow-down.png",
				"data/img/arrow-down.png", "data/img/arrow-down-pushed.png",
				540, 40, GFUI_ALIGN_HL_VB, 1,
				(void*)&RmNextRace, rmChgRaceScreen,
				NULL, (tfuiCallback)NULL, (tfuiCallback)NULL);
		GfuiAddSKey(rmScrHdle, GLUT_KEY_PAGE_DOWN, "Next Results", (void*)&RmNextRace, rmChgRaceScreen, NULL);
	}

	GfuiAddKey(rmScrHdle, (unsigned char)27, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddKey(rmScrHdle, (unsigned char)13, "", prevHdle, GfuiScreenReplace, NULL);
	GfuiAddSKey(rmScrHdle, GLUT_KEY_F12, "Take a Screen Shot", NULL, GfuiScreenShot, NULL);

	GfuiScreenActivate(rmScrHdle);
}
Esempio n. 12
0
void
ReUpdateQualifCurRes(tCarElt *car)
{
	static const char* pszTableHeader = "Rank    \tTime          \tDriver                     \tCar";
	int		i;
	int		xx;
	int		nCars;
	int		nCarsReal;
	int		printed;
	int		maxLines;
	void	*carparam;
	char	*carName;
	const char	*race = ReInfo->_reRaceName;
	void	*results = ReInfo->results;
	char	*tmp_str;
	double		time_left;
	
	if (ReInfo->s->_ncars == 1)
	{
		ReUI().eraseResultsTable();
		maxLines = ReUI().getResultsTableRowCount();
		
		snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
		carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
		carName = GfParmGetName(carparam);

		char pszTitle[128];
		snprintf(pszTitle, sizeof(pszTitle), "%s at %s", 
				 race, ReInfo->track->name);
		if (ReInfo->s->_raceType == RM_TYPE_PRACTICE || car->_laps < 1 || car->_laps > ReInfo->s->_totLaps)
			snprintf(buf, sizeof(buf), "%s (%s)", car->_name, carName);
		else
			snprintf(buf, sizeof(buf), "%s (%s) - Lap %d", car->_name, carName, car->_laps);
		ReUI().setResultsTableTitles(pszTitle, buf);
		ReUI().setResultsTableHeader(pszTableHeader);

		printed = 0;
		snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK);
		nCarsReal = GfParmGetEltNb(results, path);
		nCars = MIN(nCarsReal + 1, maxLines); // limit display to only those on 1st page
		for (i = 1; i < nCars; i++) {
			snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i);
			if (!printed && car->_bestLapTime != 0.0
				&& car->_bestLapTime < GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0)) {
				tmp_str = GfTime2Str(car->_bestLapTime, "  ", false, 3);
				snprintf(buf, sizeof(buf), " %2d \t%-12s  \t%-25s \t%-20s", i, tmp_str, car->_name, carName);
				free(tmp_str);
				ReUI().setResultsTableRow(i - 1, buf, /*highlight=*/true);
				printed = 1;
			}
			tmp_str = GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), "  ", false, 3);
			snprintf(buf, sizeof(buf), " %2d \t%-12s  \t%-25s \t%-20s",
					 i + printed, tmp_str, GfParmGetStr(results, path, RE_ATTR_NAME, ""),
					 GfParmGetStr(results, path, RE_ATTR_CAR, ""));
			free (tmp_str);
			ReUI().setResultsTableRow(i - 1 + printed, buf);
		}
	
		if (!printed) {
			tmp_str = GfTime2Str(car->_bestLapTime, "  ", false, 3);
			snprintf(buf, sizeof(buf), " %2d \t%-12s  \t%-25s \t%-20s", nCarsReal + 1, tmp_str, car->_name, carName);
			free(tmp_str);
			ReUI().setResultsTableRow(i - 1, buf, /*highlight=*/true);
		}
	
		GfParmReleaseHandle(carparam);
	}
	else
	{
		nCars = ReInfo->s->_ncars;
		if (nCars > ReUI().getResultsTableRowCount())
			nCars = ReUI().getResultsTableRowCount();

		char pszTitle[128];
		snprintf(pszTitle, sizeof(pszTitle), "%s at %s", 
				 race, ReInfo->track->name);
		if (ReInfo->s->_totTime > ReInfo->s->currentTime)
		{
			time_left = ReInfo->s->_totTime - ReInfo->s->currentTime;
			snprintf( buf, sizeof(buf), "%d:%02d:%02d",
					  (int)floor( time_left / 3600.0f ), (int)floor( time_left / 60.0f ) % 60,
					  (int)floor( time_left ) % 60 );
		}
		else
		{
			snprintf( buf, sizeof(buf), "%d laps", ReInfo->s->_totLaps );
		}
		ReUI().setResultsTableTitles(pszTitle, buf);
		ReUI().setResultsTableHeader(pszTableHeader);
		
		for (xx = 0; xx < nCars; ++xx) {
			car = ReInfo->s->cars[ xx ];
			snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
			carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
			carName = strdup(GfParmGetName(carparam));
			GfParmReleaseHandle(carparam);
			
			if (car->_state & RM_CAR_STATE_DNF) {
				snprintf(buf, sizeof(buf), "out \t               \t%-25s \t%-20s", car->_name, carName);
			} else if (car->_bestLapTime <= 0.0f) {
				snprintf(buf, sizeof(buf), " %2d \t      --:---   \t%-25s \t%-20s",
						 xx + 1, car->_name, carName);
			} else {
				if (xx == 0)
					tmp_str = GfTime2Str(car->_bestLapTime, " ", false, 3);
				else
					tmp_str = GfTime2Str(car->_bestLapTime - ReInfo->s->cars[0]->_bestLapTime,
										 "+", false, 3);
				snprintf(buf, sizeof(buf), " %2d \t%-12s  \t%-25s \t%-20s",
						 xx + 1, tmp_str, car->_name, carName);
				free(tmp_str);
			}
			ReUI().setResultsTableRow(xx, buf);
			FREEZ(carName);
		}
	}
}
Esempio n. 13
0
void
ReStoreRaceResults(const char *race)
{
	int		i;
	int		nCars;
	tCarElt	*car;
	tSituation 	*s = ReInfo->s;
	char	*carName;
	void	*carparam;
	void	*results = ReInfo->results;
	void	*params = ReInfo->params;
	
	/* Store the number of laps of the race */
	switch (ReInfo->s->_raceType) {
		case RM_TYPE_RACE:
			car = s->cars[0];
			if (car->_laps > s->_totLaps) car->_laps = s->_totLaps + 1;

			snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
			GfParmListClean(results, path);
			GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1));
			
			for (i = 0; i < s->_ncars; i++) {
				snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1);
				car = s->cars[i];
				if (car->_laps > s->_totLaps)
					car->_laps = s->_totLaps + 1;
			
				GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
			
				snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
				carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
				carName = GfParmGetName(carparam);
			
				GfParmSetStr(results, path, RE_ATTR_CAR, carName);
				GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, (tdble)car->index);
			
				GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1));
				GfParmSetNum(results, path, RE_ATTR_TIME, NULL, (tdble)car->_curTime);
				GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime);
				GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed);
				GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, (tdble)car->_dammage);
				GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, (tdble)car->_nbPitStops);
			
				GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName);
				GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex);
				snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 );
				GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL,
							 GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0));
				GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName);
				snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
				GfParmSetNum(results, path, RE_ATTR_POINTS, NULL,
							 GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0));
				if (strlen(car->_skinName) > 0)
					GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName);
				GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets);

				GfParmReleaseHandle(carparam);
			}
			break;
			
		case RM_TYPE_PRACTICE:
			if (s->_ncars == 1)
			{
				car = s->cars[0];
				snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
				GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name);
				snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
				carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
				carName = GfParmGetName(carparam);
				GfParmSetStr(results, path, RE_ATTR_CAR, carName);
				GfParmReleaseHandle(carparam);
				break;
			}
			/* Otherwise, fall through */
			
		case RM_TYPE_QUALIF:
			if (s->_ncars == 1)
			{
				car = s->cars[0];
				snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK);
				nCars = GfParmGetEltNb(results, path);
				for (i = nCars; i > 0; i--) {
					snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i);
					float opponentBestLapTime = GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0);
				
					if (car->_bestLapTime != 0.0 
						&& (car->_bestLapTime < opponentBestLapTime || opponentBestLapTime == 0.0))
					{
						/* shift */
						snprintf(path2, sizeof(path2), "%s/%s/%s/%s/%d",
								ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1);
						GfParmSetStr(results, path2, RE_ATTR_NAME,
									 GfParmGetStr(results, path, RE_ATTR_NAME, ""));
						GfParmSetStr(results, path2, RE_ATTR_CAR,
									 GfParmGetStr(results, path, RE_ATTR_CAR, ""));
						GfParmSetNum(results, path2, RE_ATTR_BEST_LAP_TIME, NULL,
									 GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0));
						GfParmSetStr(results, path2, RE_ATTR_MODULE,
									 GfParmGetStr(results, path, RM_ATTR_MODULE, ""));
						GfParmSetNum(results, path2, RE_ATTR_IDX, NULL,
									 GfParmGetNum(results, path, RM_ATTR_IDX, NULL, 0));
						GfParmSetNum(results, path2, RM_ATTR_EXTENDED, NULL,
									 GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0));
						GfParmSetStr(results, path2, ROB_ATTR_CAR,
									 GfParmGetStr(results, path, ROB_ATTR_CAR, ""));
						GfParmSetStr(results, path2, ROB_ATTR_NAME,
									 GfParmGetStr(results, path, ROB_ATTR_NAME, ""));
						snprintf(path, sizeof(path), "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
						GfParmSetNum(results, path2, RE_ATTR_POINTS, NULL,
									 GfParmGetNum(params, path, RE_ATTR_POINTS, NULL, 0));
						if (GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0))
							GfParmSetStr(results, path2, RM_ATTR_SKINNAME,
										 GfParmGetStr(results, path, RM_ATTR_SKINNAME, 0));
						GfParmSetNum(results, path2, RM_ATTR_SKINTARGETS, NULL,
									 GfParmGetNum(results, path, RM_ATTR_SKINTARGETS, NULL, 0));
					} else {
						break;
					}
				}
				/* insert after */
				snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1);
				GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
				
				snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
				carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
				carName = GfParmGetName(carparam);
				
				GfParmSetStr(results, path, RE_ATTR_CAR, carName);
				GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime);
				GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName);
				GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex);
				GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName);
				GfParmSetStr(results, path, ROB_ATTR_NAME, car->_name);
				snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 );
				GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL,
							 GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0));
				snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
				GfParmSetNum(results, path, RE_ATTR_POINTS, NULL,
							 GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0));
				if (strlen(car->_skinName) > 0)
					GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName);
				GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets);
			
				GfParmReleaseHandle(carparam);
				break;
			} else {
				car = s->cars[0];
	
				if (s->_totTime < 0.0f)
					GfLogWarning("Saving results of multicar non-race session, but it was not timed!\n" );
				snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
				GfParmListClean(results, path);
				GfParmSetNum(results, path, RE_ATTR_SESSIONTIME, NULL, (tdble)s->_totTime);
				
				for (i = 0; i < s->_ncars; i++) {
					snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i + 1);
					car = s->cars[i];
				
					GfParmSetStr(results, path, RE_ATTR_NAME, car->_name);
				
					snprintf(buf, sizeof(buf), "cars/%s/%s.xml", car->_carName, car->_carName);
					carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
					carName = GfParmGetName(carparam);
				
					GfParmSetStr(results, path, RE_ATTR_CAR, carName);
					GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, (tdble)car->index);
				
					GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, (tdble)(car->_laps - 1));
					GfParmSetNum(results, path, RE_ATTR_TIME, NULL, (tdble)car->_curTime);
					GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, (tdble)car->_bestLapTime);
					GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed);
					GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, (tdble)car->_dammage);
					GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, (tdble)car->_nbPitStops);
				
					GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName);
					GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)car->_moduleIndex);
					snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, car->index + 1 );
					GfParmSetNum(results, path, RM_ATTR_EXTENDED, NULL,
								 GfParmGetNum(params, path2, RM_ATTR_EXTENDED, NULL, 0));
					GfParmSetStr(results, path, ROB_ATTR_CAR, car->_carName);
					snprintf(path2, sizeof(path2), "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
					GfParmSetNum(results, path, RE_ATTR_POINTS, NULL,
								 GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0));
					if (strlen(car->_skinName) > 0)
						GfParmSetStr(results, path, RM_ATTR_SKINNAME, car->_skinName);
					GfParmSetNum(results, path, RM_ATTR_SKINTARGETS, NULL, (tdble)car->_skinTargets);
			
					GfParmReleaseHandle(carparam);
				}
				break;
			}
	}
}
Esempio n. 14
0
int
ReRaceEventShutdown(void)
{
	char buf[64];
	int curTrkIdx;
	void *params = ReInfo->params;
	int nbTrk;
	void *results = ReInfo->results;
	int curRaceIdx;
	bool careerMode = false;
	bool first = true;

	// Notify the UI that the race event is finishing now.
	ReUI().onRaceEventFinishing();

	// Shutdown track-physics-related stuff.
	ReTrackShutdown();

	// Determine the track of the next event to come, if not the last one
	// and, if Career mode, prepare race params / results for the next event or season.
	do {
		nbTrk = GfParmGetEltNb(params, RM_SECT_TRACKS);
		curRaceIdx =(int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1);
		curTrkIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1);

		if (curRaceIdx == 1) {
			if (curTrkIdx < nbTrk) {
				// Next track.
				curTrkIdx++;
			} else if (curTrkIdx >= nbTrk) {
				// Back to the beginning.
				curTrkIdx = 1;
			}
		}

		GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, (tdble)curTrkIdx);

		// Career mode.
		if (!strcmp(GfParmGetStr(ReInfo->mainParams, RM_SECT_SUBFILES, RM_ATTR_HASSUBFILES, RM_VAL_NO), RM_VAL_YES)) {
			careerMode = true;
			const bool lastRaceOfRound = strcmp(GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_LASTSUBFILE, RM_VAL_YES), RM_VAL_YES) == 0;

			// Previous file <= Current file.
			GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_PREV_FILE,
						 GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, ""));
			// Current file <= Next file.
			GfParmSetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE,
						 GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_NEXTSUBFILE, ""));
			
			GfParmWriteFile(NULL, ReInfo->mainResults, NULL);
			
			/* Check if the next competition has a free weekend */
			if( !first ) {
				/* Close old params */
				GfParmWriteFile( NULL, results, NULL );
				GfParmReleaseHandle( results );
				GfParmReleaseHandle( params );
			}//if !first
			
			/* Open params of next race */
			params = GfParmReadFile( GfParmGetStr(ReInfo->mainResults, RE_SECT_CURRENT, RE_ATTR_CUR_FILE, "" ), GFPARM_RMODE_STD );
			if( !params )
				break;
			results = GfParmReadFile( GfParmGetStr(params, RM_SECT_SUBFILES, RM_ATTR_RESULTSUBFILE, ""), GFPARM_RMODE_STD );
			if( !results ) {
				GfParmReleaseHandle( results );
				break;
			}
	
			if (lastRaceOfRound && curTrkIdx == 1) {
				ReCareerNextSeason();
			}
			if ((int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) == 1) {
				GfParmListClean(results, RE_SECT_STANDINGS);
				GfParmWriteFile(NULL, results, NULL);
			}
	
			/* Check if it is free */
			snprintf( buf, sizeof(buf), "%s/%d", RM_SECT_TRACKS,
					  (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1) );
			if( !strcmp(GfParmGetStr(params, buf, RM_ATTR_NAME, "free"), "free") == 0) {
				/* Not a free weekend */
				GfParmReleaseHandle( results );
				GfParmReleaseHandle( params );
				break;
			}
			first = false;
		} else {
			// Normal mode (no subfiles, so free weekends possible, so nothing to check)
			break;
		}
	} while( true );

	// Determine new race state automaton mode.
	int mode = (curTrkIdx != 1 || careerMode) ? RM_NEXT_RACE : RM_NEXT_STEP;
	bool careerNonHumanGroup = careerMode && !ReHumanInGroup();

	mode |= ReUI().onRaceEventFinished(nbTrk != 1, careerNonHumanGroup) ? RM_SYNC : RM_ASYNC;;
	
	if (mode & RM_NEXT_STEP)
		FREEZ(ReInfo->_reCarInfo);

	NoCleanupNeeded = true;

	return mode;
}
Esempio n. 15
0
/**
 * This function initialize some values which can only be done after the track is loaded.
 * 
 * This function for example defines the sector start and ends
 *
 * @param TrackHandle The handle containing the information about the track
 */
static void
FinishTrackLoading(void* TrackHandle)
{
	double *distances = NULL;
	double currentDistance;
	double tmpDistance;
	int currentLength;
	int xx;

	theTrack->numberOfSectors = GfParmGetEltNb(TrackHandle, TRK_SECT_SECTORS);

	if (theTrack->numberOfSectors < 0)
		theTrack->numberOfSectors = 0;
	//TODO(kilo): possible divison by zero!!!
	if (theTrack->length / (double)theTrack->numberOfSectors < 100.0f )
	{
		theTrack->numberOfSectors = (int)floor( theTrack->length / 100.0f );
		GfOut( "WARNING: too many sectors" );
	}

	if (theTrack->numberOfSectors == 0)
	{
		/* Default is:
		 *   1 sector on circuits of 1km or shorter
		 *   3 sectors on circuits between 1km and 6km
		 *   the minimum number of sectors such that every sector is at most 2km if the track is longer then 6km
		 *
		 *   Note: the sector end at start-finish is added later
		 */
		if (theTrack->length < 1000.0f)
			theTrack->numberOfSectors = 0;
		else if(theTrack->length < 6000.0f)
			theTrack->numberOfSectors = 2;
		else
			theTrack->numberOfSectors = (int)floor( theTrack->length / 2000.0f );

		if (theTrack->numberOfSectors > 0)
		{
			distances = (double*)malloc( sizeof( double ) * theTrack->numberOfSectors );
			for( xx = 0; xx < theTrack->numberOfSectors; ++xx )
				distances[ xx ] = theTrack->length * (double)(xx + 1) / (double)(theTrack->numberOfSectors + 1);
		}
	}
	else
	{
		distances = (double*)malloc( sizeof( double ) * theTrack->numberOfSectors );
		currentLength = 0;

		if (GfParmListSeekFirst( TrackHandle, TRK_SECT_SECTORS ) == 0)
		{
			do
			{
				currentDistance = GfParmGetCurNum( TrackHandle, TRK_SECT_SECTORS, TRK_ATT_SECTOR_DFS, NULL, 0.0f);
				if (currentDistance <= 0.0f || currentDistance >= theTrack->length)
					continue; /* Don't add the startline as sector */
				for (xx = 0; xx < currentLength; ++xx)
				{
					if (distances[xx] > currentDistance)
					{
						tmpDistance = distances[xx];
						distances[xx] = currentDistance;
						currentDistance = tmpDistance;
					}
				}

				distances[currentLength] = currentDistance;
				++currentLength;
			} while (GfParmListSeekNext(TrackHandle, TRK_SECT_SECTORS) == 0);
		}

		theTrack->numberOfSectors = currentLength;
	}

	/* All know, now allocte the structures with the right size */
	if (theTrack->numberOfSectors > 0)
	{
		theTrack->sectors = (double*)malloc( sizeof(double) * theTrack->numberOfSectors );

		for( xx = 0; xx < theTrack->numberOfSectors; ++xx )
			theTrack->sectors[xx] = distances[xx];
	}
	else
	{
		theTrack->sectors = NULL;
	}

	/* Add the finish line as last sector */
	++theTrack->numberOfSectors;

	/* Free unused memory */
	if (distances)
		free( distances );
}
Esempio n. 16
0
int
RePreRace(void)
{
	char path[128];
	const char *raceName;
	const char *raceType;
	void *params = ReInfo->params;
	void *results = ReInfo->results;
	int curRaceIdx;
	int timedLapsReplacement = 0;
	char *prevRaceName;
	
	raceName = ReInfo->_reRaceName = ReGetCurrentRaceName();
	
	GfParmRemoveVariable (params, "/", "humanInGroup");
	GfParmRemoveVariable (params, "/", "eventNb");
	GfParmSetVariable (params, "/", "humanInGroup", ReHumanInGroup() ? 1.0f : 0.0f);
	GfParmSetVariable (params, "/", "eventNb", GfParmGetNum (ReInfo->results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1.0 ) );
	if (!raceName) {
		return RM_ERROR;
	}

	if (strcmp(GfParmGetStr(params, raceName, RM_ATTR_ENABLED, RM_VAL_YES), RM_VAL_NO) == 0) {
		GfLogTrace( "Race %s disabled\n",  raceName);
		curRaceIdx = (int)GfParmGetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1);
		if (curRaceIdx < GfParmGetEltNb(params, RM_SECT_RACES)) {
			curRaceIdx++;
			GfLogTrace( "Race %s is not the last one, but the #%d\n",  raceName, curRaceIdx);
			GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, (tdble)curRaceIdx);
	
			return RM_SYNC | RM_NEXT_RACE;
		}
	
		GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1);
		return RM_SYNC | RM_NEXT_RACE | RM_NEXT_STEP;
	}

	// Get session max dammages.
	ReInfo->s->_maxDammage = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DMG, NULL, 10000);

	// Get session type (race, qualification or practice).
	raceType = GfParmGetStr(params, raceName, RM_ATTR_TYPE, RM_VAL_RACE);
	if (!strcmp(raceType, RM_VAL_RACE)) {
		ReInfo->s->_raceType = RM_TYPE_RACE;
	} else if (!strcmp(raceType, RM_VAL_QUALIF)) {
		ReInfo->s->_raceType = RM_TYPE_QUALIF;
	} else if (!strcmp(raceType, RM_VAL_PRACTICE)) {
		ReInfo->s->_raceType = RM_TYPE_PRACTICE;
	}

	// Get session duration (defaults to "All sessions" one, or else -60).
	ReInfo->s->_totTime = GfParmGetNum(params, raceName, RM_ATTR_SESSIONTIME, NULL, -1);
	if (ReInfo->s->_totTime < 0)
		ReInfo->s->_totTime = GfParmGetNum(params, RM_VAL_ANYRACE, RM_ATTR_SESSIONTIME, NULL, -60.0f);

	// Determine the actual session duration and/or number of laps.
	ReInfo->s->_extraLaps = 0; // TODO: Does this is ever needed ?
	ReInfo->s->_totLaps = 0; // Make sure it is initialized

	if (ReInfo->s->_totTime > 0 && !(ReInfo->s->_features & RM_FEATURE_TIMEDSESSION)) {
		// Timed session not supported: add 1 km for every minute in parctise or qualifying,
		// and 150 km for every hour (2.5 km for every minute) in race
		if (ReInfo->s->_raceType == RM_TYPE_RACE) {
			ReInfo->s->_totLaps = (int)floor(ReInfo->s->_totTime * 2500.0f / 60.0f / ReInfo->track->length + 0.5f);
		} else {
			ReInfo->s->_totLaps = (int)floor(ReInfo->s->_totTime * 1000.0f / 60.0f / ReInfo->track->length + 0.5f);
		}
		timedLapsReplacement = ReInfo->s->_totLaps;
		ReInfo->s->_totTime = -60.0f;
	}
	
	// Timed session doesn't exclude additional laps after the time finishes
	// Make sure that if no time set, we set far below zero
	if(ReInfo->s->_totTime <= 0.0f )
		ReInfo->s->_totTime = -60.0f;
		
	// Get session distance (defaults to "All sessions" one, or else 0).
	tdble dist = GfParmGetNum(params, raceName, RM_ATTR_DISTANCE, NULL, -1);
	if (dist < 0)
		dist = GfParmGetNum(params, RM_VAL_ANYRACE, RM_ATTR_DISTANCE, NULL, 0);
	
	// If a (> 0) session distance was specified, deduce the number of laps
	// in case the race settings don't specify it, and it is not a timed race.
	if ( (dist >= 0.001) && (ReInfo->s->_totTime < 0.0f) ) { // Why not 'if (dist > 0)' ???
		ReInfo->s->_totLaps = (int)(dist / ReInfo->track->length) + 1;
		ReInfo->s->_extraLaps = ReInfo->s->_totLaps; // Extralaps are used to find out how many laps there are after the time is up in timed sessions
	} else {dist = -1;}
	
	// Get the number of laps (defaults to "All sessions" one,
	// or else the already computed one from the session distance, or 0).
	int laps = (int)GfParmGetNum(params, raceName, RM_ATTR_LAPS, NULL, -1);
	if (laps < 0)
		laps = (int)GfParmGetNum(params, RM_VAL_ANYRACE, RM_ATTR_LAPS, NULL, 0);

	// Use lap number only when race distance is not in use.
	if ( (laps > 0) && (dist <= 0.0) && (timedLapsReplacement <= 0) ) {
		ReInfo->s->_totLaps = laps;
		ReInfo->s->_extraLaps = ReInfo->s->_totLaps; //Extralaps are used to find out how many laps there are after the time is up in timed sessions
	}

	// Make sure we have at least 1 lap race length.
	if ( (laps <= 0) && (dist <=0) && (ReInfo->s->_totTime < 0) ) {
		ReInfo->s->_totLaps = 1;
		ReInfo->s->_extraLaps = ReInfo->s->_totLaps; //Extralaps are used to find out how many laps there are after the time is up in timed sessions
	}

	// Correct extra laps (possible laps run after the winner arrived ?) :
	// during timed practice or qualification, there are none.
	if (ReInfo->s->_raceType != RM_TYPE_RACE && ReInfo->s->_totTime > 0) {
		ReInfo->s->_extraLaps = 0; //Extralaps are used to find out how many laps there are after the time is up in timed sessions
		ReInfo->s->_totLaps = 0;
	}

	GfLogInfo("Race length : time=%.0fs, laps=%d (extra=%d)\n",
			  ReInfo->s->_totTime, ReInfo->s->_totLaps, ReInfo->s->_extraLaps);
	
	// Initialize race state.
	ReInfo->s->_raceState = 0;

	// Cleanup results
	snprintf(path, sizeof(path), "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, raceName);
	GfParmListClean(results, path);

	// Drivers starting order
	// The starting order is decided here,
	// then car indexes are stored in ReStartingOrderIdx, in the starting order.
	// The actual grid is assembled in ReRaceStart().
	// In case of a race, when all cars start at the same time,
	// cars are simply added to the starting list in the order stored in ReStartingOrderIdx.
	// If only one car is at the track at a time (not timed session qualifying or practice),
	// the race is divided into many sub-races.
	// For a sub-race, only the results/RE_ATTR_CUR_DRIVER-th driver in ReStartingOrderIdx
	// is added to the starting grid.
	// RE_ATTR_CUR_DRIVER is refreshed after every sub-race in ReRaceEnd().
	int nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
	GfParmListClean(params, RM_SECT_DRIVERS_RACING);
	if (nCars == 0)
	{
		// This may happen, when playing with the text-only mode,
		// and forgetting that human are automatically excluded then,
		// or when getting back to the GUI mode, and not reconfiguring the competitors list.
		GfLogError("No competitor in this race : cancelled.\n");
		return RM_ERROR;
	}
	else
	{
		ReUI().addLoadingMessage("Determining Starting Order ...");

		const char* gridType =
			GfParmGetStr(params, raceName, RM_ATTR_START_ORDER, RM_VAL_DRV_LIST_ORDER);
		
		int maxCars = (int)GfParmGetNum(params, raceName, RM_ATTR_MAX_DRV, NULL, 100);
		nCars = MIN(nCars, maxCars);
		
		tReGridPart *GridList = NULL;
		int nGridList = 0;
		
		// Initialize the array of car indexes for starting order
		if (ReStartingOrderIdx != NULL) {
			delete[] ReStartingOrderIdx;
			ReStartingOrderIdx = NULL;
		}
		ReStartingOrderIdx = new int[nCars];
		for (int i = 0; i < nCars; i++) {
			ReStartingOrderIdx[i] = -1;
		}
		
		// Starting grid in the arrival order of the previous race (or qualification session)
		if (!strcmp(gridType, RM_VAL_LAST_RACE_ORDER))
		{
			GfLogTrace("Starting grid in the order of the last race\n");
			
			prevRaceName = ReGetPrevRaceName(/* bLoop = */false);
			if (!prevRaceName) {
				return RM_ERROR;
			}

			for (int i = 1; i < nCars + 1; i++) {
				snprintf(path, sizeof(path), "%s/%s/%s/%s/%d",
						 ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, i);
				ReStartingOrderIdx[i-1] = 
					ReFindDriverIdx (GfParmGetStr(results, path, RE_ATTR_MODULE, ""),
									(int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
			}
		}
		
		// Starting grid in the reversed arrival order of the previous race
		else if (!strcmp(gridType, RM_VAL_LAST_RACE_RORDER))
		{
			GfLogTrace("Starting grid in the reverse order of the last race\n");

			prevRaceName = ReGetPrevRaceName(/* bLoop = */false);
			if (!prevRaceName) {
				return RM_ERROR;
			}

			for (int i = 1; i < nCars + 1; i++) {
				snprintf(path, sizeof(path), "%s/%s/%s/%s/%d",
						ReInfo->track->name, RE_SECT_RESULTS, prevRaceName, RE_SECT_RANK, nCars - i + 1);
				ReStartingOrderIdx[i-1] = 
					ReFindDriverIdx (GfParmGetStr(results, path, RE_ATTR_MODULE, ""),
									(int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0));
			}
		}

		// Starting grid as a mix from the results of earlier sessions
		else if (ReParseStartingOrder(gridType, &GridList, nCars, nGridList))
		{
			GfLogTrace("Starting grid as a mix from the results of earlier sessions\n");
			
			int idx;
			int gridpos = 1;
			int carnr;
			const char *modulename;
			for (int i = 0; i < nGridList; i++) {
				if (gridpos > nCars) {break;}
				if (GridList[i].diffpos == -1) {//reversed
					for ( int j = GridList[i].startpos; j >= GridList[i].endpos; j--) {
						if (gridpos > nCars) {break;}
						snprintf(path, sizeof(path), "%s/%s/%s/%s/%d",
								ReInfo->track->name, RE_SECT_RESULTS, GridList[i].racename, RE_SECT_RANK, j);
						idx = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0);
						modulename = GfParmGetStr(results, path, RE_ATTR_MODULE, "");
						carnr = ReFindDriverIdx(modulename, idx);
						for (int k = 0; k < gridpos-1; k++) {
							if ( carnr == ReStartingOrderIdx[k] ) {
								//oops: same car twice
								GfLogWarning("The same car appears twice in the advanced grid!\n");
								carnr = -1;
								break;
							}
						}
						//adding car to the list
						if (carnr != -1) {
							ReStartingOrderIdx[gridpos-1] = carnr;
							gridpos++;
						}
					}
				} else if (GridList[i].diffpos == 1){//straight order
					for ( int j = GridList[i].startpos; j <= GridList[i].endpos; j++) {
						if (gridpos > nCars) {break;}
						snprintf(path, sizeof(path), "%s/%s/%s/%s/%d",
								ReInfo->track->name, RE_SECT_RESULTS, GridList[i].racename, RE_SECT_RANK, j);
						idx = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0);
						modulename = GfParmGetStr(results, path, RE_ATTR_MODULE, "");
						carnr = ReFindDriverIdx(modulename, idx);
						for (int k = 0; k < gridpos-1; k++) {
							if ( carnr == ReStartingOrderIdx[k] ) {
								//oops: same car twice
								GfLogWarning("The same car appears twice in the advanced grid!\n");
								carnr = -1;
								break;
							}
						}
						//adding car to the list
						if (carnr != -1) {
							ReStartingOrderIdx[gridpos-1] = carnr;
							gridpos++;
						}
					}
				}
			}
			//cleaning up memory
			if (nGridList > 0){delete[] GridList;}
		}

		// Starting grid in the drivers list order
		else
		{
			GfLogTrace("Starting grid in the order of the driver list\n");

			for (int i = 1; i < nCars + 1; i++) {
				snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS, i);
				ReStartingOrderIdx[i-1] = 
					ReFindDriverIdx (GfParmGetStr(params, path, RE_ATTR_MODULE, ""),
									(int)GfParmGetNum(params, path, RE_ATTR_IDX, NULL, 0));
			}
		}
	}
	
	GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1.0);

	return RM_SYNC | RM_NEXT_STEP;
}
Esempio n. 17
0
void GfFileSetup()
{
	void *dataVersionHandle;
	void *localVersionHandle;
	char *filename;
	size_t filenameLength;
	char *dataLocation;
	char *localLocation;
	char *absLocalLocation;
	char *absDataLocation;
	bool *isIndexUsed;
	int isIndexUsedLen;
	int index;
	bool anyLocalChange, fileFound;
	int major;
	int minor;
	struct stat st;

	// Open data (installation) version.xml.
	filenameLength = strlen(GfDataDir()) + 12 + 40;
	filename = (char*)malloc( sizeof(char) * filenameLength );
	sprintf( filename, "%sversion.xml", GfDataDir() );
	dataVersionHandle = GfParmReadFile( filename, GFPARM_RMODE_STD );
	if( !dataVersionHandle )
	{
		free( filename );
		return;
	}

	// Exit if nothing inside.
	if( GfParmListSeekFirst( dataVersionHandle, "versions" ) != 0 )
	{
		free( filename );
		GfParmReleaseHandle( dataVersionHandle );
		return;
	}

	// Create LocalDir (user settings root) if not already done.
	GfDirCreate( GfLocalDir() );

	// Open local (user settings) version.xml (create it if not there).
	if( filenameLength < strlen(GfLocalDir()) + 12 )
	{
		free( filename );
		filenameLength = strlen(GfLocalDir()) + 12 + 40;
		filename = (char*)malloc( sizeof(char) * filenameLength );
	}

	sprintf( filename, "%sversion.xml", GfLocalDir() );
	anyLocalChange = !GfFileExists(filename);
	localVersionHandle = GfParmReadFile( filename, GFPARM_RMODE_CREAT );

	// Exit if open/creation failed.
	if( !localVersionHandle )
	{
		free( filename );
		GfParmReleaseHandle( dataVersionHandle );
		return;
	}

	// Setup the index of the XML files referenced in the local version.xml.
	isIndexUsedLen = GfParmGetEltNb( localVersionHandle, "versions" )
		             + GfParmGetEltNb( dataVersionHandle, "versions" ) + 2;
	isIndexUsed = (bool*)malloc( sizeof(bool) * isIndexUsedLen );
	for( index = 0; index < isIndexUsedLen; index++ )
		isIndexUsed[index] = false;
	if( GfParmListSeekFirst( localVersionHandle, "versions" ) == 0 )
	{
		do
		{
			index = atoi( GfParmListGetCurEltName( localVersionHandle, "versions" ) );
			if( 0 <= index && index < isIndexUsedLen )
				isIndexUsed[index] = true;
		} while( GfParmListSeekNext( localVersionHandle, "versions" ) == 0 );
	}

	// For each file referenced in the installation version.xml
	do
	{
		fileFound = false;

		// Get its installation path (data), user settings path (local),
		// and new major and minor version numbers
		dataLocation = strdup( GfParmGetCurStr( dataVersionHandle, "versions", "Data location", "" ) );
		localLocation = strdup( GfParmGetCurStr( dataVersionHandle, "versions", "Local location", "" ) );
		major = (int)GfParmGetCurNum( dataVersionHandle, "versions", "Major version", NULL, 0 );
		minor = (int)GfParmGetCurNum( dataVersionHandle, "versions", "Minor version", NULL, 0 );

		absLocalLocation = (char*)malloc( sizeof(char)*(strlen(GfLocalDir())+strlen(localLocation)+3) );
		sprintf( absLocalLocation, "%s%s", GfLocalDir(), localLocation );

		absDataLocation = (char*)malloc( sizeof(char)*(strlen(GfDataDir())+strlen(dataLocation)+3) );
		sprintf( absDataLocation, "%s%s", GfDataDir(), dataLocation );

		GfLogTrace("Checking %s : user settings version ", localLocation);

		// Search for its old major and minor version numbers in the user settings.
		if( GfParmListSeekFirst( localVersionHandle, "versions" ) == 0 )
		{
			do
			{
				if( strcmp( absLocalLocation, GfParmGetCurStr( localVersionHandle, "versions", "Local location", "" ) ) == 0 )
				{
					fileFound = true;
					const int locMinor = (int)GfParmGetCurNum( localVersionHandle, "versions", "Minor version", NULL, 0 );
					const int locMajor = (int)GfParmGetCurNum( localVersionHandle, "versions", "Major version", NULL, 0 );

					GfLogTrace("%d.%d is ", locMajor, locMinor);

					if( locMajor != major || locMinor < minor)
					{
						GfLogTrace("obsolete (installed one is %d.%d) => updating ...\n",
								   major, minor);
						if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, -1 ) )
							anyLocalChange = true;
					}
					else
					{
					    GfLogTrace("up-to-date");
						if (stat(absLocalLocation, &st))
						{
							GfLogTrace(", but not there => installing ...\n");
							if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, -1 ) )
								anyLocalChange = true;
						}
						else
							GfLogTrace(".\n");
					}
					
					break;
				}
			} while( GfParmListSeekNext( localVersionHandle, "versions" ) == 0 );
		}

		if( !fileFound)
		{
			index = 0;
			while( isIndexUsed[index] )
				++index;
			GfLogTrace("not found => installing ...\n");
			if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, index ) )
				anyLocalChange = true;
			isIndexUsed[index] = true;
		}

		free( dataLocation );
		free( localLocation );
		free( absDataLocation );
		free( absLocalLocation );

	} while( GfParmListSeekNext( dataVersionHandle, "versions" ) == 0 );

	// Write the user settings version.xml if changed.
	if (anyLocalChange)
		GfParmWriteFile( NULL, localVersionHandle, "versions" );

	GfParmReleaseHandle( localVersionHandle );
	GfParmReleaseHandle( dataVersionHandle );
	free( isIndexUsed );
	free( filename );
}
Esempio n. 18
0
void
ReUpdateStandings(void)
{
	tReStandings st;
	std::string drvName;
	std::vector<tReStandings> *standings;
	std::vector<tReStandings>::iterator found;
	std::vector<tReStandings>::iterator it;
	int runDrv, curDrv;
	int i;
	void *results = ReInfo->results;

	snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK);
	runDrv = GfParmGetEltNb(results, path);
	curDrv = GfParmGetEltNb(results, RE_SECT_STANDINGS);
	
	standings = new std::vector<tReStandings>;

	standings->reserve(curDrv);

	/* Read the current standings */
	for (i = 0; i < curDrv; i++) 
	{
		snprintf(path2, sizeof(path2), "%s/%d", RE_SECT_STANDINGS, i + 1);
		st.drvName = GfParmGetStr(results, path2, RE_ATTR_NAME, 0);
		st.shortname = GfParmGetStr(results, path2, RE_ATTR_SNAME, 0);
		st.modName = GfParmGetStr(results, path2, RE_ATTR_MODULE, 0);
		st.carName = GfParmGetStr(results, path2, RE_ATTR_CAR, 0);
		st.extended = (int)GfParmGetNum(results, path2, RM_ATTR_EXTENDED, NULL, 0);
		st.drvIdx  = (int)GfParmGetNum(results, path2, RE_ATTR_IDX, NULL, 0);
		st.points  = (int)GfParmGetNum(results, path2, RE_ATTR_POINTS, NULL, 0);
		standings->push_back(st);
	}//for i

	//Void the stored results
	GfParmListClean(results, RE_SECT_STANDINGS);
	
	//Check last races' drivers and search their name in the results.
	//If found there, adds recent points.
	//If not found, adds the driver
	for (i = 0; i < runDrv; i++) {
		//Search the driver name in the standings
		snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK, i + 1);
		drvName = GfParmGetStr(results, path, RE_ATTR_NAME, 0);
		found = std::find(standings->begin(), standings->end(), drvName);
		
		if(found == standings->end()) {
			//No such driver in the standings, let's add it
			st.drvName = drvName;
			st.shortname = GfParmGetStr(results, path, RE_ATTR_SNAME, 0);
			st.modName = GfParmGetStr(results, path, RE_ATTR_MODULE, 0);
			st.carName = GfParmGetStr(results, path, RE_ATTR_CAR, 0);
			st.extended = (int)GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0);
			st.drvIdx  = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0);
			st.points  = (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
			standings->push_back(st);
		} else {
			//Driver found, add recent points
			found->points += (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
		}//if found
	}//for i
	
	//sort standings by score
	std::sort(standings->begin(), standings->end(), sortByScore);
	
	//Store the standing back
	for(it = standings->begin(), i = 0; it != standings->end(); ++it, ++i) {
		snprintf(path, sizeof(path), "%s/%d", RE_SECT_STANDINGS, i + 1);
		GfParmSetStr(results, path, RE_ATTR_NAME, it->drvName.c_str());
		GfParmSetStr(results, path, RE_ATTR_SNAME, it->shortname.c_str());
		GfParmSetStr(results, path, RE_ATTR_MODULE, it->modName.c_str());
		GfParmSetStr(results, path, RE_ATTR_CAR, it->carName.c_str());
		GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)it->drvIdx);
		GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, (tdble)it->points);
	}//for it
	delete standings;
	
	char str1[512], str2[512];
	snprintf(str1, sizeof(str1), "%sconfig/params.dtd", GfDataDir());
	snprintf(str2, sizeof(str2), "<?xml-stylesheet type=\"text/xsl\" href=\"file:///%sconfig/raceresults.xsl\"?>", GfDataDir());
	
	GfParmSetDTD (results, str1, str2);
	GfParmWriteFile(0, results, "Results");
}//ReUpdateStandings
Esempio n. 19
0
static void 
UpdateNetworkPlayers()
{
	GfDriver* newDriver;
	NetNetwork *pNetwork = NetGetNetwork();

	if (pNetwork->GetRefreshDisplay() == false)
		return;

	tRmInfo* reInfo = LmRaceEngine().inData();

	//Set current driver that camera will look at
	pNetwork->SetCurrentDriver();

	//reload xml file
	NetGetNetwork()->SetRaceXMLFile("config/raceman/networkrace.xml");
	reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD);
	assert(reInfo->params);

	reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, "");
	assert(reInfo->_reName);

	// Scan each of the human drivers to see if they're active in this race
	if (NetIsServer()) {
		NetServerMutexData *pSData = NetGetServer()->LockServerData();
		assert(pSData);

		// Ensure that garage menu knows about driver
		for (unsigned int i=0; i < pSData->m_vecNetworkPlayers.size(); i++) {
			newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx);

			if (!newDriver) { 
				GfLogInfo("Driver %s not found, reloading drivers\n", pSData->m_vecNetworkPlayers[i].name);
				GfDrivers::self()->reload();
				LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true);
				break;
			}
		}

		for (unsigned int i=0; i < pSData->m_vecNetworkPlayers.size(); i++) {
			int k = 1;
			char path2[256];

			pSData->m_vecNetworkPlayers[i].active = false;
			newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx);

			// Scan through drivers listed in 'networkrace.xml'
			while (pSData->m_vecNetworkPlayers[i].active == false) {
				sprintf(path2, "%s/%d", RM_SECT_DRIVERS, k++);
				if (GfParmExistsSection(reInfo->params, path2) == 0) {
					GfLogInfo("UpdateNetworkPlayers: Removing driver %s\n", pSData->m_vecNetworkPlayers[i].name);

					if (pSData->m_vecNetworkPlayers[i].client) {
						//need to tell/force client to disconnect
					}
					break;
				}

				if ((tdble)pSData->m_vecNetworkPlayers[i].idx == GfParmGetNum(reInfo->params, path2, RM_ATTR_IDX, NULL, 1.0) &&
						strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, path2, RM_ATTR_MODULE, "")) == 0) {
					pSData->m_vecNetworkPlayers[i].active = true;
				}
			}

			// add or remove from competitor list (for garage menu)
			GfDriver* activeDriver = LmRaceEngine().race()->getCompetitor(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx);
			if (pSData->m_vecNetworkPlayers[i].active) {
				if (!activeDriver) LmRaceEngine().race()->appendCompetitor(newDriver);
			} else {
				if (activeDriver) LmRaceEngine().race()->removeCompetitor(newDriver);
			}
		}
		NetGetServer()->UnlockServerData();
	} else {
#if 1
		// Client XML files already written to disk - this works but is not the best solution....
		GfDrivers::self()->reload();
		LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true);
#endif
	}

	//Update track info
	std::string strTrackPath = GfParmGetStr(reInfo->params, "Tracks/1", RM_ATTR_NAME, "");
	std::string strCategory = GfParmGetStr(reInfo->params, "Tracks/1", RM_ATTR_CATEGORY, "");

	std::string strTrackName = GetTrackName(strCategory.c_str(),strTrackPath.c_str());

	sprintf(buf, "%s", strTrackName.c_str());
	GfuiLabelSetText(racemanMenuHdle,g_trackHd,buf);

	//Store current track - client needs this
	GfTrack* PCurTrack = GfTracks::self()->getTrackWithName(buf);
	LmRaceEngine().race()->getManager()->setEventTrack(0, PCurTrack);
	
	int laps = (int)GfParmGetNum(reInfo->params, reInfo->_reName,"laps", "", 1);
	sprintf(buf, "%i", laps);
	GfuiLabelSetText(racemanMenuHdle,g_lapsHd,buf);

	GfuiScreenAddBgImg(racemanMenuHdle,
					   GetTrackPreviewFileName(strCategory.c_str(),strTrackPath.c_str()).c_str());
	GfuiStaticImageSet(racemanMenuHdle, g_OutlineId,
					   GetTrackOutlineFileName(strCategory.c_str(),strTrackPath.c_str()).c_str());

	// Update category info
	std::string strCarCat;
	bool bCollisions;
	NetGetNetwork()->GetHostSettings(strCarCat,bCollisions);
	GfuiLabelSetText(racemanMenuHdle,g_catHd,strCarCat.c_str());

	//fill in player data
	int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS);

	char	dname[256];
	char    robpath[256];

	float *pColor = &green[0];

	bool bEveryoneReadyToRace = true;
	
	for (int i = 1; i < nCars+1; i++) 
	{
		sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i);

		const char* robot = GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "");

		//lookup playerName and car name
		sprintf(robpath,"drivers/%s/%s.xml",robot,robot);
		void *pMod = GfParmReadFileLocal(robpath,GFPARM_RMODE_REREAD);

		if (pMod == NULL)
		{
			//try again in other path
			sprintf(robpath,"drivers/%s/%s.xml",robot,robot);
			pMod = GfParmReadFile(robpath,GFPARM_RMODE_REREAD);
			if (pMod == NULL)
				continue;
		}

		assert(pMod);

		char ppname[256];
		int idx = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, "",0);
		sprintf(ppname,"Robots/index/%d",idx);
		const char* name = GfParmGetStr(pMod, ppname, RM_ATTR_NAME, "");

		const char* car = GfParmGetStr(pMod, ppname, "car name", "");
		std::string strRealCar = GfCars::self()->getCar(car)->getName();

		// WAIT : pNData->m_vecReadyStatus[i-1] ?!
		//        This can only work when _only_ networkhuman drivers in the race
		//        (that is _no_robot_driver_) ; because m_vecReadyStatus is indexed
		//        by the networkhuman drivers list.
		// TO fix this, 2 solutions:
		// 1) make the networking module take care of the robot drivers too
		//    (in m_vecReadyStatus, m_vecNetworkPlayers, ...)
		// 2) make the networking _menu_ only take care of the networkhuman drivers.
		bool bReady = bRobotsReady;
		if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) {
			// Write car model, as it may have changed via garage menu
			if (NetIsServer()) {
				NetServerMutexData *pSData = NetGetServer()->LockServerData();
				strncpy(pSData->m_vecNetworkPlayers[idx-1].car, car, 64);
				GfLogInfo("idx %d car set to %s\n", idx, car);

				// also need to write back for garage menu
				const GfCar* newCar = GfCars::self()->getCar(car);
				newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[idx-1].idx);
				newDriver->setCar(newCar);
				NetGetServer()->UnlockServerData();
			}

			//GfLogInfo("idx %d, m_vecReadyStatus.size() %d\n", idx, pNData->m_vecReadyStatus.size());
			NetMutexData *pNData = NetGetNetwork()->LockNetworkData();
			bReady = pNData->m_vecReadyStatus[idx-1];
			NetGetNetwork()->UnlockNetworkData();
		}

		int readyindex = 0;
		if (bReady)
			readyindex = 1;	
		else
			bEveryoneReadyToRace = false;

		if (strcmp(NetGetNetwork()->GetDriverName(),name)==0)
		{
			pColor = &green[0];
			g_strCar = strRealCar;
			//Make sure checkbox matches ready state
			GfuiCheckboxSetChecked(racemanMenuHdle, g_ReadyCheckboxId, bReady);
			if (NetGetClient())
				EnableMenuClientButtons(bReady);
			else
				EnableMenuHostButtons(bReady);
		}
		else
			pColor = &white[0];

		GfuiVisibilitySet(racemanMenuHdle,g_readystatus[i-1],true);
		GfuiStaticImageSetActive(racemanMenuHdle,g_readystatus[i-1],readyindex);
		GfuiLabelSetColor(racemanMenuHdle, g_playerNames[i-1], pColor);
		GfuiLabelSetText(racemanMenuHdle,g_playerNames[i-1],name);

		GfuiLabelSetColor(racemanMenuHdle, g_carNames[i-1], pColor);
		GfuiLabelSetText(racemanMenuHdle,g_carNames[i-1],strRealCar.c_str());
		GfParmReleaseHandle(pMod);
	}

	//Clear out rest of table
	for (int i=nCars;i<MAXNETWORKPLAYERS;i++)
	{
		GfuiVisibilitySet(racemanMenuHdle,g_readystatus[i],false);
		GfuiLabelSetText(racemanMenuHdle,g_playerNames[i],"");
		GfuiLabelSetText(racemanMenuHdle,g_carNames[i],"");
	}

	pNetwork->SetRefreshDisplay(false);
	GfuiApp().eventLoop().postRedisplay();

	if (NetIsClient())
	{	
		NetGetClient()->ConnectToClients();

		if (!NetGetClient()->TimeSynced())
		{
			NetGetClient()->SendServerTimeRequest();
		}
	}

	if (NetIsServer())
	{
		if (bEveryoneReadyToRace && nCars > 1)
			ServerPrepareStartNetworkRace(NULL);
	}
}