/* Contest Arbitrator v0.3.2 by Dmitry Gorokh, UR4MCK
This program is FREEWARE!
Changelog:
15.12.2014: Fixed bug with gmtime() in report_ubn()
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "config.h"
#include "main.h"
#include "report.h"
#include "contests/wakeup.h"
#define SPACES " " /* 16 spaces for proper output formating */
char *report_name(char *report_path, const char *path, const CONFIG_S *config) {
/* Return complete report file name (with path) */
char tmp[MAX_STR], *s, *slash, *dot;
DEBUG("==> report_name('%s', '%s', %p)\n", report_path, path, config);
if (!report_path || !path || !config) return NULL;
/* Step down to the end of path and note appearence of slashes & dots */
strcpy(tmp, path);
slash = dot = NULL;
s = tmp;
while (*s != '\0') {
if (*s == '/' || *s == '\\') slash = s;
else if (*s == '.') dot = s;
s++;
}
/* Get pure name */
if (dot) *dot = '\0';
if (slash) s = slash + 1; else s = (char*)path;
/* Check report directory */
if (!config->report_dir || (config->report_dir && config->report_dir[0] == '\0')) slash = ".";
else slash = (char*)(config->report_dir);
/* Construct full path to report file */
sprintf(report_path, "%s/%s.txt", slash, s);
DEBUG("<== report_name('%s', '%s', %p)\n", report_path, path, config);
return report_path;
}
void report_add(FILE *fd, const char *fmt, ...) {
/* Write to report file */
va_list ap;
char s[MAX_STR];
if (fd) {
va_start(ap, fmt);
vsnprintf(s, MAX_STR, fmt, ap);
va_end(ap);
fwrite(s, 1, strlen(s), fd);
}
}
void report_ubn(BASE_S *base, CONFIG_S *config) {
/* Update all UBN files and include post contest evaluation info */
unsigned int i, num;
int j, k;
char num_spaces[7], mode_spaces[6], band_spaces[6], callsign_spaces[15], sent_spaces[14], recv_spaces[14];
char score_spaces[9], qso_num[7], date[11], time[6], *mode, *band, sent[32], recv[32], score[9], remarks[MAX_STR];
char msg[5][64], *s, *d;
HAM_S *ham;
QSO_S *qso;
FILE *ubn_fd;
struct tm gmt;
DEBUG("==> report_ubn(%p, %p)\n", base, config);
for (i = 0; i < base->ham_num; i++) {
ham = base->ham[i];
if (ham->ubn_file[0] != '\0') {
if (!(ubn_fd = fopen(ham->ubn_file, "a"))) out(NULL, "WARNING: Unable to open UBN file: %s\n", ham->ubn_file);
else {
/* Make table with each QSO information */
report_add(ubn_fd, " ***** QSO STATISTICS *****\n\n");
/* Ham's properties */
report_add(ubn_fd, "Callsign: %s\n", ham->callsign);
if (ham->optype_id) report_add(ubn_fd, "Operation type : %s\n", get_optype(ham->optype_id));
if (ham->band_id) report_add(ubn_fd, "Operating bands: %s\n", get_band(ham->band_id));
if (ham->mode_id) report_add(ubn_fd, "Operating modes: %s\n", get_mode(ham->mode_id));
/* Header */
report_add(ubn_fd, "+-------+----------+-------+------+------+---------------+-------------+-------------+---------+------+-------------\n");
report_add(ubn_fd, "| QSO # | Date | Time | Mode | Band | CALL | Sent | Rcvd | Score | Mult | REMARKS \n");
report_add(ubn_fd, "| | | | | | | | | | | \n");
report_add(ubn_fd, "+-------+----------+-------+------+------+---------------+-------------+-------------+---------+------+-------------\n");
/* QSO information */
num = 1;
qso = ham->qso;
while (qso) {
/* Format QSO number */
sprintf(qso_num, "%u", num++);
if ((j = 6 - strlen(qso_num)) < 0) j = 0; else strncpy(num_spaces, SPACES, j);
num_spaces[j] = '\0';
/* Format date & time */
gmtime_r(&(qso->timestamp), &gmt);
strftime(date, sizeof(date), "%d.%m.%Y", &gmt);
strftime(time, sizeof(time), "%H:%M", &gmt);
/* Calculate mode_spaces */
mode = get_qso_mode(qso->mode_op);
if ((j = 5 - strlen(mode)) < 0) j = 0; else strncpy(mode_spaces, SPACES, j);
mode_spaces[j] = '\0';
/* Calculate band_spaces */
band = get_band(get_band_id(qso->freq));
if ((j = 5 - strlen(band)) < 0) j = 0; else strncpy(band_spaces, SPACES, j);
band_spaces[j] = '\0';
/* Calculate callsign_spaces */
if ((j = 14 - strlen(qso->callsign)) < 0) j = 0; else strncpy(callsign_spaces, SPACES, j);
callsign_spaces[j] = '\0';
/* Format sent & received info */
sprintf(sent, "%s %s %s", qso->check_sent[0], qso->check_sent[1] , qso->check_sent[2]);
sprintf(recv, "%s %s %s", qso->check_recv[0], qso->check_recv[1] , qso->check_recv[2]);
if ((j = 13 - strlen(sent)) < 0) j = 0; else strncpy(sent_spaces, SPACES, j);
sent_spaces[j] = '\0';
if ((j = 13 - strlen(recv)) < 0) j = 0; else strncpy(recv_spaces, SPACES, j);
recv_spaces[j] = '\0';
/* Format score */
sprintf(score, "%d", qso->score);
if ((j = 8 - strlen(score)) < 0) j = 0; else strncpy(score_spaces, SPACES, j);
score_spaces[j] = '\0';
/* Format remarks */
memset(msg, 0, sizeof(msg));
if (qso->ham_id < -1) sprintf(msg[0], "No log received from %s", qso->callsign);
switch (qso->checked) {
case QSO_STATUS_CONTEST_ERROR:
strcpy(msg[1], "Error during contest evaluation");
break;
case QSO_STATUS_ERROR:
sprintf(msg[1], "Not in the log of %s", qso->callsign);
break;
case QSO_STATUS_GENERAL_XCHECK_OK:
strcpy(msg[1], "Incomplete contest evaluation");
break;
case QSO_STATUS_CONTEST_XCHECK_FAIL:
sprintf(msg[1], "QSO with error");
break;
case QSO_STATUS_CONTEST_XCHECK_ONE_SIDE_VALID:
sprintf(msg[1], "This QSO is successful for you but failed for %s", qso->callsign);
break;
case QSO_STATUS_CONTEST_XCHECK_ONE_SIDE_FAIL_RECV:
strcpy(msg[1], "Bad copy");
break;
case QSO_STATUS_CONTEST_XCHECK_ONE_SIDE_FAIL_SENT:
strcpy(msg[1], "Bad exchange");
break;
}
if (qso->marked) strcpy(msg[2], "QSO is marked by judge");
if (qso->dupe) strcpy(msg[3], "Duplicate QSO");
d = remarks;
for (j = 0; j < 4; j++) {
s = msg[j];
while (*s) *d++ = *s++;
if (s > msg[j] && j < 3) {
for (k = j + 1; k < 4; k++) {
if (msg[k][0] != '\0') {
*d++ = ';';
*d++ = ' ';
break;
}
}
}
}
j = (int)(d - remarks);
remarks[j] = '\0';
/* Print QSO info */
report_add(ubn_fd, "| %s%s|%s| %s | %s%s| %s%s| %s%s|%s%s|%s%s| %s%s| %c | %s\n",
qso_num, num_spaces, date, time, mode, mode_spaces, band, band_spaces, qso->callsign, callsign_spaces,
sent, sent_spaces, recv, recv_spaces, score, score_spaces, qso->mult ? '*' : ' ', remarks);
qso = (QSO_S*)(qso->next);
}
/* Footer */
report_add(ubn_fd, "+-------+----------+-------+------+------+---------------+-------------+-------------+---------+------+-------------\n\n");
report_add(ubn_fd, "Total score: %u (%u mult)\n", ham->actual_score, ham->total_mult);
if (ham->rating_place) report_add(ubn_fd, "You are #%u in Rating Table%s\n", ham->rating_place,
ham->rating_place < 4 ? ". CONGRATULATIONS!" : "");
if (config->contest.www[0]) report_add(ubn_fd, "\nOfficial results you can find at: %s\n", config->contest.www);
fclose(ubn_fd);
}
}
}
DEBUG("<== report_ubn(%p, %p)\n", base, config);
}