2
#include "components.h"
5
XtResource Score::resources[] = {
6
{ "scoreTitle", "ScoreTitle", XtRString, sizeof(char *),
7
0*sizeof(char *), XtRString, (XtPointer)"XShisen High Score\n\n" },
8
{ "scoreFormat", "ScoreFormat", XtRString, sizeof(char *),
9
1*sizeof(char *), XtRString, (XtPointer)"%2d %2.2d:%2.2d:%2.2d %-28s %s %s\n" },
10
{ "strPeriod", "StrPeriod", XtRString, sizeof(char *),
11
2*sizeof(char *), XtRString, (XtPointer)"Last %d days" },
12
{ "averagePeriod", "AveragePeriod", XtRString, sizeof(char *),
13
3*sizeof(char *), XtRString, (XtPointer)"14" },
14
{ "strPlayed", "StrPlayed", XtRString, sizeof(char *),
15
4*sizeof(char *), XtRString, (XtPointer)"Played" },
16
{ "strCompleted", "StrCompleted", XtRString, sizeof(char *),
17
5*sizeof(char *), XtRString, (XtPointer)"Completed" },
18
{ "strTedumari", "StrTedumari", XtRString, sizeof(char *),
19
6*sizeof(char *), XtRString, (XtPointer)"Deadlocked" },
20
{ "strSearched", "StrSearched", XtRString, sizeof(char *),
21
7*sizeof(char *), XtRString, (XtPointer)"Search used" },
22
{ "strGiveUp", "StrGiveUp", XtRString, sizeof(char *),
23
8*sizeof(char *), XtRString, (XtPointer)"Given up" },
24
{ "strTotal", "StrTotal", XtRString, sizeof(char *),
25
9*sizeof(char *), XtRString, (XtPointer)"Total" },
26
{ "strAverage", "StrAverage", XtRString, sizeof(char *),
27
10*sizeof(char *), XtRString, (XtPointer)"Whole Average" },
28
{ "strGames", "StrGames", XtRString, sizeof(char *),
29
11*sizeof(char *), XtRString, (XtPointer)"games" },
30
{ "personalTitle", "PersonalTitle", XtRString, sizeof(char *),
31
12*sizeof(char *), XtRString, (XtPointer)"Personal Statistics for %s" }
35
ScoreRecord::SetDefault(void)
41
strcpy(date, "00-00-00");
42
strcpy(time, "00:00:00");
46
ScoreRecord::ReadField(FILE *fp, int kanjiCode, int &offset)
50
if (fread((void*)buffer, sizeof(char), 64, fp) != 64 ||
55
for(int i=0; i<64; i++) {
56
buffer[i] = ((buffer[i] - offset - i) & 0xff);
59
strncpy(name, buffer, 28);
63
strcpy(name, sjis_to_euc(name));
66
strcpy(name, sjis_to_jis(name));
69
hour = atoi(&buffer[35]);
70
min = atoi(&buffer[38]);
71
sec = atoi(&buffer[41]);
72
strncpy(date, &buffer[44], 8);
74
strncpy(time, &buffer[53], 8);
77
for(int i=1; i<8; i++) {
80
date[7] = date[6] == '0' ? '1' : '0';
85
ScoreRecord::WriteField(FILE *fp, int kanjiCode, int &cr_offset, int cr)
91
strcpy(buffer, euc_to_sjis(name));
94
strcpy(buffer, jis_to_sjis(name));
101
strncpy(&buffer[29], "X" XSHISEN_VERSION, 5);
103
sprintf(&buffer[35], "%2.2d:%2.2d:%2.2d", hour, min, sec);
105
strncpy(&buffer[44], date, 8);
107
strncpy(&buffer[53], time, 8);
112
for(int i=0; i<64; i++) {
113
buffer[i] = ((buffer[i] + cr_offset + i) & 0xff);
117
fwrite((void*)buffer, sizeof(char), 64, fp);
121
Score::retry_button(Widget w, XtPointer client_data)
123
Score *p = (Score *)client_data;
126
#else /* USE_MOTIF */
127
XtPopdown(p->mdialog);
128
#endif /* USE_MOTIF */
133
Score::abandon_button(Widget w, XtPointer client_data)
135
Score *p = (Score *)client_data;
138
#else /* USE_MOTIF */
139
XtPopdown(p->mdialog);
140
#endif /* USE_MOTIF */
141
p->DisplayScore(p->game);
148
if (!mdialog_exist) {
149
mdialog = XmCreateWarningDialog(toplevel, "mdialog", NULL, 0);
150
XtAddCallback(mdialog, XmNokCallback,
151
(XtCallbackProc)retry_button,
153
XtAddCallback(mdialog, XmNcancelCallback,
154
(XtCallbackProc)abandon_button,
157
XtUnmanageChild(XmMessageBoxGetChild(mdialog, XmDIALOG_HELP_BUTTON));
159
XtManageChild(mdialog);
160
#else /* USE_MOTIF */
161
if (!mdialog_exist) {
162
Widget form, label, b1, b2;
164
XtVaGetValues(toplevel, XtNx, &x, XtNy, &y, NULL);
165
mdialog = XtVaCreatePopupShell("mdialog_popup", transientShellWidgetClass,
170
form = XtVaCreateManagedWidget("mdialog", formWidgetClass, mdialog,
172
label = XtVaCreateManagedWidget("label", labelWidgetClass, form,
175
b1 = XtVaCreateManagedWidget("ok_button", commandWidgetClass, form,
178
b2 = XtVaCreateManagedWidget("cancel_button", commandWidgetClass, form,
182
XtAddCallback(b1, XtNcallback,
183
(XtCallbackProc)retry_button,
185
XtAddCallback(b2, XtNcallback,
186
(XtCallbackProc)abandon_button,
190
XtPopup(mdialog, XtGrabNone);
191
#endif /* USE_MOTIF */
195
Score::readfile(void)
197
FILE *fp = fopen(filename, "r");
201
for(int i=0; i<SCORENUM; i++) {
206
if (fseek(fp, 1344*game+704, SEEK_SET) != 0)
207
fseek(fp, 0, SEEK_END);
209
for(int i=0; i<SCORENUM; i++){
210
rec[i].ReadField(fp, kanjiCode, offset);
216
Score::writefile(void)
218
static const char filler[] = "\032"
220
FILE *fp = fopen(filename, "r+");
229
fseek(fp, 1344*game, SEEK_SET);
230
for(i=0; i<SCORENUM; i++) {
231
rec[i].WriteField(fp, kanjiCode, offset);
233
fwrite((void*)filler, sizeof(filler)-1, 1, fp);
234
for(i=0; i<SCORENUM; i++) {
235
rec[i].WriteField(fp, kanjiCode, offset, 1);
238
return 0; // no problem
241
Score::Score(Widget parent)
244
score = XmCreateMessageDialog(parent, "score", NULL, 0);
245
XtAddCallback(score, XmNokCallback, (XtCallbackProc)PopDownCB, NULL);
246
XtUnmanageChild(XmMessageBoxGetChild(score, XmDIALOG_CANCEL_BUTTON));
247
XtUnmanageChild(XmMessageBoxGetChild(score, XmDIALOG_HELP_BUTTON));
248
#else /* USE_MOTIF */
249
Widget form, label, button;
250
score = XtVaCreatePopupShell("score", transientShellWidgetClass, parent,
251
XtNallowShellResize, True,
253
form = XtVaCreateManagedWidget("mf", formWidgetClass, score,
255
label = XtVaCreateManagedWidget("label", labelWidgetClass, form,
258
XtNbottom, XawChainBottom,
262
button = XtVaCreateManagedWidget("ok_button", commandWidgetClass, form,
265
XtNbottom, XawChainTop,
266
XtNleft, XawChainLeft,
267
XtNright, XawChainLeft,
270
XtAddCallback(button, XtNcallback, (XtCallbackProc)PopDownCB, (XtPointer)score);
271
#endif /* USE_MOTIF */
277
Score::Popup(String str)
280
XmString mstr = XmStringCreateLtoR(str, XmFONTLIST_DEFAULT_TAG);
282
XmNmessageString, mstr,
285
XtManageChild(score);
286
#else /* USE_MOTIF */
287
XtVaSetValues(XtNameToWidget(score, "*label"),
290
XtPopup(score, XtGrabNone);
291
#endif /* USE_MOTIF */
295
Score::SetScoreFile(const char *scorefile, const char *kcode, const char *personal)
299
filename = strdup(scorefile);
300
home = getenv("HOME");
303
logfile = new char[strlen(home)+strlen(personal)+2];
304
sprintf(logfile, "%s/%s", home, personal);
306
if (strcasecmp(kcode, "euc") == 0)
308
else if (strcasecmp(kcode, "jis") == 0)
315
Score::do_first_call(void)
317
XtVaGetApplicationResources(score, (XtPointer)res_strings,
318
resources, XtNumber(resources), NULL);
322
XtVaGetValues(toplevel, XtNx, &x, XtNy, &y, NULL);
323
XtVaSetValues(score, XtNx, x+10, XtNy, y+10, NULL);
324
#endif /* !USE_MOTIF */
328
Score::DisplayScore(int kind_of_game)
330
char format[SCORENUM*80+20], buff[SCORENUM*80];
331
long prev_time, this_time;
338
// Always read the latest high score
340
sprintf(format, res_strings[0]);
342
for(int i=0; i<SCORENUM; i++) {
343
this_time = rec[i].hour * 3600 + rec[i].min * 60 + rec[i].sec;
344
if (this_time == prev_time)
348
prev_time = this_time;
349
sprintf(buff, res_strings[1], i+1-num, rec[i].hour, rec[i].min, rec[i].sec,
350
rec[i].name, rec[i].date, rec[i].time);
351
strcat(format, buff);
356
// Convert milisecond data into hour:minute:second
358
Score::ms_to_hms(int ms, unsigned char &h, unsigned char &m, unsigned char &s)
365
// Call Score::SetScore formerly!
367
Score::Register(void)
369
unsigned char m, s, h;
375
char namebuf[128], myname[NAMELEN+1], gecos[128], *po;
377
s1 = scoreToRegister / 1000;
378
ms_to_hms(scoreToRegister, h, m, s);
379
pw = getpwuid(getuid());
380
strcpy(gecos, pw->pw_gecos);
381
if ((po = strchr(gecos, ',')) != NULL)
383
sprintf(namebuf, "%-8.8s (%s)", pw->pw_name, gecos);
384
sprintf(myname, "%-28.28s", namebuf);
385
// Always read the latest high score
388
// Get my best score in past
391
for(i=0; i<SCORENUM; i++) {
392
if (strcmp(myname, rec[i].name) == 0) {
397
#endif /* !ALLOW_DUPSCORE */
399
// Check if this score values as high score
401
for(i=0; i<SCORENUM; i++) {
402
int sx = rec[i].hour * 3600 + rec[i].min * 60 + rec[i].sec;
408
if (inspos == SCORENUM || mybest < inspos) {
409
return; // Not high score!
412
for(i=mybest; i>inspos; i--) {
413
if (i>=SCORENUM) continue;
417
rec[inspos].hour = h;
420
strcpy(rec[inspos].name, myname);
423
sprintf(rec[i].date, "%2.2d-%2.2d-%2.2d", tp->tm_year%100, tp->tm_mon+1, tp->tm_mday);
424
sprintf(rec[i].time, "%2.2d:%2.2d:%2.2d", tp->tm_hour, tp->tm_min, tp->tm_sec);
425
if (writefile() == 0)
430
Score::LogRecord(int flag, int result, int gamesize, int level, int rest)
431
// flag: 0=giveup 1=finished 2=finish+help 3=tedumari
438
stream = fopen(logfile, "a");
440
return; /* Just do not record, no notifying */
443
check_digit = flag*3 + gamesize + level*7 + (tp->tm_year%100)*3 + rest*7
444
+ tp->tm_mon*7 + tp->tm_mday*3 + tp->tm_hour*7 + tp->tm_min*3 + tp->tm_sec;
446
fprintf(stream, "%2.2d%2.2d%8.8d%2.2d%1.1d%2.2d%4.4d%2.2d%3.3d%3.3d%2.2d%2.2d\n",
448
tp->tm_sec, result, tp->tm_min, gamesize, tp->tm_year%100, level, tp->tm_mon,
449
check_digit, rest, tp->tm_mday, tp->tm_hour);
454
Score::PersonalStat(int kind_of_game)
457
char buf[4096], *bufp, xb[128];
458
char scorebuf[SCORENUM*2+1][128];
459
int sec, min, hour, day, month, year;
460
int g, f, c1, c2, l, t;
462
int w1[2][4], w2[2][4], w3[2][4]; // for average
465
unsigned char t1, t2, t3;
470
time(&tm2); // Time of now
474
tm2 -= 86400 * atoi(res_strings[3]);
475
s = fopen(logfile, "r");
478
for(i=0; i<SCORENUM*2; i++)
479
strcpy(scorebuf[i], "99:99:99 ( 0) [00-00-00 00:00:00]");
480
memset(w1, 0, 2*4*sizeof(int));
481
memset(w2, 0, 2*4*sizeof(int));
482
memset(w3, 0, 2*4*sizeof(int));
483
while(fgets(buf, 128, s) != NULL) {
484
switch(strlen(buf)) {
486
// Just for compatibility with xshisen 1.10
487
f = atoiSubstring(buf + 0, 2);
488
sec = atoiSubstring(buf + 2, 2);
489
t = atoiSubstring(buf + 4, 8);
490
min = atoiSubstring(buf + 12, 2);
491
g = atoiSubstring(buf + 14, 1);
492
year = atoiSubstring(buf + 15, 2);
493
l = atoiSubstring(buf + 17, 4);
494
month = atoiSubstring(buf + 21, 2);
495
c1 = atoiSubstring(buf + 23, 3);
496
day = atoiSubstring(buf + 26, 2);
497
hour = atoiSubstring(buf + 28, 2);
499
c2 = f*3 + g + l*7 + year*3 + month*7 + day*3 + hour*7 + min*3 + sec;
502
// Just for compatibility with xshisen 1.10, Y2K
503
f = atoiSubstring(buf + 0, 2);
504
sec = atoiSubstring(buf + 2, 2);
505
t = atoiSubstring(buf + 4, 8);
506
min = atoiSubstring(buf + 12, 2);
507
g = atoiSubstring(buf + 14, 1);
508
year = atoiSubstring(buf + 15, 3) - 100;
509
l = atoiSubstring(buf + 18, 4);
510
month = atoiSubstring(buf + 22, 2);
511
c1 = atoiSubstring(buf + 24, 3);
512
day = atoiSubstring(buf + 27, 2);
513
hour = atoiSubstring(buf + 29, 2);
515
c2 = f*3 + g + l*7 + (year+100)*3 + month*7 + day*3 + hour*7 + min*3 + sec
519
// This is usual format
520
f = atoiSubstring(buf + 0, 2);
521
sec = atoiSubstring(buf + 2, 2);
522
t = atoiSubstring(buf + 4, 8);
523
min = atoiSubstring(buf + 12, 2);
524
g = atoiSubstring(buf + 14, 1);
525
year = atoiSubstring(buf + 15, 2);
526
l = atoiSubstring(buf + 17, 4);
527
month = atoiSubstring(buf + 21, 2);
528
c1 = atoiSubstring(buf + 23, 3);
529
rest = atoiSubstring(buf + 26, 3);
530
day = atoiSubstring(buf + 29, 2);
531
hour = atoiSubstring(buf + 31, 2);
532
c2 = f*3 + g + l*7 + year*3 + month*7 + day*3 + hour*7 + min*3
536
// This is usual format, Y2K
537
f = atoiSubstring(buf + 0, 2);
538
sec = atoiSubstring(buf + 2, 2);
539
t = atoiSubstring(buf + 4, 8);
540
min = atoiSubstring(buf + 12, 2);
541
g = atoiSubstring(buf + 14, 1);
542
year = atoiSubstring(buf + 15, 3) - 100;
543
l = atoiSubstring(buf + 18, 4);
544
month = atoiSubstring(buf + 22, 2);
545
c1 = atoiSubstring(buf + 24, 3);
546
rest = atoiSubstring(buf + 27, 3);
547
day = atoiSubstring(buf + 30, 2);
548
hour = atoiSubstring(buf + 32, 2);
549
c2 = f*3 + g + l*7 + (year+100)*3 + month*7 + day*3 + hour*7 + min*3
553
// Someone edited this file?
557
if (c1 != c2 || g != game)
558
continue; // Check digit was incorrect, or other game size
560
continue; // Invalid value
562
ms_to_hms(t, t1, t2, t3);
563
if (f == 1) { // Only completed game can be included
564
sprintf(scorebuf[SCORENUM*2],
565
"%2.2d:%2.2d:%2.2d (%3d) [%2.2d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d]",
566
t1, t2, t3, l, year, month+1, day, hour, min, sec);
567
for(i=SCORENUM*2; i>0 && strcmp(scorebuf[i-1],scorebuf[i])>0; i--) {
569
strcpy(p, scorebuf[i-1]);
570
strcpy(scorebuf[i-1], scorebuf[i]);
571
strcpy(scorebuf[i], p);
580
tb.tm_year = year > 69 ? year : year + 100;
581
tm1 = mktime(&tb); // Time of the score
585
if (tm1 >= tm2) { // if the time of the score is newer than specified days ago
594
pw = getpwuid(getuid());
595
sprintf(bufp, res_strings[12], pw->pw_name);
596
bufp += strlen(bufp);
597
for(i=0; i<SCORENUM; i++) {
598
sprintf(bufp, "%2d ", i+1);
600
strcpy(bufp, scorebuf[i]);
601
bufp += strlen(bufp);
602
sprintf(bufp, " %2d ", SCORENUM+i+1);
604
strcpy(bufp, scorebuf[SCORENUM+i]);
605
bufp += strlen(bufp);
609
*bufp = '\n'; bufp++;
610
*bufp = '\n'; bufp++;
611
sprintf(xb, res_strings[2], atoi(res_strings[3]));
612
strcpy(bufp, makeStatistics(xb, w1[1], w2[1], w3[1]));
613
bufp += strlen(bufp);
614
strcpy(bufp, makeStatistics(res_strings[9], w1[0], w2[0], w3[0]));
615
bufp += strlen(bufp);
621
Score::atoiSubstring(const char *str, int length)
624
strncpy(b, str, length);
630
*Score::makeStatistics(const char *title, int rtime[], int rcount[], int rlev[])
634
unsigned char t1, t2, t3;
635
static char b[1024], *bp;
638
x = rcount[0] + rcount[1] + rcount[2] + rcount[3];
639
sprintf(bp, "%-20.20s: %6d %s\n", title, x, res_strings[11]);
642
x = rtime[1] / rcount[1];
643
y = (double)rlev[1] / (double)rcount[1];
644
ms_to_hms(x, t1, t2, t3);
646
sprintf(bp, " %-14.14s: %2.2d:%2.2d:%2.2d (%4.1f) %6d %s\n",
647
res_strings[5], t1, t2, t3, y, rcount[1], res_strings[11]);
651
x = rtime[3] / rcount[3];
652
y = (double)rlev[3] / (double)rcount[3];
653
ms_to_hms(x, t1, t2, t3);
655
sprintf(bp, " %-14.14s: %2.2d:%2.2d:%2.2d (%4.1f) %6d %s\n",
656
res_strings[6], t1, t2, t3, y, rcount[3], res_strings[11]);
660
x = rtime[2] / rcount[2];
661
y = (double)rlev[2] / (double)rcount[2];
662
ms_to_hms(x, t1, t2, t3);
664
sprintf(bp, " %-14.14s: %2.2d:%2.2d:%2.2d (%4.1f) %6d %s\n",
665
res_strings[7], t1, t2, t3, y, rcount[2], res_strings[11]);
669
x = rtime[0] / rcount[0];
670
y = (double)rlev[0] / (double)rcount[0];
671
ms_to_hms(x, t1, t2, t3);
673
sprintf(bp, " %-14.14s: %2.2d:%2.2d:%2.2d (%4.1f) %6d %s\n",
674
res_strings[8], t1, t2, t3, y, rcount[0], res_strings[11]);