/***************************************************************************
file : raceresults.cpp
created : Thu Jan 2 12:43:10 CET 2003
copyright : (C) 2002 by Eric Espié
email : eric.espie@torcs.org
version : $Id: raceresults.cpp,v 1.9 2006/10/06 15:33:03 berniw Exp $
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/** @file
@author Eric Espie
@version $Id: raceresults.cpp,v 1.9 2006/10/06 15:33:03 berniw Exp $
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "racemain.h"
#include "racegl.h"
#include "raceinit.h"
#include "raceengine.h"
#include "raceresults.h"
static char buf[1024];
static char path[1024];
static char path2[1024];
typedef struct
{
char *carName;
char *modName;
int drvIdx;
int points;
} tReStandings;
void
ReInitResults(void)
{
struct tm *stm;
time_t t;
void *results;
t = time(NULL);
stm = localtime(&t);
sprintf(buf, "%sresults/%s/results-%4d-%02d-%02d-%02d-%02d.xml",
GetLocalDir(),
ReInfo->_reFilename,
stm->tm_year+1900,
stm->tm_mon+1,
stm->tm_mday,
stm->tm_hour,
stm->tm_min);
ReInfo->results = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);
results = ReInfo->results;
GfParmSetNum(results, RE_SECT_HEADER, RE_ATTR_DATE, NULL, (tdble)t);
GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_TRACK, NULL, 1);
GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_RACE, NULL, 1);
GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, 1);
}
void
ReEventInitResults(void)
{
int nCars;
int i;
void *results = ReInfo->results;
void *params = ReInfo->params;
nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS);
for (i = 1; i < nCars + 1; i++) {
sprintf(path, "%s/%s/%d", ReInfo->track->name, RM_SECT_DRIVERS, i);
sprintf(path2, "%s/%d", RM_SECT_DRIVERS, i);
GfParmSetStr(results, path, RE_ATTR_DLL_NAME, GfParmGetStr(params, path2, RM_ATTR_MODULE, ""));
GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, GfParmGetNum(params, path2, RM_ATTR_IDX, (char*)NULL, 0));
}
}
void
ReUpdateStandings(void)
{
int maxDrv;
int curDrv;
int runDrv;
char *carName;
char *modName;
int drvIdx;
int points;
int i, j;
int found;
tReStandings *standings = 0;
void *results = ReInfo->results;
char str1[1024], str2[1024];
sprintf(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);
maxDrv = curDrv + runDrv;
standings = (tReStandings *)calloc(maxDrv, sizeof(tReStandings));
/* Read the current standings */
for (i = 0; i < curDrv; i++) {
sprintf(path2, "%s/%d", RE_SECT_STANDINGS, i + 1);
standings[i].carName = strdup(GfParmGetStr(results, path2, RE_ATTR_NAME, 0));
standings[i].modName = strdup(GfParmGetStr(results, path2, RE_ATTR_MODULE, 0));
standings[i].drvIdx = (int)GfParmGetNum(results, path2, RE_ATTR_IDX, NULL, 0);
standings[i].points = (int)GfParmGetNum(results, path2, RE_ATTR_POINTS, NULL, 0);
}
GfParmListClean(results, RE_SECT_STANDINGS);
for (i = 0; i < runDrv; i++) {
/* Search the driver in the standings */
found = 0;
sprintf(path, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK, i + 1);
carName = GfParmGetStr(results, path, RE_ATTR_NAME, 0);
for (j = 0; j < curDrv; j++) {
if (!strcmp(carName, standings[j].carName)) {
found = 1;
break;
}
}
if (!found) {
/* Add the new driver */
curDrv++;
standings[j].carName = strdup(carName);
standings[j].modName = strdup(GfParmGetStr(results, path, RE_ATTR_MODULE, 0));
standings[j].drvIdx = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0);
standings[j].points = (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
} else {
/* Add the new points */
standings[j].points += (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
}
/* bubble sort... */
while (j > 0) {
if (standings[j - 1].points >= standings[j].points) {
break;
}
/* Swap with preceeding */
carName = standings[j].carName;
modName = standings[j].modName;
drvIdx = standings[j].drvIdx;
points = standings[j].points;
standings[j].carName = standings[j - 1].carName;
standings[j].modName = standings[j - 1].modName;
standings[j].drvIdx = standings[j - 1].drvIdx;
standings[j].points = standings[j - 1].points;
standings[j - 1].carName = carName;
standings[j - 1].modName = modName;
standings[j - 1].drvIdx = drvIdx;
standings[j - 1].points = points;
j--;
}
}
/* Store the standing back */
for (i = 0; i < curDrv; i++) {
sprintf(path, "%s/%d", RE_SECT_STANDINGS, i + 1);
GfParmSetStr(results, path, RE_ATTR_NAME, standings[i].carName);
free(standings[i].carName);
GfParmSetStr(results, path, RE_ATTR_MODULE, standings[i].modName);
free(standings[i].modName);
GfParmSetNum(results, path, RE_ATTR_IDX, NULL, standings[i].drvIdx);
GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, standings[i].points);
}
free(standings);
sprintf(str1, "%sconfig/params.dtd", GetDataDir());
sprintf(str2, "", GetDataDir());
GfParmSetDTD (results, str1, str2);
GfParmWriteFile(0, results, "Results");
}
void
ReStoreRaceResults(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;
sprintf(path, "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
GfParmListClean(results, path);
GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, car->_laps - 1);
for (i = 0; i < s->_ncars; i++) {
sprintf(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);
sprintf(buf, "cars/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam);
GfParmReleaseHandle(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
GfParmSetNum(results, path, RE_ATTR_INDEX, NULL, car->index);
GfParmSetNum(results, path, RE_ATTR_LAPS, NULL, car->_laps - 1);
GfParmSetNum(results, path, RE_ATTR_TIME, NULL, car->_curTime);
GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, car->_bestLapTime);
GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, car->_topSpeed);
GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, car->_dammage);
GfParmSetNum(results, path, RE_ATTR_NB_PIT_STOPS, NULL, car->_nbPitStops);
GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName);
GfParmSetNum(results, path, RE_ATTR_IDX, NULL, car->_driverIndex);
sprintf(path2, "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
GfParmSetNum(results, path, RE_ATTR_POINTS, NULL,
(int)GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0));
}
break;
case RM_TYPE_PRACTICE:
car = s->cars[0];
sprintf(path, "%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race);
GfParmSetStr(results, path, RM_ATTR_DRVNAME, car->_name);
break;
case RM_TYPE_QUALIF:
car = s->cars[0];
sprintf(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--) {
sprintf(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 */
sprintf(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));
sprintf(path, "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
GfParmSetNum(results, path2, RE_ATTR_POINTS, NULL,
(int)GfParmGetNum(params, path, RE_ATTR_POINTS, NULL, 0));
} else {
break;
}
}
/* insert after */
sprintf(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);
sprintf(buf, "cars/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam);
GfParmReleaseHandle(carparam);
GfParmSetStr(results, path, RE_ATTR_CAR, carName);
GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, car->_bestLapTime);
GfParmSetStr(results, path, RE_ATTR_MODULE, car->_modName);
GfParmSetNum(results, path, RE_ATTR_IDX, NULL, car->_driverIndex);
sprintf(path2, "%s/%s/%d", race, RM_SECT_POINTS, i + 1);
GfParmSetNum(results, path, RE_ATTR_POINTS, NULL,
(int)GfParmGetNum(params, path2, RE_ATTR_POINTS, NULL, 0));
break;
}
}
void
ReUpdateQualifCurRes(tCarElt *car)
{
int i;
int nCars;
int printed;
int maxLines;
void *carparam;
char *carName;
char *race = ReInfo->_reRaceName;
void *results = ReInfo->results;
ReResEraseScreen();
maxLines = ReResGetLines();
sprintf(buf, "%s on %s - Lap %d", car->_name, ReInfo->track->name, car->_laps);
ReResScreenSetTitle(buf);
sprintf(buf, "cars/%s/%s.xml", car->_carName, car->_carName);
carparam = GfParmReadFile(buf, GFPARM_RMODE_STD);
carName = GfParmGetName(carparam);
GfParmReleaseHandle(carparam);
printed = 0;
sprintf(path, "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK);
nCars = GfParmGetEltNb(results, path);
nCars = MIN(nCars + 1, maxLines);
for (i = 1; i < nCars; i++) {
sprintf(path, "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, race, RE_SECT_RANK, i);
if (!printed) {
if ((car->_bestLapTime != 0.0) && (car->_bestLapTime < GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0))) {
sprintf(buf, "%d - %s - %s (%s)", i, GfTime2Str(car->_bestLapTime, 0), car->_name, carName);
ReResScreenSetText(buf, i - 1, 1);
printed = 1;
}
}
sprintf(buf, "%d - %s - %s (%s)", i + printed, GfTime2Str(GfParmGetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, 0), 0),
GfParmGetStr(results, path, RE_ATTR_NAME, ""), GfParmGetStr(results, path, RE_ATTR_CAR, ""));
ReResScreenSetText(buf, i - 1 + printed, 0);
}
if (!printed) {
sprintf(buf, "%d - %s - %s (%s)", i, GfTime2Str(car->_bestLapTime, 0), car->_name, carName);
ReResScreenSetText(buf, i - 1, 1);
}
ReInfo->_refreshDisplay = 1;
}
void
ReSavePracticeLap(tCarElt *car)
{
void *results = ReInfo->results;
tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]);
sprintf(path, "%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, car->_laps - 1);
GfParmSetNum(results, path, RE_ATTR_TIME, NULL, car->_lastLapTime);
GfParmSetNum(results, path, RE_ATTR_BEST_LAP_TIME, NULL, car->_bestLapTime);
GfParmSetNum(results, path, RE_ATTR_TOP_SPEED, NULL, info->topSpd);
GfParmSetNum(results, path, RE_ATTR_BOT_SPEED, NULL, info->botSpd);
GfParmSetNum(results, path, RE_ATTR_DAMMAGES, NULL, car->_dammage);
}
int
ReDisplayResults(void)
{
void *params = ReInfo->params;
if ((!strcmp(GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_DISPRES, RM_VAL_YES), RM_VAL_YES)) ||
(ReInfo->_displayMode == RM_DISP_MODE_NORMAL)) {
RmShowResults(ReInfo->_reGameScreen, ReInfo);
} else {
ReResShowCont();
}
return RM_ASYNC | RM_NEXT_STEP;
}
void
ReDisplayStandings(void)
{
RmShowStandings(ReInfo->_reGameScreen, ReInfo);
}