Let XBoard propose name of tourney file
authorH.G. Muller <h.g.muller@hccnet.nl>
Wed, 8 Jun 2011 14:44:16 +0000 (16:44 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Wed, 8 Jun 2011 16:09:14 +0000 (18:09 +0200)
Add an option -defaultTourneyName to configure the name that will be
proposed in the Tournament Options dialog's tournament-file field. The
option can contain %y, %M, %d, %h, %m, %s for year, month, day, hour,
mintes, seconds of the curret time in %02d format, or %Y for the year in
%04d format. Any tournament -file name is ignored when no participants
are given. Participants without a tourney file remains an error.

args.h
backend.c
backend.h
common.h
winboard/wsettings.c
xboard.conf.in
xoptions.c

diff --git a/args.h b/args.h
index faaf63f..b3776ee 100644 (file)
--- a/args.h
+++ b/args.h
@@ -622,6 +622,7 @@ ArgDescriptor argDescriptors[] = {
   { "sn", ArgString, (void *) &appData.pgnName[1], FALSE, INVALID },
   { "absoluteAnalysisScores", ArgBoolean, (void *) &appData.whitePOV, TRUE, FALSE },
   { "pairingEngine", ArgFilename, (void *) &appData.pairingEngine, TRUE, "" },
+  { "defaultTourneyName", ArgFilename, (void *) &appData.defName, TRUE, "" },
 
 #if ZIPPY
   { "zippyTalk", ArgBoolean, (void *) &appData.zippyTalk, FALSE, (ArgIniType) ZIPPY_TALK },
index 51f348e..c73d6e7 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -9553,6 +9553,35 @@ TwoMachinesEventIfReady P((void))
   TwoMachinesEvent();
 }
 
+char *
+MakeName(char *template)
+{
+    time_t clock;
+    struct tm *tm;
+    static char buf[MSG_SIZ];
+    char *p = buf;
+    int i;
+
+    clock = time((time_t *)NULL);
+    tm = localtime(&clock);
+
+    while(*p++ = *template++) if(p[-1] == '%') {
+       switch(*template++) {
+         case 0:   *p = 0; return buf;
+         case 'Y': i = tm->tm_year+1900; break;
+         case 'y': i = tm->tm_year-100; break;
+         case 'M': i = tm->tm_mon+1; break;
+         case 'd': i = tm->tm_mday; break;
+         case 'h': i = tm->tm_hour; break;
+         case 'm': i = tm->tm_min; break;
+         case 's': i = tm->tm_sec; break;
+         default:  i = 0;
+       }
+       snprintf(p-1, MSG_SIZ-10 - (p - buf), "%02d", i); p += strlen(p);
+    }
+    return buf;
+}
+
 int
 CountPlayers(char *p)
 {
@@ -9596,17 +9625,21 @@ CreateTourney(char *name)
 {
        FILE *f;
        if(name[0] == NULLCHAR) {
-           DisplayError(_("You must supply a tournament file,\nfor storing the tourney progress"), 0);
+           if(appData.participants[0])
+               DisplayError(_("You must supply a tournament file,\nfor storing the tourney progress"), 0);
            return 0;
        }
-       f = fopen(appData.tourneyFile, "r");
+       f = fopen(name, "r");
        if(f) { // file exists
+           ASSIGN(appData.tourneyFile, name);
            ParseArgsFromFile(f); // parse it
        } else {
-           if(CountPlayers(appData.participants) < appData.tourneyType + (!appData.tourneyType) + 1) {
+           if(!appData.participants[0]) return 0; // ignore tourney file if non-existing & no participants
+           if(CountPlayers(appData.participants) < (appData.tourneyType>0 ? appData.tourneyType+1 : 2)) {
                DisplayError(_("Not enough participants"), 0);
                return 0;
            }
+           ASSIGN(appData.tourneyFile, name);
            if((f = WriteTourneyFile("")) == NULL) return 0;
        }
        fclose(f);
index ebcc74f..c4b6bb2 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -296,6 +296,7 @@ void GLT_TagsToList P(( char * tags ));
 void GLT_ParseList P((void));
 void NamesToList P((char *name, char **engines, char **mnemonics));
 int CreateTourney P((char *name));
+char *MakeName P((char *templ));
 void SwapEngines P((int n));
 
 extern char* StripHighlight P((char *));  /* returns static data */
index c52cd9f..ad52fb9 100644 (file)
--- a/common.h
+++ b/common.h
@@ -650,6 +650,7 @@ typedef struct {
     Boolean whitePOV;
 
     char *tourneyFile;
+    char *defName;
     char *processes;
     char *results;
     char *participants;
index 023eb2d..84c02cb 100644 (file)
@@ -362,7 +362,7 @@ GetOptionValues(HWND hDlg, ChessProgramState *cps, Option *optionList)
                if(cps) len = MSG_SIZ - strlen(optionList[j].name) - 9, text = newText;\r
                else    len = GetWindowTextLength(GetDlgItem(hDlg, 2001+2*i)) + 1, text = (char*) malloc(len);\r
                success = GetDlgItemText( hDlg, 2001+2*i, text, len );\r
-               if(!success) break;\r
+               if(!success) text[0] = NULLCHAR; // empty string can be valid input\r
                if(!cps) {\r
                    char *p;\r
                    p = (optionList[j].type != FileName ? strdup(text) : InterpretFileName(text, homeDir)); // all files relative to homeDir!\r
@@ -687,17 +687,18 @@ void LoadEnginePopUp(HWND hwnd)
 }\r
 \r
 Boolean autoinc, twice, swiss;\r
+char *tfName;\r
 \r
 int MatchOK()\r
 {\r
     if(autoinc) appData.loadGameIndex = appData.loadPositionIndex = -(twice + 1);\r
     if(swiss) { appData.defaultMatchGames = 1; appData.tourneyType = -1; }\r
-    if(CreateTourney(appData.tourneyFile)) MatchEvent(2); else return 0;\r
+    if(CreateTourney(tfName)) MatchEvent(2); else return !appData.participants[0];\r
     return 1;\r
 }\r
 \r
 Option tourneyOptions[] = {\r
-  { 0,  0,          4, NULL, (void*) &appData.tourneyFile, "", NULL, FileName, N_("Tournament file:") },\r
+  { 0,  0,          4, NULL, (void*) &tfName, "", NULL, FileName, N_("Tournament file:") },\r
   { 30, 0,          0, NULL, NULL, NULL, NULL, Label, N_("If you specify an existing file, the rest of this dialog will be ignored.") },\r
   { 30, 0,          0, NULL, NULL, NULL, NULL, Label, N_("Otherwise, the file will be created, with the settings you specify below:") },\r
   { 0,  1,          0, NULL, (void*) &engineChoice, (char*) (engineMnemonic+1), (engineMnemonic+1), ComboBox, N_("Select Engine:") },\r
@@ -742,7 +743,7 @@ void TourneyPopup(HWND hwnd)
     twice = TRUE; swiss = appData.tourneyType < 0;\r
     while(engineList[n]) n++; tourneyOptions[3].max = n-1;\r
     snprintf(title, MSG_SIZ, _("Tournament and Match Options"));\r
-    if(appData.pairingEngine[0]) tourneyOptions[5].min = -19;\r
+    ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));\r
 \r
     GenericPopup(hwnd, tourneyOptions);\r
 }\r
index edd1cf9..63f56c9 100644 (file)
@@ -48,6 +48,7 @@
 -msLoginDelay 0
 -delayBeforeQuit 0
 -delayAfterQuit 0
+-defaultTourneyName "Tourney_%y%M%d_%h%m.trn"
 ;
 ; PGN format & Game List
 ;
index b47f9a4..f3e8f67 100644 (file)
@@ -780,7 +780,7 @@ void GenericPopDown(w, event, prms, nprms)
     PopDown(prms[0][0] - '0');
 }
 
-char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params;
+char *engineName, *engineDir, *engineChoice, *engineLine, *nickName, *params, *tfName;
 Boolean isUCI, hasBook, storeVariant, v1, addToList, useNick;
 extern Option installOptions[], matchOptions[];
 char *engineNr[] = { N_("First Engine"), N_("Second Engine"), NULL };
@@ -803,14 +803,14 @@ int MatchOK(int n)
 {
     if(appData.participants && appData.participants[0]) free(appData.participants);
     appData.participants = strdup(engineName);
-    if(!CreateTourney(appData.tourneyFile)) return 0;
+    if(!CreateTourney(tfName)) return !appData.participants[0];
     PopDown(0); // early popdown to prevent FreezeUI called through MatchEvent from causing XtGrab warning
     MatchEvent(2); // start tourney
     return 1;
 }
 
 Option matchOptions[] = {
-{ 0,  0,          0, NULL, (void*) &appData.tourneyFile, ".trn", NULL, FileName, N_("Tournament file:") },
+{ 0,  0,          0, NULL, (void*) &tfName, ".trn", NULL, FileName, N_("Tournament file:") },
 { 0,  0,          0, NULL, (void*) &appData.roundSync, "", NULL, CheckBox, N_("Sync after round    (for concurrent playing of a single") },
 { 0,  0,          0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle      tourney with multiple XBoards)") },
 { 0xD, 150,       0, NULL, (void*) &engineName, "", NULL, TextBox, "Tourney participants:" },
@@ -1771,6 +1771,7 @@ void MatchOptionsProc(w, event, prms, nprms)
    NamesToList(firstChessProgramNames, engineList, engineMnemonic);
    comboCallback = &AddToTourney;
    matchOptions[5].min = -(appData.pairingEngine[0] != NULLCHAR); // with pairing engine, allow Swiss
+   ASSIGN(tfName, appData.tourneyFile[0] ? appData.tourneyFile : MakeName(appData.defName));
    GenericPopUp(matchOptions, _("Match Options"), 0);
 }