MeOS version 3.6-1033 RC1

This commit is contained in:
Erik Melin 2019-03-19 22:32:05 +01:00
parent 8ba2208e65
commit e8e5e499f2
176 changed files with 8023 additions and 3024 deletions

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -30,26 +30,36 @@
#include "meos_util.h" #include "meos_util.h"
#include "Localizer.h" #include "Localizer.h"
#include "gdiconstants.h" #include "gdiconstants.h"
#include "HTMLWriter.h"
#include "Printer.h"
#include "oListInfo.h"
#include "meosexception.h"
#include <sstream>
#include <iomanip>
double getLocalScale(const wstring &fontName, wstring &faceName); double getLocalScale(const wstring &fontName, wstring &faceName);
wstring getMeosCompectVersion(); wstring getMeosCompectVersion();
static void generateStyles(const gdioutput &gdi, ostream &fout, bool withTbl, const list<TextInfo> &TL, map <string, shared_ptr<HTMLWriter>> HTMLWriter::tCache;
extern wchar_t exePath[MAX_PATH];
static void generateStyles(const gdioutput &gdi, ostream &fout, double scale, bool withTbl, const list<TextInfo> &TL,
map< pair<gdiFonts, string>, pair<string, string> > &styles) { map< pair<gdiFonts, string>, pair<string, string> > &styles) {
fout << "<style type=\"text/css\">\n"; fout << "<style type=\"text/css\">\n";
fout << "body {background-color: rgb(250,250,255)}\n"; fout << "body {background-color: rgb(250,250,255)}\n";
fout << "h1 {font-family:arial,sans-serif;font-size:24px;font-weight:normal;white-space:nowrap}\n"; fout << "h1 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 24 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h2 {font-family:arial,sans-serif;font-size:20px;font-weight:normal;white-space:nowrap}\n"; fout << "h2 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 20 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "h3 {font-family:arial,sans-serif;font-size:16px;font-weight:normal;white-space:nowrap}\n"; fout << "h3 {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 16 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "p {font-family:arial,sans-serif;font-size:12px;font-weight:normal}\n"; fout << "p {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal}\n";
fout << "div {font-family:arial,sans-serif;font-size:12px;font-weight:normal}\n"; fout << "div {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
if (withTbl) { if (withTbl) {
fout << "td {font-family:arial,sans-serif;font-size:12px;font-weight:normal;white-space:nowrap}\n"; fout << "td {font-family:arial,sans-serif;font-size:" << fixed << std::setprecision(2) << 12 * scale << "px;font-weight:normal;white-space:nowrap}\n";
fout << "td.e0 {background-color: rgb(238,238,255)}\n"; fout << "td.e0 {background-color: rgb(238,238,255)}\n";
fout << "td.e1 {background-color: rgb(245,245,255)}\n"; fout << "td.e1 {background-color: rgb(245,245,255)}\n";
fout << "td.header {line-height:1.8;height:40px}\n"; fout << "td.header {line-height:" << fixed << std::setprecision(2) << 1.8 * scale << ";height:" << fixed << std::setprecision(2) << 40 * scale << "px}\n";
fout << "td.freeheader {line-height:1.2}\n"; fout << "td.freeheader {line-height:" << fixed << std::setprecision(2) << 1.2 * scale << "}\n";
} }
list<TextInfo>::const_iterator it=TL.begin(); list<TextInfo>::const_iterator it=TL.begin();
int styleList = 1; int styleList = 1;
@ -93,16 +103,16 @@ static void generateStyles(const gdioutput &gdi, ostream &fout, bool withTbl, co
} }
wstring faceName; wstring faceName;
double scale = 1.0; double iscale = 1.0;
if (it->font.empty()) { if (it->font.empty()) {
faceName = L"arial,sans-serif"; faceName = L"arial,sans-serif";
} }
else else
scale = getLocalScale(it->font, faceName); iscale = getLocalScale(it->font, faceName);
fout << element << "." << style fout << element << "." << style
<< "{font-family:" << gdi.narrow(faceName) << ";font-size:" << "{font-family:" << gdi.narrow(faceName) << ";font-size:"
<< itos(int(floor(scale * baseSize + 0.5))) << fixed << std::setprecision(2) << (scale * iscale * baseSize)
<< "px;font-weight:normal;white-space:nowrap}\n"; << "px;font-weight:normal;white-space:nowrap}\n";
styles[make_pair(font, gdi.narrow(it->font))] = make_pair(element, style); styles[make_pair(font, gdi.narrow(it->font))] = make_pair(element, style);
@ -112,6 +122,76 @@ static void generateStyles(const gdioutput &gdi, ostream &fout, bool withTbl, co
fout << "</style>\n"; fout << "</style>\n";
} }
class InterpTextInfo {
public:
static int x(const TextInfo &ti) {
return ti.xp;
}
static int y(const TextInfo &ti) {
return ti.yp;
}
static const TextInfo &ti(const TextInfo &in_ti) {
return in_ti;
}
};
template<typename T, typename TI>
void HTMLWriter::formatTL(ostream &fout,
const map<pair<gdiFonts, string>, pair<string, string>> &styles,
const T &tl,
double &yscale, double &xscale,
int &offsetY, int &offsetX) {
auto itt = tl.begin();
while (itt != tl.end()) {
auto &ctr_it = *itt;
const TextInfo &it = TI::ti(ctr_it);
if (gdioutput::skipTextRender(it.format)) {
++itt;
continue;
}
string yp = itos(int(yscale*TI::y(ctr_it)) + offsetY);
string xp = itos(int(xscale*TI::x(ctr_it)) + offsetX);
string estyle;
if (it.format != 1 && it.format != boldSmall) {
if (it.format & textRight)
estyle = " style=\"position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
else
estyle = " style=\"position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
}
else {
if (it.format & textRight)
estyle = " style=\"font-weight:bold;position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
else
estyle = " style=\"font-weight:bold;position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
}
string starttag, endtag;
getStyle(styles, it.getGdiFont(), gdioutput::narrow(it.font), estyle, starttag, endtag);
if (!it.text.empty())
fout << starttag << gdioutput::toUTF8(encodeXML(it.text)) << endtag << endl;
if (it.format == boldLarge) {
auto next = itt;
++next;
if (next == tl.end() || next->yp != it.yp)
offsetY += 7;
}
++itt;
}
}
static void getStyle(const map< pair<gdiFonts, string>, pair<string, string> > &styles, static void getStyle(const map< pair<gdiFonts, string>, pair<string, string> > &styles,
gdiFonts font, const string &face, const string &extraStyle, string &starttag, string &endtag) { gdiFonts font, const string &face, const string &extraStyle, string &starttag, string &endtag) {
starttag.clear(); starttag.clear();
@ -187,94 +267,52 @@ static void getStyle(const map< pair<gdiFonts, string>, pair<string, string> > &
} }
} }
bool gdioutput::writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const void HTMLWriter::writeHTML(gdioutput &gdi, const wstring &file,
{ const wstring &title, int refreshTimeOut, double scale){
checkWriteAccess(file); checkWriteAccess(file);
ofstream fout(file.c_str()); ofstream fout(file.c_str());
if (fout.bad()) if (fout.bad())
return false; throw std::exception("Bad output stream");
writeHTML(gdi, fout, title, refreshTimeOut, scale);
}
fout << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n" << void HTMLWriter::writeHTML(gdioutput &gdi, ostream &fout, const wstring &title, int refreshTimeOut, double scale) {
" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n"; if (scale <= 0)
scale = 1.0;
fout << "<!DOCTYPE html>" << endl;
fout << "<html>\n<head>\n"; fout << "<html>\n<head>\n";
fout << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"; fout << "<meta charset=\"UTF-8\"/>\n";
if (refreshTimeOut > 0) if (refreshTimeOut > 0)
fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n"; fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n";
fout << "<title>" << gdioutput::toUTF8(title) << "</title>\n";
fout << "<title>" << toUTF8(title) << "</title>\n";
map< pair<gdiFonts, string>, pair<string, string> > styles; map< pair<gdiFonts, string>, pair<string, string> > styles;
generateStyles(*this, fout, false, TL, styles); generateStyles(gdi, fout, scale, false, gdi.getTL(), styles);
fout << "</head>\n"; fout << "</head>\n";
fout << "<body>\n"; fout << "<body>\n";
double yscale = 1.3 * scale;
double xscale = 1.2 * scale;
int offsetY = 0, offsetX = 0;
HTMLWriter::formatTL<list<TextInfo>, InterpTextInfo>(fout, styles, gdi.getTL(), yscale, xscale, offsetY, offsetX);
list<TextInfo>::const_iterator it = TL.begin(); fout << "<p style=\"position:absolute;left:10px;top:" << int(yscale*(gdi.getPageY()-45)) + offsetY << "px\">";
double yscale = 1.3;
double xscale = 1.2;
int offsetY = 0;
while (it!=TL.end()) {
if (skipTextRender(it->format)) {
++it;
continue;
}
string yp = itos(int(yscale*it->yp) + offsetY);
string xp = itos(int(xscale *it->xp));
string estyle;
if (it->format!=1 && it->format!=boldSmall) {
if (it->format & textRight)
estyle = " style=\"position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
else
estyle = " style=\"position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
}
else {
if (it->format & textRight)
estyle = " style=\"font-weight:bold;position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
else
estyle = " style=\"font-weight:bold;position:absolute;left:" +
xp + "px;top:" + yp + "px\"";
}
string starttag, endtag;
getStyle(styles, it->getGdiFont(), narrow(it->font), estyle, starttag, endtag);
if (!it->text.empty())
fout << starttag << toUTF8(encodeXML(it->text)) << endtag << endl;
if (it->format == boldLarge) {
list<TextInfo>::const_iterator next = it;
++next;
if (next == TL.end() || next->yp != it->yp)
offsetY += 7;
}
++it;
}
fout << "<p style=\"position:absolute;left:10px;top:" << int(yscale*MaxY)+15 + offsetY << "px\">";
char bf1[256]; char bf1[256];
char bf2[256]; char bf2[256];
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256); GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256); GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
//fout << "Skapad av <i>MeOS</i>: " << bf1 << " "<< bf2 << "\n"; //fout << "Skapad av <i>MeOS</i>: " << bf1 << " "<< bf2 << "\n";
fout << toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " << bf1 << " "<< bf2 << "\n"; fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " << bf1 << " "<< bf2 << "\n";
fout << "</p>\n"; fout << "</p>\n";
fout << "</body>\n"; fout << "</body>\n";
fout << "</html>\n"; fout << "</html>\n";
return false;
} }
wstring html_table_code(const wstring &in) wstring html_table_code(const wstring &in)
@ -292,40 +330,45 @@ bool sortTL_X(const TextInfo *a, const TextInfo *b)
} }
bool gdioutput::writeTableHTML(const wstring &file, void HTMLWriter::writeTableHTML(gdioutput &gdi,
const wstring &title, int refreshTimeOut) const const wstring &file,
{ const wstring &title,
int refreshTimeOut,
double scale) {
checkWriteAccess(file); checkWriteAccess(file);
ofstream fout(file.c_str()); ofstream fout(file.c_str());
if (fout.bad()) if (fout.bad())
return false; return throw std::exception("Bad output stream");
return writeTableHTML(fout, title, false, refreshTimeOut); writeTableHTML(gdi, fout, title, false, refreshTimeOut, scale);
} }
bool gdioutput::writeTableHTML(ostream &fout, void HTMLWriter::writeTableHTML(gdioutput &gdi,
ostream &fout,
const wstring &title, const wstring &title,
bool simpleFormat, bool simpleFormat,
int refreshTimeOut) const { int refreshTimeOut,
double scale) {
fout << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n" << if (scale <= 0)
" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n"; scale = 1.0;
fout << "<!DOCTYPE html>" << endl;
fout << "<html>\n<head>\n"; fout << "<html>\n<head>\n";
fout << "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"; fout << "<meta charset=\"UTF-8\"/>\n";
if (refreshTimeOut > 0) if (refreshTimeOut > 0)
fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n"; fout << "<meta http-equiv=\"refresh\" content=\"" << refreshTimeOut << "\">\n";
fout << "<title>" << toUTF8(title) << "</title>\n"; fout << "<title>" << gdioutput::toUTF8(title) << "</title>\n";
map< pair<gdiFonts, string>, pair<string, string> > styles; map< pair<gdiFonts, string>, pair<string, string> > styles;
generateStyles(*this, fout, true, TL, styles); generateStyles(gdi, fout, scale, true, gdi.getTL(), styles);
fout << "</head>\n"; fout << "</head>\n";
fout << "<body>\n"; fout << "<body>\n";
auto &TL = gdi.getTL();
list<TextInfo>::const_iterator it = TL.begin(); auto it = TL.begin();
int MaxX = gdi.getPageX() - 100;
map<int,int> tableCoordinates; map<int,int> tableCoordinates;
//Get x-coordinates //Get x-coordinates
@ -463,39 +506,39 @@ bool gdioutput::writeTableHTML(ostream &fout,
for (size_t k=0;k<row.size();k++) { for (size_t k=0;k<row.size();k++) {
int thisCol=tableCoordinates[row[k]->xp]; int thisCol=tableCoordinates[row[k]->xp];
if (k==0 && thisCol!=0) if (k == 0 && thisCol != 0)
fout << "<td" << lineclass << " colspan=\"" << thisCol << "\">&nbsp;</td>"; fout << "<td" << lineclass << " colspan=\"" << thisCol << "\">&nbsp;</td>";
int nextCol; int nextCol;
if (row.size()==k+1) if (row.size() == k + 1)
nextCol=tableCoordinates.rbegin()->second; nextCol = tableCoordinates.rbegin()->second;
else else
nextCol=tableCoordinates[row[k+1]->xp]; nextCol = tableCoordinates[row[k + 1]->xp];
int colspan=nextCol-thisCol; int colspan = nextCol - thisCol;
assert(colspan>0); assert(colspan > 0);
string style; string style;
if (row[k]->format&textRight) if (row[k]->format&textRight)
style=" style=\"text-align:right\""; style = " style=\"text-align:right\"";
if (colspan==1 && !sizeSet[thisCol]) { if (colspan == 1 && !sizeSet[thisCol]) {
fout << " <td" << lineclass << style << " width=\"" << int( (k+1<row.size()) ? fout << " <td" << lineclass << style << " width=\"" << int((k + 1 < row.size()) ?
(row[k+1]->xp - row[k]->xp) : (MaxX-row[k]->xp)) << "\">"; (row[k + 1]->xp - row[k]->xp) : (MaxX - row[k]->xp)) << "\">";
sizeSet[thisCol]=true; sizeSet[thisCol] = true;
} }
else if (colspan>1) else if (colspan > 1)
fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">"; fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">";
else else
fout << " <td" << lineclass << style << ">"; fout << " <td" << lineclass << style << ">";
gdiFonts font = row[k]->getGdiFont(); gdiFonts font = row[k]->getGdiFont();
string starttag, endtag; string starttag, endtag;
getStyle(styles, font, narrow(row[k]->font), "", starttag, endtag); getStyle(styles, font, gdioutput::narrow(row[k]->font), "", starttag, endtag);
fout << starttag << toUTF8(html_table_code(row[k]->text)) << endtag << "</td>" << endl; fout << starttag << gdioutput::toUTF8(html_table_code(row[k]->text)) << endtag << "</td>" << endl;
} }
fout << "</tr>\n"; fout << "</tr>\n";
@ -512,12 +555,423 @@ bool gdioutput::writeTableHTML(ostream &fout,
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256); GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256); GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
wstring meos = getMeosCompectVersion(); wstring meos = getMeosCompectVersion();
fout << toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS " fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS "
<< toUTF8(meos) << "</i></a>: " << bf1 << " "<< bf2 << "\n"; << gdioutput::toUTF8(meos) << "</i></a>: " << bf1 << " " << bf2 << "\n";
fout << "</p><br>\n"; fout << "</p><br>\n";
} }
fout << "</body>\n"; fout << "</body>" << endl;
fout << "</html>\n"; fout << "</html>" << endl;
}
return true;
extern wchar_t programPath[MAX_PATH];
void HTMLWriter::enumTemplates(TemplateType type, vector<TemplateInfo> &descriptionFile) {
vector<wstring> res;
#ifdef _DEBUG
expandDirectory((wstring(programPath) + L".\\..\\Lists\\").c_str(), L"*.template", res);
#endif
wchar_t listpath[MAX_PATH];
getUserFile(listpath, L"");
expandDirectory(listpath, L"*.template", res);
if (exePath[0])
expandDirectory(exePath, L"*.template", res);
set<string> tags;
tCache.clear();
TemplateInfo ti;
for (wstring &fn : res) {
ifstream file(fn);
string str;
if (getline(file, str)) {
if (str == "@MEOS EXPORT TEMPLATE" && getline(file, str)) {
vector<string> tagName;
split(str, "@", tagName);
if (tagName.size() == 2) {
ti.tag = tagName[0];
if (!tags.insert(tagName[0]).second)
continue; // Already included
string2Wide(tagName[1], ti.name);
if (getline(file, str)) {
string2Wide(str, ti.desc);
}
ti.file = fn;
if (type == TemplateType::List)
descriptionFile.push_back(ti);
}
else {
throw meosException(L"Bad template: " + fn);
}
}
else if (str == "@MEOS PAGE" && getline(file, str)) {
vector<string> tagName;
split(str, "@", tagName);
if (tagName.size() == 2) {
ti.tag = tagName[0];
if (!tags.insert(tagName[0]).second)
continue; // Already included
string2Wide(tagName[1], ti.name);
if (getline(file, str)) {
string2Wide(str, ti.desc);
}
ti.file = fn;
if (type == TemplateType::Page)
descriptionFile.push_back(ti);
}
else {
throw meosException(L"Bad template: " + fn);
}
}
}
}
}
const HTMLWriter &HTMLWriter::getWriter(TemplateType type, const string &tag) {
auto res = tCache.find(tag);
if (res != tCache.end()) {
return *res->second;
}
else {
vector<TemplateInfo> descriptionFile;
enumTemplates(type, descriptionFile);
int ix = -1;
for (size_t k = 0; k < descriptionFile.size(); k++) {
if (descriptionFile[k].tag == tag) {
ix = k;
break;
}
}
if (ix == -1)
throw std::exception("Internal error");
shared_ptr<HTMLWriter> tmpl = make_shared<HTMLWriter>();
tmpl->read(descriptionFile[ix].file);
vector<string> tagName;
split(tmpl->info, "@", tagName);
if (tagName.size() == 2)
tCache[tagName[0]] = tmpl;
return *tmpl;
}
}
string HTMLWriter::localize(const string &in) {
string out;
size_t offset = 0;
size_t pos = in.find_first_of('$', offset);
while (pos != string::npos) {
if (out.empty())
out.reserve(in.length() * 2);
size_t end = in.find_first_of('$', pos+1);
if (end != string::npos && end > pos + 2) {
wstring key = gdioutput::fromUTF8(in.substr(pos + 1, end - pos - 1));
out += in.substr(offset, pos-offset);
if (key[0] != '!')
out += gdioutput::toUTF8(lang.tl(key));
else
out += gdioutput::toUTF8(lang.tl(key.substr(1), true));
offset = end + 1;
pos = in.find_first_of('$', offset);
}
else
break;
}
if (offset == 0)
return trim(in);
out += in.substr(offset);
return trim(out);
}
void HTMLWriter::read(const wstring &fileName) {
ifstream file(fileName);
string dmy;
string *acc = &dmy;
string str;
int ok = 0 ;
const string comment = "//";
while (getline(file, str)) {
if (ok == 0 && str == "@MEOS EXPORT TEMPLATE") {
ok = 1;
continue;
}
else if (ok == 1) {
ok = 2;
info = str;
}
else if (ok == 0 && str == "@MEOS PAGE") {
ok = 3;
continue;
}
else if (ok == 3) {
ok = 4;
info = str;
acc = &page;
continue;
}
else if (str.length() > 1 && str[0] == '%')
continue; // Ignore comment
else if (str == "@HEAD")
acc = &head;
else if (str == "@DESCRIPRION")
acc = &description;
else if (str == "@OUTERPAGE")
acc = &outerpage;
else if (str == "@INNERPAGE")
acc = &innerpage;
else if (str == "@SEPARATOR")
acc = &separator;
else if (str == "@END")
acc = &end;
else {
size_t cix = str.rfind(comment);
if (cix != string::npos) {
if (cix == 0)
continue; // Comment line
else if (cix > 0 && str[cix - 1] != ':')
str = str.substr(0, cix);
}
*acc += localize(str) + "\n";
if (!(str.empty() || acc->back() == '>' || acc->back() == ';' || acc->back() == '}' || acc->back() == '{'))
*acc += " ";
}
}
}
namespace {
void replaceAll(string& str, const string& from, const string& to) {
size_t start_pos = 0;
while ((start_pos = str.find(from, start_pos)) != string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
}
class InterpPrintTextInfo {
public:
static int x(const PrintTextInfo &ti) {
return int(ti.xp);
}
static int y(const PrintTextInfo &ti) {
return int(ti.yp);
}
static const TextInfo &ti(const PrintTextInfo &in_ti) {
return in_ti.ti;
}
};
void HTMLWriter::generate(gdioutput &gdi,
ostream &fout,
const wstring &title,
const wstring &contentDescription,
bool respectPageBreak,
const int nRows,
const int numCol,
const int interval,
const int marginPercent,
double scale) const {
int w, h;
gdi.getTargetDimension(w, h);
string meos = "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS</i></a>: " + gdioutput::toUTF8(getMeosCompectVersion()) + "</a>";
int margin = (w * marginPercent) / 100;
int height = nRows * gdi.getLineHeight();
bool infPage = false;
if (nRows == 0) {
infPage = true;
height = gdi.getPageY()/numCol;
}
PageInfo pageInfo;
pageInfo.topMargin = 20;
pageInfo.scaleX = 1.0f;
pageInfo.scaleY = 1.0f;
pageInfo.leftMargin = 20;
pageInfo.bottomMargin = 30;
pageInfo.pageY = float(height - margin);
pageInfo.printHeader = false;
pageInfo.yMM2PrintC = pageInfo.xMM2PrintC = 1;
pageInfo.xMM2PrintK = 0;
pageInfo.yMM2PrintK = 0;
list<RectangleInfo> rectangles;
vector<RenderedPage> pages;
pageInfo.renderPages(gdi.getTL(), rectangles, false, respectPageBreak || infPage, pages);
int numChapter = 0;
for (auto &pi : pages)
if (pi.startChapter)
numChapter++;
if (infPage && pages.size() > size_t(numCol)) {
bool respectChapter = numChapter == numCol; // If the number of chapters (linked lists) equals number of columns, respec these.
vector<RenderedPage> pagesOut;
bool startPage = true;
int ydiff = 0;
for (auto &p : pages) {
if (p.text.empty())
continue;
if (respectChapter)
startPage = p.startChapter;
else if (!pagesOut.empty() && pagesOut.back().text.back().yp + p.text.back().yp / 4 > height)
startPage = true;
if (startPage && pagesOut.size() < size_t(numCol)) {
pagesOut.push_back(move(p));
startPage = false;
ydiff = int(pagesOut.back().text.back().yp);
}
else {
for (auto &t : p.text) {
pagesOut.back().text.push_back(move(t));
pagesOut.back().text.back().yp += ydiff;
}
ydiff = int(pagesOut.back().text.back().yp);
}
}
pages.swap(pagesOut);
}
string output = head;
replaceAll(output, "@D", gdioutput::toUTF8(encodeXML(contentDescription)));
replaceAll(output, "@T", gdioutput::toUTF8(encodeXML(title)));
replaceAll(output, "@M", meos);
map<pair<gdiFonts, string>, pair<string, string>> styles;
{
stringstream sout;
generateStyles(gdi, sout, scale, false, gdi.getTL(), styles);
replaceAll(output, "@S", sout.str());
}
int nPage = (pages.size() + numCol - 1) / numCol;
replaceAll(output, "@N", itos(nPage));
fout << output;
int ipCounter = 1;
int opCounter = 1;
for (size_t pix = 0; pix < pages.size();) {
string innerpageoutput;
for (int ip = 0; ip < numCol; ip++) {
if (pages.size() == pix)
break;
if (ip > 0) {
// Separator
output = separator;
replaceAll(output, "@P", itos(ipCounter));
replaceAll(output, "@L", itos((ip * 100) / numCol));
innerpageoutput += output;
}
auto &p = pages[pix++];
stringstream sout;
double yscale = 1.3 * scale;
double xscale = 1.2 * scale;
int offsetY = 0, offsetX = 0;
formatTL<vector<PrintTextInfo>, InterpPrintTextInfo>(sout, styles, p.text, yscale, xscale, offsetY, offsetX);
output = innerpage;
replaceAll(output, "@P", itos(ipCounter++));
replaceAll(output, "@L", itos((ip * 100) / numCol));
replaceAll(output, "@C", sout.str());
replaceAll(output, "@M", meos);
innerpageoutput += output;
}
string outeroutput = outerpage;
replaceAll(outeroutput, "@P", itos(opCounter++));
replaceAll(outeroutput, "@C", innerpageoutput);
replaceAll(output, "@M", meos);
replaceAll(output, "@N", itos(nPage));
fout << outeroutput << endl;
}
assert(opCounter - 1 == nPage);
output = end;
replaceAll(output, "@N", itos(opCounter - 1));
replaceAll(output, "@I", itos(numCol));
replaceAll(output, "@T", itos(interval));
replaceAll(output, "@M", meos);
fout << output;
}
void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak,
const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale) {
checkWriteAccess(file);
ofstream fout(file.c_str());
write(gdi, fout, title, contentsDescription, respectPageBreak, typeTag, refresh,
rows, cols, time_ms, margin, scale);
}
void HTMLWriter::write(gdioutput &gdi, ostream &fout, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak, const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale) {
if (typeTag == "table")
writeTableHTML(gdi, fout, title, false, refresh, scale);
else if (typeTag == "free") {
writeHTML(gdi, fout, title, refresh, scale);
}
else {
/* auto res = tCache.find(typeTag);
if (res == tCache.end()) {
vector<HTMLWriter::TemplateInfo> htmlTmpl;
HTMLWriter::enumTemplates(TemplateType::List, htmlTmpl);
int ix = -1;
for (size_t k = 0; k < htmlTmpl.size(); k++) {
if (htmlTmpl[k].tag == typeTag) {
ix = k;
break;
}
}
if (ix == -1)
throw std::exception("Internal error");
shared_ptr<HTMLWriter> tmpl = make_shared<HTMLWriter>();
tmpl->read(htmlTmpl[ix].file);
vector<string> tagName;
split(tmpl->info, "@", tagName);
if (tagName.size() == 2)
tCache[tagName[0]] = tmpl;
tmpl->generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}
else {
res->second->generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}*/
getWriter(TemplateType::List, typeTag).generate(gdi, fout, title, contentsDescription, respectPageBreak, rows, cols, time_ms, margin, scale);
}
}
void HTMLWriter::write(gdioutput &gdi, const wstring &file, const wstring &title, int refresh, oListParam &param, const oEvent &oe) {
write(gdi, file, title, param.getContentsDescriptor(oe), param.pageBreak, param.htmlTypeTag,
refresh != 0 ? refresh : param.timePerPage / 1000, param.htmlRows, param.nColumns,
param.timePerPage, param.margin, param.htmlScale);
}
void HTMLWriter::getPage(const oEvent &oe, string &out) const {
out = page;
} }

114
code/HTMLWriter.h Normal file
View File

@ -0,0 +1,114 @@
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#pragma once
struct oListParam;
class HTMLWriter {
string info;
string description;
string head;
string outerpage;
string innerpage;
string separator;
string end;
string page;
static map <string, shared_ptr<HTMLWriter>> tCache;
static string localize(const string &in);
public:
static void reset() {
tCache.clear();
}
enum class TemplateType {
List,
Page
};
static const HTMLWriter &getWriter(TemplateType type, const string &tag);
struct TemplateInfo {
string tag;
wstring name;
wstring desc;
wstring file;
};
static void enumTemplates(TemplateType type, vector<TemplateInfo> &descriptionFile);
void read(const wstring &fileName);
void generate(gdioutput &gdi,
ostream &fout,
const wstring &title,
const wstring &contentDescription,
bool respectPageBreak,
const int nRows,
const int numCol,
const int interval,
const int marginPercent,
double scal) const;
void getPage(const oEvent &oe, string &out) const;
static void writeHTML(gdioutput &gdi, ostream &dout, const wstring &title, int refreshTimeOut, double scale);
static void writeTableHTML(gdioutput &gdi, ostream &fout,
const wstring &title,
bool simpleFormat,
int refreshTimeOut,
double scale);
static void writeTableHTML(gdioutput &gdi, const wstring &file,
const wstring &title,
int refreshTimeOut,
double scale);
static void writeHTML(gdioutput &gdi, const wstring &file,
const wstring &title, int refreshTimeOut, double scale);
static void write(gdioutput &gdi, const wstring &file, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak, const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale);
static void write(gdioutput &gdi, ostream &fout, const wstring &title, const wstring &contentsDescription,
bool respectPageBreak, const string &typeTag, int refresh,
int rows, int cols, int time_ms, int margin, double scale);
static void write(gdioutput &gdi, const wstring &file, const wstring &title, int refresh, oListParam &param, const oEvent &oe);
template<typename T, typename TI>
static void formatTL(ostream &fout,
const map< pair<gdiFonts, string>, pair<string, string> > &styles,
const T &tl,
double &yscale,
double &xscale,
int &offsetY,
int &offsetX);
};

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -55,6 +55,9 @@ MeOSFeatures::MeOSFeatures(void)
addHead("Rogaining"); addHead("Rogaining");
add(Rogaining, L"RO", "Rogaining"); add(Rogaining, L"RO", "Rogaining");
add(PointAdjust, L"PA", "Manual point reductions and adjustments").require(Rogaining); add(PointAdjust, L"PA", "Manual point reductions and adjustments").require(Rogaining);
addHead("Timekeeping");
add(NoCourses, L"NC", "Without courses");
} }
MeOSFeatures::FeatureDescriptor &MeOSFeatures::add(Feature feat, const wchar_t *code, const char *descr) { MeOSFeatures::FeatureDescriptor &MeOSFeatures::add(Feature feat, const wchar_t *code, const char *descr) {
@ -239,6 +242,8 @@ void MeOSFeatures::loadDefaults(oEvent &oe) {
void MeOSFeatures::useAll(oEvent &oe) { void MeOSFeatures::useAll(oEvent &oe) {
for (size_t k = 0; k < desc.size(); k++) { for (size_t k = 0; k < desc.size(); k++) {
if (desc[k].feat == NoCourses)
continue;
if (desc[k].feat != _Head) if (desc[k].feat != _Head)
features.insert(desc[k].feat); features.insert(desc[k].feat);
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -50,6 +50,7 @@ public:
DrawStartList, DrawStartList,
Bib, Bib,
RunnerDb, RunnerDb,
NoCourses,
}; };
private: private:
@ -97,6 +98,9 @@ public:
const string &getDescription(Feature f) const; const string &getDescription(Feature f) const;
const wstring &getCode(Feature f) const; const wstring &getCode(Feature f) const;
bool withoutCourses(const oEvent &oe) const { return hasFeature(NoCourses) && oe.getNumCourses() == 0; }
bool withCourses(const oEvent *oe) const { return !withoutCourses(*oe); }
wstring serialize() const; wstring serialize() const;
void deserialize(const wstring &input, oEvent &oe); void deserialize(const wstring &input, oEvent &oe);
}; };

View File

@ -4,7 +4,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -59,6 +59,7 @@ struct PageInfo {
void renderPages(const list<TextInfo> &tl, void renderPages(const list<TextInfo> &tl,
const list<RectangleInfo> &rects, const list<RectangleInfo> &rects,
bool invertHeightY, bool invertHeightY,
bool respectPageBreak,
vector<RenderedPage> &pages); vector<RenderedPage> &pages);
wstring pageInfo(const RenderedPage &page) const; wstring pageInfo(const RenderedPage &page) const;
@ -68,6 +69,7 @@ struct PageInfo {
struct RenderedPage { struct RenderedPage {
int nPage; // This page number int nPage; // This page number
wstring info; wstring info;
bool startChapter = false;
vector<PrintTextInfo> text; vector<PrintTextInfo> text;
vector<RectangleInfo> rectangles; vector<RectangleInfo> rectangles;
__int64 checkSum; __int64 checkSum;

View File

@ -1,4 +1,26 @@
#include "stdafx.h" /************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "stdafx.h"
#include "RestService.h" #include "RestService.h"
#include "meos_util.h" #include "meos_util.h"
#include "restserver.h" #include "restserver.h"
@ -8,7 +30,7 @@
int AutomaticCB(gdioutput *gdi, int type, void *data); int AutomaticCB(gdioutput *gdi, int type, void *data);
RestService::RestService() : AutoMachine("Informationsserver"), port(-1) { RestService::RestService() : AutoMachine("Informationsserver", Machines::mInfoService), port(-1) {
} }
RestService::~RestService() { RestService::~RestService() {
@ -30,19 +52,62 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
else else
throw meosException("Invalid port number"); throw meosException("Invalid port number");
} }
if (gdi.isChecked("AllowEntry")) {
RestServer::EntryPermissionType pt = (RestServer::EntryPermissionType)gdi.getSelectedItem("PermissionPerson").first;
RestServer::EntryPermissionClass pc = (RestServer::EntryPermissionClass)gdi.getSelectedItem("PermissionClass").first;
server->setEntryPermission(pc, pt);
}
else {
server->setEntryPermission(RestServer::EntryPermissionClass::None,
RestServer::EntryPermissionType::None);
}
} }
void ListIpAddresses(vector<string>& ip);
void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) { void RestService::settings(gdioutput &gdi, oEvent &oe, bool created) {
if (port == -1) if (port == -1)
port = oe.getPropertyInt("ServicePort", 2009); port = oe.getPropertyInt("ServicePort", 2009);
settingsTitle(gdi, "MeOS Informationsserver REST-API"); settingsTitle(gdi, "MeOS Informationsserver REST-API");
//gdi.fillRight();
gdi.pushX();
gdi.addCheckbox("AllowEntry", "Tillåt anmälan", 0, false).setHandler(this);
gdi.addSelection("PermissionPerson", 180, 200, 0, L"Vem får anmäla sig:");
gdi.addItem("PermissionPerson", RestServer::getPermissionsPersons());
gdi.autoGrow("PermissionPerson");
gdi.selectFirstItem("PermissionPerson");
gdi.fillDown();
gdi.addSelection("PermissionClass", 180, 200, 0, L"Till vilka klasser:");
gdi.addItem("PermissionClass", RestServer::getPermissionsClass());
gdi.autoGrow("PermissionClass");
gdi.selectFirstItem("PermissionClass");
bool disablePermisson = true;
gdi.popX();
startCancelInterval(gdi, "Save", created, IntervalNone, L""); startCancelInterval(gdi, "Save", created, IntervalNone, L"");
if (!server) if (!server)
gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos"); gdi.addInput("Port", itow(port), 10, 0, L"Port:", L"#http://localhost:[PORT]/meos");
else else {
gdi.addString("", 0, "Server startad på X#" + itos(port)); gdi.addString("", 0, "Server startad på X#" + itos(port));
auto per = server->getEntryPermission();
if (get<RestServer::EntryPermissionType>(per) != RestServer::EntryPermissionType::None)
disablePermisson = false;
else {
gdi.selectItemByData("PermissionPerson", size_t(get<RestServer::EntryPermissionType>(per)));
gdi.selectItemByData("PermissionClass", size_t(get<RestServer::EntryPermissionClass>(per)));
}
}
if (disablePermisson) {
gdi.disableInput("PermissionPerson");
gdi.disableInput("PermissionClass");
}
else {
gdi.check("AllowEntry", true);
}
gdi.popX(); gdi.popX();
gdi.addString("", 10, "help:rest"); gdi.addString("", 10, "help:rest");
@ -65,7 +130,31 @@ void RestService::status(gdioutput &gdi) {
gdi.addButton("Update", "Uppdatera").setHandler(this); gdi.addButton("Update", "Uppdatera").setHandler(this);
gdi.dropLine(0.6); gdi.dropLine(0.6);
gdi.addString("", 1, "Testa servern:"); gdi.addString("", 1, "Testa servern:");
gdi.addString("link", 0, "#http://localhost:" + itos(port) + "/meos").setHandler(this);
string sport;
if (port != 80) {
sport = ":" + itos(port);
}
gdi.addString("link", 0, "#http://localhost" + sport + "/meos").setHandler(this);
vector<string> adr;
ListIpAddresses(adr);
if (adr.size() > 0) {
gdi.dropLine();
gdi.addString("", 1, "Externa adresser:");
for (string &ip : adr) {
gdi.addString("link", 0, "#http://" + ip + sport + "/meos").setHandler(this);
}
}
/*
if (get<RestServer::EntryPermissionType>(server->getEntryPermission()) != RestServer::EntryPermissionType::None) {
gdi.addString("", fontMediumPlus, "Anmälan");
}*/
} }
gdi.dropLine(2); gdi.dropLine(2);
@ -87,9 +176,13 @@ void RestService::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
if (bi.id == "Update") { if (bi.id == "Update") {
gdi.getTabs().get(TAutoTab)->loadPage(gdi); gdi.getTabs().get(TAutoTab)->loadPage(gdi);
} }
else if (bi.id == "AllowEntry") {
gdi.setInputStatus("PermissionPerson", gdi.isChecked(bi.id));
gdi.setInputStatus("PermissionClass", gdi.isChecked(bi.id));
}
} }
else if (type == GUI_LINK) { else if (type == GUI_LINK) {
wstring url = L"http://localhost:" + itow(port) + L"/meos"; wstring url = ((TextInfo &)info).text;
ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL); ShellExecute(NULL, L"open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
} }
} }

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -994,7 +994,7 @@ void RunnerDB::updateAdd(const oRunner &r, map<int, int> &clubIdMap)
if (r.getExtIdentifier() > 0) { if (r.getExtIdentifier() > 0) {
RunnerWDBEntry *dbe = getRunnerById(int(r.getExtIdentifier())); RunnerWDBEntry *dbe = getRunnerById(int(r.getExtIdentifier()));
if (dbe) { if (dbe) {
dbe->dbe().cardNo = r.CardNo; dbe->dbe().cardNo = r.getCardNo();
return; // Do not change too much in runner from national database return; // Do not change too much in runner from national database
} }
} }

View File

@ -11,7 +11,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1688,7 +1688,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
} }
string2Wide(lastNameByte, lastName); string2Wide(lastNameByte, lastName);
wcsncpy(card.lastName, lastName.c_str(), 20); wcsncpy_s(card.lastName, lastName.c_str(), 20);
memcpy(firstNameByte, data+32+20, 20); memcpy(firstNameByte, data+32+20, 20);
firstNameByte[20] = 0; firstNameByte[20] = 0;
@ -1698,7 +1698,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
} }
string2Wide(firstNameByte, firstName); string2Wide(firstNameByte, firstName);
wcsncpy(card.firstName, firstName.c_str(), 20); wcsncpy_s(card.firstName, firstName.c_str(), 20);
data+=128-16; data+=128-16;

View File

@ -11,7 +11,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -36,7 +36,7 @@ bool getDesktopFile(wchar_t *fileNamePath, const wchar_t *fileName, const wchar_
bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName); bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName);
class gdioutput; class gdioutput;
gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x = 0, int max_y = 0); gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x = 0, int max_y = 0, bool fixedSize = false);
gdioutput *getExtraWindow(const string &tag, bool toForeGround); gdioutput *getExtraWindow(const string &tag, bool toForeGround);
string uniqueTag(const char *base); string uniqueTag(const char *base);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -44,6 +44,7 @@
#include "gdiconstants.h" #include "gdiconstants.h"
#include "meosexception.h" #include "meosexception.h"
#include "HTMLWriter.h"
static TabAuto *tabAuto = 0; static TabAuto *tabAuto = 0;
int AutoMachine::uniqueId = 1; int AutoMachine::uniqueId = 1;
@ -212,7 +213,7 @@ void TabAuto::timerCallback(gdioutput &gdi)
DWORD d=0; DWORD d=0;
if (reload && !editMode && gdi.getData("AutoPage", d) && d) if (reload && !editMode && gdi.getData("AutoPage", d) && d)
loadPage(gdi); loadPage(gdi, false);
} }
void TabAuto::setTimer(AutoMachine *am) void TabAuto::setTimer(AutoMachine *am)
@ -259,7 +260,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
if (sm) if (sm)
sm->saveSettings(gdi); sm->saveSettings(gdi);
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id=="Result") { else if (bu.id=="Result") {
PrintResultMachine *sm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt())); PrintResultMachine *sm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
@ -271,8 +272,10 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
ext.push_back(make_pair(L"Webbdokument", L"*.html;*.htm")); ext.push_back(make_pair(L"Webbdokument", L"*.html;*.htm"));
wstring file = gdi.browseForSave(ext, L"html", index); wstring file = gdi.browseForSave(ext, L"html", index);
if (!file.empty()) if (!file.empty()) {
gdi.setText("ExportFile", file); gdi.setText("ExportFile", file);
oe->setProperty("LastExportTarget", file);
}
} }
else if (bu.id == "BrowseScript") { else if (bu.id == "BrowseScript") {
vector< pair<wstring, wstring> > ext; vector< pair<wstring, wstring> > ext;
@ -288,9 +291,11 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.setInputStatus("ExportScript", stat); gdi.setInputStatus("ExportScript", stat);
gdi.setInputStatus("BrowseFile", stat); gdi.setInputStatus("BrowseFile", stat);
gdi.setInputStatus("BrowseScript", stat); gdi.setInputStatus("BrowseScript", stat);
if (gdi.hasField("HTMLRefresh")) {
gdi.setInputStatus("HTMLRefresh", stat); gdi.setInputStatus("HTMLRefresh", stat);
gdi.setInputStatus("StructuredExport", stat); gdi.setInputStatus("StructuredExport", stat);
} }
}
else if (bu.id == "DoPrint") { else if (bu.id == "DoPrint") {
bool stat = gdi.isChecked(bu.id); bool stat = gdi.isChecked(bu.id);
gdi.setInputStatus("PrinterSetup", stat); gdi.setInputStatus("PrinterSetup", stat);
@ -339,9 +344,11 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
prm->doPrint = gdi.isChecked("DoPrint"); prm->doPrint = gdi.isChecked("DoPrint");
prm->exportFile = gdi.getText("ExportFile"); prm->exportFile = gdi.getText("ExportFile");
prm->exportScript = gdi.getText("ExportScript"); prm->exportScript = gdi.getText("ExportScript");
if (!prm->readOnly) {
prm->structuredExport = gdi.isChecked("StructuredExport"); prm->structuredExport = gdi.isChecked("StructuredExport");
prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0; prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
if (!prm->readOnly) {
gdi.getSelection("Classes", prm->classesToPrint); gdi.getSelection("Classes", prm->classesToPrint);
ListBoxInfo lbi; ListBoxInfo lbi;
@ -350,6 +357,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
par.selection=prm->classesToPrint; par.selection=prm->classesToPrint;
par.listCode = EStdListType(lbi.data); par.listCode = EStdListType(lbi.data);
par.pageBreak = gdi.isChecked("PageBreak"); par.pageBreak = gdi.isChecked("PageBreak");
par.showHeader = gdi.isChecked("ShowHeader");
par.showInterTimes = gdi.isChecked("ShowInterResults"); par.showInterTimes = gdi.isChecked("ShowInterResults");
par.splitAnalysis = gdi.isChecked("SplitAnalysis"); par.splitAnalysis = gdi.isChecked("SplitAnalysis");
int legNr = gdi.getSelectedItem("LegNumber").first; int legNr = gdi.getSelectedItem("LegNumber").first;
@ -363,13 +371,15 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
} }
prm->po.onlyChanged = gdi.isChecked("OnlyChanged"); prm->po.onlyChanged = gdi.isChecked("OnlyChanged");
prm->pageBreak = gdi.isChecked("PageBreak"); prm->pageBreak = gdi.isChecked("PageBreak");
prm->showHeader = gdi.isChecked("ShowHeader");
prm->showInterResult = gdi.isChecked("ShowInterResults"); prm->showInterResult = gdi.isChecked("ShowInterResults");
prm->splitAnalysis = gdi.isChecked("SplitAnalysis"); prm->splitAnalysis = gdi.isChecked("SplitAnalysis");
prm->synchronize=true; //To force continuos data sync. prm->synchronize=true; //To force continuos data sync.
setTimer(prm); setTimer(prm);
} }
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
#endif #endif
} }
@ -401,7 +411,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
setTimer(sm); setTimer(sm);
} }
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id=="Save") { // General save else if (bu.id=="Save") { // General save
AutoMachine *sm=getMachine(bu.getExtraInt()); AutoMachine *sm=getMachine(bu.getExtraInt());
@ -410,7 +420,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
setTimer(sm); setTimer(sm);
} }
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id=="StartPrewarning") { else if (bu.id=="StartPrewarning") {
PrewarningMachine *pwm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt())); PrewarningMachine *pwm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
@ -419,7 +429,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
pwm->waveFolder=gdi.getText("WaveFolder"); pwm->waveFolder=gdi.getText("WaveFolder");
gdi.getSelection("Controls", pwm->controls); gdi.getSelection("Controls", pwm->controls);
oe->synchronizeList(oLPunchId); oe->synchronizeList(oListId::oLPunchId);
oe->clearPrewarningSounds(); oe->clearPrewarningSounds();
pwm->synchronizePunches=true; pwm->synchronizePunches=true;
@ -432,7 +442,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
} }
} }
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id=="StartPunch") { else if (bu.id=="StartPunch") {
@ -452,17 +462,17 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
} }
} }
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id == "Cancel") { else if (bu.id == "Cancel") {
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id == "Stop") { else if (bu.id == "Stop") {
if (bu.getExtraInt()) if (bu.getExtraInt())
stopMachine(getMachine(bu.getExtraInt())); stopMachine(getMachine(bu.getExtraInt()));
updateSyncInfo(); updateSyncInfo();
loadPage(gdi); loadPage(gdi, false);
} }
else if (bu.id == "PrinterSetup") { else if (bu.id == "PrinterSetup") {
PrintResultMachine *prm = PrintResultMachine *prm =
@ -479,7 +489,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
if (prm) { if (prm) {
prm->process(gdi, oe, SyncNone); prm->process(gdi, oe, SyncNone);
setTimer(prm); setTimer(prm);
loadPage(gdi); loadPage(gdi, false);
} }
} }
else if (bu.id == "SelectAll") { else if (bu.id == "SelectAll") {
@ -540,8 +550,11 @@ bool TabAuto::stopMachine(AutoMachine *am)
void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) { void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) {
editMode=true; editMode=true;
bool createNew = (sm==0); bool createNew = (sm==0) || (ms == Machines::Unknown);
if (!sm) { if (sm) {
ms = sm->getType();
}
else {
sm = AutoMachine::construct(ms); sm = AutoMachine::construct(ms);
machines.push_back(sm); machines.push_back(sm);
} }
@ -576,7 +589,7 @@ void TabAuto::killMachines()
AutoMachine::resetGlobalId(); AutoMachine::resetGlobalId();
} }
bool TabAuto::loadPage(gdioutput &gdi) bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
{ {
oe->checkDB(); oe->checkDB();
tabAuto=this; tabAuto=this;
@ -587,8 +600,8 @@ bool TabAuto::loadPage(gdioutput &gdi)
int storedOY = 0; int storedOY = 0;
int storedOX = 0; int storedOX = 0;
if (isAP) { if (isAP) {
storedOY = gdi.GetOffsetY(); storedOY = gdi.getOffsetY();
storedOX = gdi.GetOffsetX(); storedOX = gdi.getOffsetX();
} }
gdi.clearPage(false); gdi.clearPage(false);
@ -652,7 +665,8 @@ bool TabAuto::loadPage(gdioutput &gdi)
if (isAP) { if (isAP) {
gdi.setOffset(storedOY, storedOY, true); gdi.setOffset(storedOY, storedOY, true);
} }
if (showSettingsLast && !machines.empty())
settings(gdi, *machines.rbegin(), Machines::Unknown);
gdi.refresh(); gdi.refresh();
return true; return true;
} }
@ -693,7 +707,7 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool c
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) { void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
settingsTitle(gdi, "Resultatutskrift / export"); settingsTitle(gdi, "Resultatutskrift / export");
wstring time=created ? L"10:00" : getTimeMS(interval); wstring time = (created && interval <= 0) ? L"10:00" : getTimeMS(interval);
startCancelInterval(gdi, "StartResult", created, IntervalMinute, time); startCancelInterval(gdi, "StartResult", created, IntervalMinute, time);
if (created) { if (created) {
@ -716,9 +730,15 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
gdi.addButton("BrowseFile", "Bläddra...", AutomaticCB); gdi.addButton("BrowseFile", "Bläddra...", AutomaticCB);
gdi.setCX(cx); gdi.setCX(cx);
gdi.dropLine(2.3); gdi.dropLine(2.3);
if (!readOnly) {
gdi.addCheckbox("StructuredExport", "Strukturerat exportformat", 0, structuredExport); gdi.addCheckbox("StructuredExport", "Strukturerat exportformat", 0, structuredExport);
gdi.addCheckbox("HTMLRefresh", "HTML med AutoRefresh", 0, htmlRefresh != 0); gdi.addCheckbox("HTMLRefresh", "HTML med AutoRefresh", 0, htmlRefresh != 0);
gdi.dropLine(1.2); }
else {
gdi.addString("", 0, "HTML formaterad genom listinställningar");
}
gdi.dropLine(1.8);
gdi.setCX(cx); gdi.setCX(cx);
gdi.addInput("ExportScript", exportScript, 32, 0, L"Skript att köra efter export:"); gdi.addInput("ExportScript", exportScript, 32, 0, L"Skript att köra efter export:");
gdi.dropLine(0.7); gdi.dropLine(0.7);
@ -730,16 +750,17 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
gdi.setInputStatus("ExportScript", doExport); gdi.setInputStatus("ExportScript", doExport);
gdi.setInputStatus("BrowseFile", doExport); gdi.setInputStatus("BrowseFile", doExport);
gdi.setInputStatus("BrowseScript", doExport); gdi.setInputStatus("BrowseScript", doExport);
gdi.setInputStatus("StructuredExport", doExport);
gdi.setInputStatus("HTMLRefresh", doExport);
gdi.setInputStatus("PrinterSetup", doPrint); gdi.setInputStatus("PrinterSetup", doPrint);
if (!readOnly) { if (!readOnly) {
gdi.setInputStatus("StructuredExport", doExport);
gdi.setInputStatus("HTMLRefresh", doExport);
gdi.fillDown(); gdi.fillDown();
gdi.addString("", 1, "Listval"); gdi.addString("", fontMediumPlus, "Listval");
gdi.dropLine(); gdi.dropLine();
gdi.fillRight(); gdi.fillRight();
gdi.addListBox("Classes", 150,300,0, L"", L"", true); gdi.addListBox("Classes", 150, 300, 0, L"", L"", true);
gdi.pushX(); gdi.pushX();
gdi.fillDown(); gdi.fillDown();
vector< pair<wstring, size_t> > d; vector< pair<wstring, size_t> > d;
@ -771,6 +792,8 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
gdi.selectItemByData("LegNumber", listInfo.getLegNumberCoded()); gdi.selectItemByData("LegNumber", listInfo.getLegNumberCoded());
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, pageBreak); gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, pageBreak);
gdi.addCheckbox("ShowHeader", "Visa rubrik", 0, showHeader);
gdi.addCheckbox("ShowInterResults", "Visa mellantider", 0, showInterResult, gdi.addCheckbox("ShowInterResults", "Visa mellantider", 0, showInterResult,
"Mellantider visas för namngivna kontroller."); "Mellantider visas för namngivna kontroller.");
gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, splitAnalysis); gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, splitAnalysis);
@ -784,7 +807,8 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
} }
else { else {
gdi.fillDown(); gdi.fillDown();
gdi.addString("", 1, L"Lista av typ 'X'#" + listInfo.getName()); gdi.addString("", fontMediumPlus, L"Lista av typ 'X'#" + listInfo.getName());
gdi.dropLine();
gdi.addCheckbox("OnlyChanged", "Skriv endast ut ändade sidor", 0, po.onlyChanged); gdi.addCheckbox("OnlyChanged", "Skriv endast ut ändade sidor", 0, po.onlyChanged);
} }
} }
@ -804,7 +828,7 @@ void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
if (doPrint) { if (doPrint) {
gdiPrint.refresh(); gdiPrint.refresh();
try { try {
gdiPrint.print(po, oe); gdiPrint.print(po, oe, true, false, listInfo.getParam().pageBreak);
} }
catch (const meosException &ex) { catch (const meosException &ex) {
printError = ex.wwhat(); printError = ex.wwhat();
@ -814,10 +838,19 @@ void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
} }
if (doExport) { if (doExport) {
if (!exportFile.empty()) { if (!exportFile.empty()) {
checkWriteAccess(exportFile);
wstring tExport = exportFile + L"~";
if (!readOnly) {
if (structuredExport) if (structuredExport)
gdiPrint.writeTableHTML(exportFile, oe->getName(), htmlRefresh); HTMLWriter::writeTableHTML(gdiPrint, tExport, oe->getName(), htmlRefresh, 1.0);
else else
gdiPrint.writeHTML(exportFile, oe->getName(), htmlRefresh); HTMLWriter::writeHTML(gdiPrint, tExport, oe->getName(), htmlRefresh, 1.0);
}
else {
HTMLWriter::write(gdiPrint, tExport, oe->getName(), 0, listInfo.getParam(), *oe);
}
DeleteFile(exportFile.c_str());
MoveFile(tExport.c_str(), exportFile.c_str());
if (!exportScript.empty()) { if (!exportScript.empty()) {
ShellExecute(NULL, NULL, exportScript.c_str(), exportFile.c_str(), NULL, SW_HIDE); ShellExecute(NULL, NULL, exportScript.c_str(), exportFile.c_str(), NULL, SW_HIDE);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -44,6 +44,9 @@ enum Machines {
mOnlineInput, mOnlineInput,
mSaveBackup, mSaveBackup,
mInfoService, mInfoService,
mMySQLReconnect,
Unknown = -1,
}; };
class AutoMachine class AutoMachine
@ -51,6 +54,8 @@ class AutoMachine
private: private:
int myid; int myid;
static int uniqueId; static int uniqueId;
const Machines type;
protected: protected:
bool editMode; bool editMode;
@ -76,7 +81,12 @@ public:
virtual void status(gdioutput &gdi) = 0; virtual void status(gdioutput &gdi) = 0;
virtual bool stop() {return true;} virtual bool stop() {return true;}
virtual AutoMachine *clone() const = 0; virtual AutoMachine *clone() const = 0;
AutoMachine(const string &s) : myid(uniqueId++), name(s), interval(0), timeout(0),
Machines getType() {
return type;
};
AutoMachine(const string &s, Machines type) : myid(uniqueId++), type(type), name(s), interval(0), timeout(0),
synchronize(false), synchronizePunches(false), editMode(false) {} synchronize(false), synchronizePunches(false), editMode(false) {}
virtual ~AutoMachine() = 0 {} virtual ~AutoMachine() = 0 {}
}; };
@ -93,6 +103,7 @@ protected:
PrinterObject po; PrinterObject po;
set<int> classesToPrint; set<int> classesToPrint;
bool pageBreak; bool pageBreak;
bool showHeader;
bool showInterResult; bool showInterResult;
bool splitAnalysis; bool splitAnalysis;
bool notShown; bool notShown;
@ -112,9 +123,18 @@ public:
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast); void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
void settings(gdioutput &gdi, oEvent &oe, bool created); void settings(gdioutput &gdi, oEvent &oe, bool created);
PrintResultMachine(int v):AutoMachine("Resultatutskrift") { void setHTML(const wstring &file, int timeout) {
exportFile = file;
doExport = true;
doPrint = false;
if (timeout > 0)
interval = timeout;
}
PrintResultMachine(int v):AutoMachine("Resultatutskrift", Machines::mPrintResultsMachine) {
interval=v; interval=v;
pageBreak = true; pageBreak = true;
showHeader = false;
showInterResult = true; showInterResult = true;
notShown = true; notShown = true;
splitAnalysis = true; splitAnalysis = true;
@ -126,9 +146,10 @@ public:
structuredExport = true; structuredExport = true;
htmlRefresh = v; htmlRefresh = v;
} }
PrintResultMachine(int v, const oListInfo &li):AutoMachine("Utskrift / export"), listInfo(li) { PrintResultMachine(int v, const oListInfo &li):AutoMachine("Utskrift / export", Machines::mPrintResultsMachine), listInfo(li) {
interval=v; interval=v;
pageBreak = true; pageBreak = true;
showHeader = false;
showInterResult = true; showInterResult = true;
notShown = true; notShown = true;
splitAnalysis = true; splitAnalysis = true;
@ -160,7 +181,7 @@ public:
void settings(gdioutput &gdi, oEvent &oe, bool created); void settings(gdioutput &gdi, oEvent &oe, bool created);
void saveSettings(gdioutput &gdi); void saveSettings(gdioutput &gdi);
SaveMachine():AutoMachine("Säkerhetskopiera") , saveIter(0) { SaveMachine():AutoMachine("Säkerhetskopiera", Machines::mSaveBackup) , saveIter(0) {
} }
}; };
@ -177,7 +198,7 @@ public:
PrewarningMachine *clone() const {return new PrewarningMachine(*this);} PrewarningMachine *clone() const {return new PrewarningMachine(*this);}
void status(gdioutput &gdi); void status(gdioutput &gdi);
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast); void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
PrewarningMachine():AutoMachine("Förvarningsröst") {} PrewarningMachine():AutoMachine("Förvarningsröst", Machines::mPrewarningMachine) {}
friend class TabAuto; friend class TabAuto;
}; };
@ -212,7 +233,7 @@ public:
void settings(gdioutput &gdi, oEvent &oe, bool created); void settings(gdioutput &gdi, oEvent &oe, bool created);
void status(gdioutput &gdi); void status(gdioutput &gdi);
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast); void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
PunchMachine():AutoMachine("Stämplingsautomat"), radio(0) {} PunchMachine():AutoMachine("Stämplingsautomat", Machines::mPunchMachine), radio(0) {}
friend class TabAuto; friend class TabAuto;
}; };
@ -228,7 +249,7 @@ public:
void settings(gdioutput &gdi, oEvent &oe, bool created); void settings(gdioutput &gdi, oEvent &oe, bool created);
void status(gdioutput &gdi); void status(gdioutput &gdi);
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast); void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
SplitsMachine() : AutoMachine("Sträcktider/WinSplits"), leg(-1) {} SplitsMachine() : AutoMachine("Sträcktider/WinSplits", Machines::mSplitsMachine), leg(-1) {}
friend class TabAuto; friend class TabAuto;
}; };
@ -271,7 +292,10 @@ public:
int processButton(gdioutput &gdi, const ButtonInfo &bu); int processButton(gdioutput &gdi, const ButtonInfo &bu);
int processListBox(gdioutput &gdi, const ListBoxInfo &bu); int processListBox(gdioutput &gdi, const ListBoxInfo &bu);
bool loadPage(gdioutput &gdi); bool loadPage(gdioutput &gdi, bool showSettingsLast);
bool loadPage(gdioutput &gdi) {
return loadPage(gdi, false);
}
const char * getTypeStr() const {return "TAutoTab";} const char * getTypeStr() const {return "TAutoTab";}
TabType getType() const {return TAutoTab;} TabType getType() const {return TAutoTab;}

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -42,6 +42,7 @@
#include "gdifonts.h" #include "gdifonts.h"
#include "oEventDraw.h" #include "oEventDraw.h"
#include "MeOSFeatures.h" #include "MeOSFeatures.h"
#include "qualification_final.h"
extern pEvent gEvent; extern pEvent gEvent;
const char *visualDrawWindow = "visualdraw"; const char *visualDrawWindow = "visualdraw";
@ -109,6 +110,23 @@ TabClass::~TabClass(void)
{ {
} }
oEvent::DrawMethod TabClass::getDefaultMethod(const set<oEvent::DrawMethod> &allowedValues) const {
oEvent::DrawMethod dm = (oEvent::DrawMethod)oe->getPropertyInt("DefaultDrawMethod", (int)oEvent::DrawMethod::MeOS);
if (allowedValues.count(dm))
return dm;
else
return oEvent::DrawMethod::MeOS;
}
void TabClass::createDrawMethod(gdioutput& gdi) {
gdi.addSelection("Method", 200, 200, 0, L"Metod:");
gdi.addItem("Method", lang.tl("Lottning") + L" (MeOS)", int(oEvent::DrawMethod::MeOS));
gdi.addItem("Method", lang.tl("Lottning"), int(oEvent::DrawMethod::Random));
gdi.addItem("Method", lang.tl("SOFT-lottning"), int(oEvent::DrawMethod::SOFT));
gdi.selectItemByData("Method", (int)getDefaultMethod({ oEvent::DrawMethod::Random, oEvent::DrawMethod::SOFT, oEvent::DrawMethod::MeOS }));
}
bool ClassInfoSortStart(ClassInfo &ci1, ClassInfo &ci2) bool ClassInfoSortStart(ClassInfo &ci1, ClassInfo &ci2)
{ {
return ci1.firstStart>ci2.firstStart; return ci1.firstStart>ci2.firstStart;
@ -237,6 +255,8 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id == "AssignCourses") { else if (bi.id == "AssignCourses") {
set<int> selectedCourses, selectedLegs; set<int> selectedCourses, selectedLegs;
pClass pc = oe->getClass(ClassId);
gdi.getSelection("AllCourses", selectedCourses); gdi.getSelection("AllCourses", selectedCourses);
gdi.getSelection("AllStages", selectedLegs); gdi.getSelection("AllStages", selectedLegs);
for (set<int>::iterator it = selectedLegs.begin(); it != selectedLegs.end(); ++it) { for (set<int>::iterator it = selectedLegs.begin(); it != selectedLegs.end(); ++it) {
@ -248,7 +268,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
bool empty = true; bool empty = true;
for (size_t k = 0; k < forkingSetup.size(); k++) { for (size_t k = 0; k < forkingSetup.size(); k++) {
if (forkingSetup[k].empty()) { if (forkingSetup[k].empty()) {
gdi.setText("leg"+ itos(k), lang.tl("Leg X: Do not modify.#" + itos(k+1))); gdi.setText("leg"+ itos(k), lang.tl(L"Leg X: Do not modify.#" + pc->getLegNumber(k)));
} }
else { else {
empty = false; empty = false;
@ -262,7 +282,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
break; break;
} }
} }
gdi.setText("leg"+ itos(k), lang.tl(L"Leg X: Use Y.#" + itow(k+1) + L"#" + crs)); gdi.setText("leg"+ itos(k), lang.tl(L"Leg X: Use Y.#" + pc->getLegNumber(k) + L"#" + crs));
} }
} }
gdi.setInputStatus("ApplyForking", !empty); gdi.setInputStatus("ApplyForking", !empty);
@ -374,8 +394,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
pc->setNumStages(0); pc->setNumStages(0);
pc->synchronize(); pc->synchronize();
gdi.restore(); gdi.restore();
gdi.enableInput("MultiCourse", true); selectClass(gdi, ClassId);
gdi.enableInput("Courses");
} }
else if (bi.id=="SetNStage") { else if (bi.id=="SetNStage") {
if (!checkClassSelected(gdi)) if (!checkClassSelected(gdi))
@ -441,8 +460,10 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
save(gdi, false); //Clears and reloads save(gdi, false); //Clears and reloads
if (gdi.hasField("Courses")) {
gdi.selectItemByData("Courses", -2); gdi.selectItemByData("Courses", -2);
gdi.disableInput("Courses"); gdi.disableInput("Courses");
}
oe->setupRelay(*pc, newType, nstages, st); oe->setupRelay(*pc, newType, nstages, st);
if (gdi.hasField("MAdd")) { if (gdi.hasField("MAdd")) {
@ -458,6 +479,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
pc->synchronize(); pc->synchronize();
gdi.restore(); gdi.restore();
gdi.enableInput("MultiCourse", true); gdi.enableInput("MultiCourse", true);
if (gdi.hasField("Courses"))
gdi.enableInput("Courses"); gdi.enableInput("Courses");
oe->adjustTeamMultiRunners(pc); oe->adjustTeamMultiRunners(pc);
} }
@ -837,6 +859,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
if (classes.empty()) { if (classes.empty()) {
gdi.dropLine();
gdi.addButton("DrawMode", L"Återgå", ClassesCB);
gdi.scrollToBottom();
throw meosException("Ingen klass vald."); throw meosException("Ingen klass vald.");
} }
@ -855,8 +880,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
else if (bi.id=="DoDrawAll") { else if (bi.id=="DoDrawAll") {
readClassSettings(gdi); readClassSettings(gdi);
int method = gdi.getSelectedItem("Method").first; oEvent::DrawMethod method = (oEvent::DrawMethod)gdi.getSelectedItem("Method").first;
bool soft = method == DMSOFT;
int pairSize = gdi.getSelectedItem("PairSize").first; int pairSize = gdi.getSelectedItem("PairSize").first;
bool drawCoursebased = drawInfo.coursesTogether; bool drawCoursebased = drawInfo.coursesTogether;
@ -885,7 +909,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
for (map<int, vector<ClassDrawSpecification> >::iterator it = specs.begin(); for (map<int, vector<ClassDrawSpecification> >::iterator it = specs.begin();
it != specs.end(); ++it) { it != specs.end(); ++it) {
oe->drawList(it->second, soft, pairSize, oEvent::drawAll); oe->drawList(it->second, method, pairSize, oEvent::DrawType::DrawAll);
} }
oe->addAutoBib(); oe->addAutoBib();
@ -944,6 +968,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
prepareForDrawing(gdi); prepareForDrawing(gdi);
} }
else if (bi.id == "DrawMode") { else if (bi.id == "DrawMode") {
if (gdi.hasField("Name"))
save(gdi, false); save(gdi, false);
ClassId = 0; ClassId = 0;
@ -961,10 +986,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
gdi.addInput("Vacances", L"5%", 10, 0, L"Andel vakanser:"); gdi.addInput("Vacances", L"5%", 10, 0, L"Andel vakanser:");
gdi.popX(); gdi.popX();
gdi.addSelection("Method", 200, 200, 0, L"Metod:"); createDrawMethod(gdi);
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
gdi.selectItemByData("Method", getDefaultMethod({ DMRandom, DMSOFT }));
gdi.fillDown(); gdi.fillDown();
gdi.addCheckbox("LateBefore", "Efteranmälda före ordinarie"); gdi.addCheckbox("LateBefore", "Efteranmälda före ordinarie");
@ -1104,11 +1126,21 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
pairSize = gdi.getSelectedItem("PairSize").first; pairSize = gdi.getSelectedItem("PairSize").first;
} }
int method = gdi.getSelectedItem("Method").first; oEvent::DrawMethod method = (oEvent::DrawMethod)gdi.getSelectedItem("Method").first;
bool useSoft = method == DMSOFT;
int baseInterval = convertAbsoluteTimeMS(minInterval) / 2;
if (baseInterval<1 || baseInterval>60 * 60 || baseInterval == NOTIME)
throw meosException("Ogiltigt minimalt intervall.");
int iFirstStart = oe->getRelativeTime(firstStart);
if (iFirstStart <= 0 || iFirstStart == NOTIME)
throw meosException("Ogiltig första starttid. Måste vara efter nolltid.");
clearPage(gdi, true); clearPage(gdi, true);
oe->automaticDrawAll(gdi, firstStart, minInterval, vacances, oe->automaticDrawAll(gdi, firstStart, minInterval, vacances,
lateBefore, useSoft, pairSize); lateBefore, method, pairSize);
oe->addAutoBib(); oe->addAutoBib();
gdi.scrollToBottom(); gdi.scrollToBottom();
gdi.addButton("Cancel", "Återgå", ClassesCB); gdi.addButton("Cancel", "Återgå", ClassesCB);
@ -1262,6 +1294,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
readDrawInfo(gdi, drawInfo); readDrawInfo(gdi, drawInfo);
if (drawInfo.baseInterval <= 0 || drawInfo.baseInterval == NOTIME) if (drawInfo.baseInterval <= 0 || drawInfo.baseInterval == NOTIME)
throw meosException("Ogiltigt basintervall."); throw meosException("Ogiltigt basintervall.");
if (drawInfo.firstStart <= 0 || drawInfo.firstStart == NOTIME)
throw meosException("Ogiltig första starttid. Måste vara efter nolltid.");
if (drawInfo.minClassInterval <= 0 || drawInfo.minClassInterval == NOTIME) if (drawInfo.minClassInterval <= 0 || drawInfo.minClassInterval == NOTIME)
throw meosException("Ogiltigt minimalt intervall."); throw meosException("Ogiltigt minimalt intervall.");
if (drawInfo.minClassInterval > drawInfo.maxClassInterval || drawInfo.maxClassInterval == NOTIME) if (drawInfo.minClassInterval > drawInfo.maxClassInterval || drawInfo.maxClassInterval == NOTIME)
@ -1277,12 +1312,6 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
} }
gdi.enableEditControls(false); gdi.enableEditControls(false);
if (drawInfo.firstStart<=0) {
drawInfo.baseInterval = 0;
gdi.addString("", 0, "Raderar starttider...");
}
oe->optimizeStartOrder(gdi, drawInfo, cInfo); oe->optimizeStartOrder(gdi, drawInfo, cInfo);
showClassSettings(gdi); showClassSettings(gdi);
@ -1340,7 +1369,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
for (set<int>::const_iterator it = classes.begin(); it != classes.end(); ++it) { for (set<int>::const_iterator it = classes.begin(); it != classes.end(); ++it) {
vector<ClassDrawSpecification> spec; vector<ClassDrawSpecification> spec;
spec.push_back(ClassDrawSpecification(*it, 0, 0, 0, 0)); spec.push_back(ClassDrawSpecification(*it, 0, 0, 0, 0));
oe->drawList(spec, false, 1, oEvent::drawAll); oe->drawList(spec, oEvent::DrawMethod::Random, 1, oEvent::DrawType::DrawAll);
} }
if (bi.getExtraInt() == 1) if (bi.getExtraInt() == 1)
@ -1363,7 +1392,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
return classCB(gdi, type, &bi); return classCB(gdi, type, &bi);
} }
else if (bi.id == "DrawAllBefore" || bi.id == "DrawAllAfter") { else if (bi.id == "DrawAllBefore" || bi.id == "DrawAllAfter") {
oe->drawRemaining(true, bi.id == "DrawAllAfter"); oe->drawRemaining(oEvent::DrawMethod::MeOS, bi.id == "DrawAllAfter");
oe->addAutoBib(); oe->addAutoBib();
loadPage(gdi); loadPage(gdi);
} }
@ -1373,7 +1402,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
DWORD cid=ClassId; DWORD cid=ClassId;
pClass pc = oe->getClass(cid); pClass pc = oe->getClass(cid);
DrawMethod method = DrawMethod(gdi.getSelectedItem("Method").first); oEvent::DrawMethod method = oEvent::DrawMethod(gdi.getSelectedItem("Method").first);
int interval = 0; int interval = 0;
if (gdi.hasField("Interval")) if (gdi.hasField("Interval"))
@ -1405,11 +1434,11 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
throw std::exception("Ogiltig första starttid. Måste vara efter nolltid."); throw std::exception("Ogiltig första starttid. Måste vara efter nolltid.");
oEvent::DrawType dtype(oEvent::drawAll); oEvent::DrawType dtype(oEvent::DrawType::DrawAll);
if (bi.id=="DoDrawAfter") if (bi.id=="DoDrawAfter")
dtype = oEvent::remainingAfter; dtype = oEvent::DrawType::RemainingAfter;
else if (bi.id=="DoDrawBefore") else if (bi.id=="DoDrawBefore")
dtype = oEvent::remainingBefore; dtype = oEvent::DrawType::RemainingBefore;
else { else {
if (warnDrawStartTime(gdi, t, false)) if (warnDrawStartTime(gdi, t, false))
return 0; return 0;
@ -1435,24 +1464,24 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (gdi.hasField("ScaleFactor")) if (gdi.hasField("ScaleFactor"))
scaleFactor = _wtof(gdi.getText("ScaleFactor").c_str()); scaleFactor = _wtof(gdi.getText("ScaleFactor").c_str());
if (method == DMRandom || method == DMSOFT) { if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::MeOS) {
vector<ClassDrawSpecification> spec; vector<ClassDrawSpecification> spec;
spec.push_back(ClassDrawSpecification(cid, leg, t, interval, vacanses)); spec.push_back(ClassDrawSpecification(cid, leg, t, interval, vacanses));
oe->drawList(spec, method == DMSOFT, pairSize, dtype); oe->drawList(spec, method, pairSize, dtype);
} }
else if (method == DMClumped) else if (method == oEvent::DrawMethod::Clumped)
oe->drawListClumped(cid, t, interval, vacanses); oe->drawListClumped(cid, t, interval, vacanses);
else if (method == DMPursuit || method == DMReversePursuit) { else if (method == oEvent::DrawMethod::Pursuit || method == oEvent::DrawMethod::ReversePursuit) {
oe->drawPersuitList(cid, t, restartTime, maxTime, oe->drawPersuitList(cid, t, restartTime, maxTime,
interval, pairSize, interval, pairSize,
method == DMReversePursuit, method == oEvent::DrawMethod::ReversePursuit,
scaleFactor); scaleFactor);
} }
else if (method == DMSimultaneous) { else if (method == oEvent::DrawMethod::Simultaneous) {
simultaneous(cid, time); simultaneous(cid, time);
} }
else if (method == DMSeeded) { else if (method == oEvent::DrawMethod::Seeded) {
ListBoxInfo seedMethod; ListBoxInfo seedMethod;
gdi.getSelectedItem("SeedMethod", seedMethod); gdi.getSelectedItem("SeedMethod", seedMethod);
wstring seedGroups = gdi.getText("SeedGroups"); wstring seedGroups = gdi.getText("SeedGroups");
@ -1525,7 +1554,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
vector<ClassDrawSpecification> spec; vector<ClassDrawSpecification> spec;
spec.push_back(ClassDrawSpecification(ClassId, leg, 0, 0, 0)); spec.push_back(ClassDrawSpecification(ClassId, leg, 0, 0, 0));
oe->drawList(spec, false, 1, oEvent::drawAll); oe->drawList(spec, oEvent::DrawMethod::Random, 1, oEvent::DrawType::DrawAll);
loadPage(gdi); loadPage(gdi);
} }
else if (bi.id=="Draw") { else if (bi.id=="Draw") {
@ -1567,7 +1596,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
gdi.setRestorePoint("MultiDayDraw"); gdi.setRestorePoint("MultiDayDraw");
lastDrawMethod = NOMethod; lastDrawMethod = oEvent::DrawMethod::NOMethod;
drawDialog(gdi, getDefaultMethod(getSupportedDrawMethods(multiDay)), *pc); drawDialog(gdi, getDefaultMethod(getSupportedDrawMethods(multiDay)), *pc);
} }
else if (bi.id == "HandleMultiDay") { else if (bi.id == "HandleMultiDay") {
@ -1578,15 +1607,15 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (!pc) if (!pc)
throw std::exception("Class not found"); throw std::exception("Class not found");
if (!gdi.isChecked(bi.id) && (lastDrawMethod == DMReversePursuit || if (!gdi.isChecked(bi.id) && (lastDrawMethod == oEvent::DrawMethod::ReversePursuit ||
lastDrawMethod == DMPursuit)) { lastDrawMethod == oEvent::DrawMethod::Pursuit)) {
drawDialog(gdi, DMSOFT, *pc); drawDialog(gdi, oEvent::DrawMethod::MeOS, *pc);
} }
else else
setMultiDayClass(gdi, gdi.isChecked(bi.id), lastDrawMethod); setMultiDayClass(gdi, gdi.isChecked(bi.id), lastDrawMethod);
} }
else if (bi.id == "QualificationFinal") { else if (bi.id == "QualificationFinal" || bi.id == "UpdateQF") {
save(gdi, true); save(gdi, true);
pClass pc = oe->getClass(ClassId); pClass pc = oe->getClass(ClassId);
if (!pc) if (!pc)
@ -1599,6 +1628,32 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
pc->updateFinalClasses(0, true); pc->updateFinalClasses(0, true);
loadPage(gdi); loadPage(gdi);
} }
else if (bi.id == "RemoveQF") {
pClass pc = oe->getClass(ClassId);
if (!pc)
throw std::exception("Class not found");
if (pc->getQualificationFinal()) {
bool hasResult = false;
for (int inst = 0; inst < pc->getQualificationFinal()->getNumClasses(); inst++) {
auto vc = pc->getVirtualClass(inst);
if (vc && oe->classHasResults(vc->getId())) {
hasResult = true;
}
}
if (hasResult) {
if (!gdi.ask(L"Det finns resultat som går förlorade om du tar bort schemat. Vill du fortsätta?"))
return 0;
}
else {
if (!gdi.ask(L"Vill du ta bort schemat?"))
return 0;
}
pc->getDI().setString("Qualification", L"");
pc->clearQualificationFinal();
pc->synchronize(true);
selectClass(gdi, pc->getId());
}
}
else if (bi.id=="Bibs") { else if (bi.id=="Bibs") {
save(gdi, true); save(gdi, true);
if (!checkClassSelected(gdi)) if (!checkClassSelected(gdi))
@ -1722,6 +1777,28 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
pClass pc=oe->getClass(ClassId); pClass pc=oe->getClass(ClassId);
if (!pc) if (!pc)
throw std::exception("Class not found"); throw std::exception("Class not found");
if (pc->getQualificationFinal() || (pc->getParentClass() && pc->getParentClass()->getQualificationFinal())) {
set<int> base;
if (pc->getParentClass()) {
pClass baseClass = pc->getParentClass();
baseClass->getQualificationFinal()->getBaseClassInstances(base);
int inst = (pc->getId() - baseClass->getId()) / MaxClassId;
// Change to base class
pc = baseClass;
ClassId = pc->getId();
if (!base.count(inst)) {
throw meosException("Operationen stöds inte på en finalklass");
}
}
else {
pc->getQualificationFinal()->getBaseClassInstances(base);
}
if (base.size() <= 1) {
throw meosException("Kval-Final-schemat har endast en basklass");
}
}
clearPage(gdi, true); clearPage(gdi, true);
gdi.addString("", boldLarge, L"Dela klass: X#" + pc->getName()); gdi.addString("", boldLarge, L"Dela klass: X#" + pc->getName());
@ -1738,18 +1815,39 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
oClass::getSplitMethods(mt); oClass::getSplitMethods(mt);
gdi.addItem("Type", mt); gdi.addItem("Type", mt);
gdi.selectFirstItem("Type"); gdi.selectFirstItem("Type");
int numSplitDef = 2;
if (pc->getQualificationFinal()) {
gdi.fillDown();
gdi.popX();
gdi.dropLine(3);
set<int> base;
pc->getQualificationFinal()->getBaseClassInstances(base);
gdi.addString("", 1, "Kval/final-schema");
for (int i : base) {
if (pc->getVirtualClass(i)) {
gdi.addStringUT(0, pc->getVirtualClass(i)->getName());
int tot2 = 0;
oe->getNumClassRunners(pc->getVirtualClass(i)->getId(), 0, tot2, fin, dns);
tot += tot2;
}
}
numSplitDef = base.size();
gdi.dropLine(1);
gdi.setData("NumCls", numSplitDef);
}
else {
gdi.addSelection("SplitInput", 100, 150, ClassesCB, L"Antal klasser:").setExtra(tot); gdi.addSelection("SplitInput", 100, 150, ClassesCB, L"Antal klasser:").setExtra(tot);
vector< pair<wstring, size_t> > sp; vector< pair<wstring, size_t> > sp;
for (int k = 2; k < 10; k++) for (int k = 2; k < 10; k++)
sp.push_back(make_pair(itow(k), k)); sp.push_back(make_pair(itow(k), k));
gdi.addItem("SplitInput", sp); gdi.addItem("SplitInput", sp);
gdi.selectFirstItem("SplitInput"); gdi.selectFirstItem("SplitInput");
gdi.dropLine(3); gdi.dropLine(3);
gdi.popX(); gdi.popX();
updateSplitDistribution(gdi, 2, tot); }
updateSplitDistribution(gdi, numSplitDef, tot);
} }
else if (bi.id=="DoSplit") { else if (bi.id=="DoSplit") {
if (!checkClassSelected(gdi)) if (!checkClassSelected(gdi))
@ -1761,9 +1859,17 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("Type", lbi); gdi.getSelectedItem("Type", lbi);
int number;
int number = gdi.getSelectedItem("SplitInput").first; if (gdi.hasData("NumCls")) {
DWORD dn;
number = gdi.getData("NumCls", dn);
number = dn;
}
else {
number = gdi.getSelectedItem("SplitInput").first;
}
vector<int> parts(number); vector<int> parts(number);
for (int k = 0; k < number; k++) { for (int k = 0; k < number; k++) {
string id = "CLS" + itos(k); string id = "CLS" + itos(k);
parts[k] = gdi.getTextNo(id, false); parts[k] = gdi.getTextNo(id, false);
@ -1983,7 +2089,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
if (!pc) if (!pc)
throw std::exception("Nullpointer exception"); throw std::exception("Nullpointer exception");
drawDialog(gdi, DrawMethod(bi.data), *pc); drawDialog(gdi, oEvent::DrawMethod(bi.data), *pc);
} }
} }
else if (type==GUI_INPUTCHANGE) { else if (type==GUI_INPUTCHANGE) {
@ -2251,11 +2357,7 @@ void TabClass::showClassSettings(gdioutput &gdi)
gdi.setCX(rc.left + gdi.scaleLength(10)); gdi.setCX(rc.left + gdi.scaleLength(10));
gdi.setCY(rc.top + gdi.scaleLength(10)); gdi.setCY(rc.top + gdi.scaleLength(10));
gdi.addSelection("Method", 200, 200, 0, L"Metod:"); createDrawMethod(gdi);
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
gdi.selectItemByData("Method", getDefaultMethod({DMRandom, DMSOFT}));
gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:"); gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:");
gdi.addItem("PairSize", getPairOptions()); gdi.addItem("PairSize", getPairOptions());
@ -2292,11 +2394,13 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
if (cid==0) { if (cid==0) {
gdi.restore("", true); gdi.restore("", true);
gdi.disableInput("MultiCourse", true); gdi.disableInput("MultiCourse", true);
if (gdi.hasField("Courses"))
gdi.enableInput("Courses"); gdi.enableInput("Courses");
gdi.enableEditControls(false); gdi.enableEditControls(false);
gdi.setText("Name", L""); gdi.setText("Name", L"");
gdi.selectItemByData("Courses", -2); gdi.selectItemByData("Courses", -2);
gdi.check("AllowQuickEntry", true); gdi.check("AllowQuickEntry", true);
gdi.setText("NumberMaps", L"");
if (gdi.hasField("FreeStart")) if (gdi.hasField("FreeStart"))
gdi.check("FreeStart", false); gdi.check("FreeStart", false);
@ -2333,6 +2437,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
pc->synchronize(); pc->synchronize();
gdi.setText("Name", pc->getName()); gdi.setText("Name", pc->getName());
gdi.setTextZeroBlank("NumberMaps", pc->getNumberMaps(true));
gdi.setText("ClassType", pc->getType()); gdi.setText("ClassType", pc->getType());
gdi.setText("StartName", pc->getStart()); gdi.setText("StartName", pc->getStart());
@ -2368,16 +2473,46 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
} }
ClassId=cid; ClassId=cid;
if (pc->hasTrueMultiCourse()) { if (pc->getQualificationFinal()) {
gdi.restore("", false);
gdi.enableInput("MultiCourse", false);
if (gdi.hasField("Courses")) {
gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
}
gdi.setRestorePoint();
gdi.fillDown();
gdi.newColumn();
int cx = gdi.getCX(), cy = gdi.getCY();
gdi.setCX(cx + 10);
gdi.setCY(cy + 10);
gdi.addString("", fontMediumPlus, "Kval/final-schema");
gdi.pushX();
gdi.dropLine(0.3);
gdi.fillRight();
gdi.addButton("UpdateQF", "Uppdatera", ClassesCB);
gdi.fillDown();
gdi.addButton("RemoveQF", "Ta bort", ClassesCB);
gdi.popX();
pc->getQualificationFinal()->printScheme(pc, gdi);
}
else if (pc->hasTrueMultiCourse()) {
gdi.restore("", false); gdi.restore("", false);
multiCourse(gdi, pc->getNumStages()); multiCourse(gdi, pc->getNumStages());
gdi.refresh(); gdi.refresh();
if (gdi.hasField("Courses")) {
gdi.addItem("Courses", lang.tl("Flera banor"), -3); gdi.addItem("Courses", lang.tl("Flera banor"), -3);
gdi.selectItemByData("Courses", -3); gdi.selectItemByData("Courses", -3);
gdi.disableInput("Courses"); gdi.disableInput("Courses");
gdi.check("CoursePool", pc->hasCoursePool()); gdi.check("CoursePool", pc->hasCoursePool());
}
if (gdi.hasField("Unordered")) if (gdi.hasField("Unordered"))
gdi.check("Unordered", pc->hasUnorderedLegs()); gdi.check("Unordered", pc->hasUnorderedLegs());
@ -2432,9 +2567,11 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
else { else {
gdi.restore("", true); gdi.restore("", true);
gdi.enableInput("MultiCourse", true); gdi.enableInput("MultiCourse", true);
if (gdi.hasField("Courses")) {
gdi.enableInput("Courses"); gdi.enableInput("Courses");
pCourse pcourse = pc->getCourse(); pCourse pcourse = pc->getCourse();
gdi.selectItemByData("Courses", pcourse ? pcourse->getId():-2); gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
}
} }
if (gdi.hasField("QualificationFinal")) if (gdi.hasField("QualificationFinal"))
gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0); gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0);
@ -2490,14 +2627,14 @@ void TabClass::legSetup(gdioutput &gdi)
void TabClass::multiCourse(gdioutput &gdi, int nLeg) { void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
currentStage=-1; currentStage=-1;
pClass pc = oe->getClass(ClassId);
bool simpleView = nLeg==1; bool isQF = (pc && pc->isQualificationFinalClass());
bool simpleView = nLeg==1 || isQF;
bool showGuide = (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Relay) || bool showGuide = (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Relay) ||
oe->getMeOSFeatures().hasFeature(MeOSFeatures::Patrol)) && nLeg==0; oe->getMeOSFeatures().hasFeature(MeOSFeatures::Patrol)) && nLeg==0 && !isQF;
if (nLeg == 0 && !showGuide) { if (nLeg == 0 && !showGuide) {
pClass pc = oe->getClass(ClassId);
if (pc) { if (pc) {
pc->setNumStages(1); pc->setNumStages(1);
pc->setStartType(0, STDrawn, false); pc->setStartType(0, STDrawn, false);
@ -2512,7 +2649,6 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
gdi.fillDown(); gdi.fillDown();
gdi.newColumn(); gdi.newColumn();
int cx=gdi.getCX(), cy=gdi.getCY(); int cx=gdi.getCX(), cy=gdi.getCY();
gdi.setCX(cx+10); gdi.setCX(cx+10);
gdi.setCY(cy+10); gdi.setCY(cy+10);
@ -2551,6 +2687,9 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false, gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false,
"Knyt löparna till banor från en pool vid målgång."); "Knyt löparna till banor från en pool vid målgång.");
gdi.addCheckbox("LockForking", "Lås gafflingar", MultiCB, false,
"Markera för att förhindra oavsiktlig ändring av gafflingsnycklar.");
gdi.addButton("OneCourse", "Endast en bana", MultiCB, "Använd endast en bana i klassen"); gdi.addButton("OneCourse", "Endast en bana", MultiCB, "Använd endast en bana i klassen");
gdi.setRestorePoint("Courses"); gdi.setRestorePoint("Courses");
selectCourses(gdi, 0); selectCourses(gdi, 0);
@ -2627,6 +2766,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
} }
gdi.dropLine(-0.1); gdi.dropLine(-0.1);
if (oe->getMeOSFeatures().withCourses(oe))
gdi.addButton(string("@Course")+legno, "Banor...", MultiCB); gdi.addButton(string("@Course")+legno, "Banor...", MultiCB);
gdi.fillDown(); gdi.fillDown();
@ -2648,6 +2788,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
} }
gdi.pushX(); gdi.pushX();
if (oe->getMeOSFeatures().withCourses(oe)) {
gdi.fillRight(); gdi.fillRight();
gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false, gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false,
"Knyt löparna till banor från en pool vid målgång."); "Knyt löparna till banor från en pool vid målgång.");
@ -2667,6 +2808,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
gdi.addButton("DefineForking", "Define forking...", MultiCB); gdi.addButton("DefineForking", "Define forking...", MultiCB);
gdi.popX(); gdi.popX();
}
RECT rc; RECT rc;
rc.left = cx; rc.left = cx;
rc.right = gdi.getWidth()+10; rc.right = gdi.getWidth()+10;
@ -2676,7 +2818,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
gdi.setRestorePoint("Courses"); gdi.setRestorePoint("Courses");
if (nLeg==1) if (nLeg==1 && oe->getMeOSFeatures().withCourses(oe))
gdi.sendCtrlMessage("@Course0"); gdi.sendCtrlMessage("@Course0");
} }
@ -2721,6 +2863,10 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
ClassId=pc->getId(); ClassId=pc->getId();
pc->setName(name); pc->setName(name);
if (gdi.hasField("NumberMaps")) {
pc->setNumberMaps(gdi.getTextNo("NumberMaps"));
}
if (gdi.hasField("StartName")) if (gdi.hasField("StartName"))
pc->setStart(gdi.getText("StartName")); pc->setStart(gdi.getText("StartName"));
@ -2771,19 +2917,21 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
pc->lockedClassAssignment(locked); pc->lockedClassAssignment(locked);
} }
if (gdi.hasField("Courses")) {
int crs = gdi.getSelectedItem("Courses").first; int crs = gdi.getSelectedItem("Courses").first;
if (crs==0) { if (crs == 0) {
//Skapa ny bana... //Skapa ny bana...
pCourse pcourse=oe->addCourse(L"Bana " + name); pCourse pcourse = oe->addCourse(L"Bana " + name);
pc->setCourse(pcourse); pc->setCourse(pcourse);
pc->synchronize(); pc->synchronize();
return; return;
} }
else if (crs==-2) else if (crs == -2)
pc->setCourse(0); pc->setCourse(0);
else if (crs > 0) else if (crs > 0)
pc->setCourse(oe->getCourse(crs)); pc->setCourse(oe->getCourse(crs));
}
if (pc->hasMultiCourse()) { if (pc->hasMultiCourse()) {
@ -2890,16 +3038,16 @@ bool TabClass::loadPage(gdioutput &gdi)
oe->checkNecessaryFeatures(); oe->checkNecessaryFeatures();
gdi.selectTab(tabId); gdi.selectTab(tabId);
clearPage(gdi, false); clearPage(gdi, false);
int xp=gdi.getCX(); int xp = gdi.getCX();
const int button_w=gdi.scaleLength(90); const int button_w = gdi.scaleLength(90);
string switchMode; string switchMode;
switchMode=tableMode ? "Formulärläge" : "Tabelläge"; switchMode = tableMode ? "Formulärläge" : "Tabelläge";
gdi.addButton(2, 2, button_w, "SwitchMode", switchMode, gdi.addButton(2, 2, button_w, "SwitchMode", switchMode,
ClassesCB, "Välj vy", false, false).fixedCorner(); ClassesCB, "Välj vy", false, false).fixedCorner();
if (tableMode) { if (tableMode) {
Table *tbl=oe->getClassTB(); Table *tbl = oe->getClassTB();
gdi.addTable(tbl, xp, 30); gdi.addTable(tbl, xp, 30);
return true; return true;
} }
@ -2908,7 +3056,7 @@ bool TabClass::loadPage(gdioutput &gdi)
try { try {
defineForking(gdi, false); defineForking(gdi, false);
} }
catch(...) { catch (...) {
showForkingGuide = false; showForkingGuide = false;
throw; throw;
} }
@ -2933,23 +3081,28 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.addInput("Name", L"", 14, ClassesCB, L"Klassnamn:"); gdi.addInput("Name", L"", 14, ClassesCB, L"Klassnamn:");
bool sameLineNameCourse = true; bool sameLineNameCourse = true;
if (showAdvanced) { if (showAdvanced) {
gdi.addCombo("ClassType", 100, 300, 0, L"Typ:"); gdi.addCombo("ClassType", 80, 300, 0, L"Typ:");
oe->fillClassTypes(gdi, "ClassType"); oe->fillClassTypes(gdi, "ClassType");
sameLineNameCourse = false; sameLineNameCourse = false;
} }
bool useCourse = oe->getMeOSFeatures().withoutCourses(*oe) == false;
if (showMulti(false) || !sameLineNameCourse) { if (showMulti(false) && useCourse) {
gdi.addInput("NumberMaps", L"", 6, ClassesCB, L"Antal kartor:");
}
if (useCourse && (showMulti(false) || !sameLineNameCourse)) {
gdi.dropLine(3); gdi.dropLine(3);
gdi.popX(); gdi.popX();
} }
if (useCourse) {
gdi.addSelection("Courses", 120, 400, ClassesCB, L"Bana:"); gdi.addSelection("Courses", 120, 400, ClassesCB, L"Bana:");
oe->fillCourses(gdi, "Courses", true); oe->fillCourses(gdi, "Courses", true);
gdi.addItem("Courses", lang.tl("Ingen bana"), -2); gdi.addItem("Courses", lang.tl("Ingen bana"), -2);
}
if (showMulti(false)) { if (showMulti(false)) {
gdi.dropLine(0.9); gdi.dropLine(0.9);
if (showMulti(true)) { if (showMulti(true) || !useCourse) {
gdi.addButton("MultiCourse", "Flera banor/stafett...", ClassesCB); gdi.addButton("MultiCourse", "Flera banor/stafett...", ClassesCB);
} }
else { else {
@ -2957,6 +3110,9 @@ bool TabClass::loadPage(gdioutput &gdi)
} }
gdi.disableInput("MultiCourse"); gdi.disableInput("MultiCourse");
} }
else if (useCourse) {
gdi.addInput("NumberMaps", L"", 6, ClassesCB, L"Antal kartor:");
}
gdi.popX(); gdi.popX();
if (showAdvanced) { if (showAdvanced) {
@ -3077,7 +3233,7 @@ bool TabClass::loadPage(gdioutput &gdi)
func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true)); func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true));
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::MultipleRaces)) if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::MultipleRaces))
func.push_back(ButtonData("QualificationFinal", "Kval-Final-Schema", false)); func.push_back(ButtonData("QualificationFinal", "Kval/final-schema", false));
RECT funRect; RECT funRect;
funRect.right = gdi.getCX() - 7; funRect.right = gdi.getCX() - 7;
@ -3107,7 +3263,7 @@ bool TabClass::loadPage(gdioutput &gdi)
gdi.dropLine(2.5); gdi.dropLine(2.5);
funRect.bottom = gdi.getCY(); funRect.bottom = gdi.getCY();
gdi.addRectangle(funRect, colorLightGreen); gdi.addRectangle(funRect, colorLightBlue);
gdi.popX(); gdi.popX();
gdi.dropLine(0.5); gdi.dropLine(0.5);
@ -3246,22 +3402,25 @@ void TabClass::prepareForDrawing(gdioutput &gdi) {
gdi.refresh(); gdi.refresh();
} }
void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) { bool isInSameClass(oEvent::DrawMethod m1, oEvent::DrawMethod m2, const set<oEvent::DrawMethod> &cls) {
oe->setProperty("DefaultDrawMethod", method); return cls.count(m1) && cls.count(m2);
}
void TabClass::drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClass &pc) {
oe->setProperty("DefaultDrawMethod", (int)method);
if (lastDrawMethod == method) if (lastDrawMethod == method)
return; return;
bool noUpdate = false; bool noUpdate = false;
if (lastDrawMethod == DMPursuit && method == DMReversePursuit) if (isInSameClass(lastDrawMethod, method, { oEvent::DrawMethod::Pursuit,
noUpdate = true; oEvent::DrawMethod::ReversePursuit }))
if (lastDrawMethod == DMReversePursuit && method == DMPursuit)
noUpdate = true; noUpdate = true;
if (lastDrawMethod == DMRandom && method == DMSOFT) if (isInSameClass(lastDrawMethod, method, { oEvent::DrawMethod::Random,
noUpdate = true; oEvent::DrawMethod::SOFT,
if (lastDrawMethod == DMSOFT && method == DMRandom) oEvent::DrawMethod::MeOS }))
noUpdate = true; noUpdate = true;
if (noUpdate) { if (noUpdate) {
@ -3292,7 +3451,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
const bool multiDay = oe->hasPrevStage() && gdi.isChecked("HandleMultiDay"); const bool multiDay = oe->hasPrevStage() && gdi.isChecked("HandleMultiDay");
if (method == DMSeeded) { if (method == oEvent::DrawMethod::Seeded) {
gdi.addString("", 10, "help:seeding_info"); gdi.addString("", 10, "help:seeding_info");
gdi.dropLine(1); gdi.dropLine(1);
gdi.pushX(); gdi.pushX();
@ -3323,8 +3482,8 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
gdi.dropLine(1); gdi.dropLine(1);
} }
if (method == DMRandom || method == DMSOFT || method == DMPursuit if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::Pursuit
|| method == DMReversePursuit || method == DMSeeded) { || method == oEvent::DrawMethod::ReversePursuit || method == oEvent::DrawMethod::Seeded || method == oEvent::DrawMethod::MeOS) {
gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:").setSynchData(&lastPairSize); gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:").setSynchData(&lastPairSize);
gdi.addItem("PairSize", getPairOptions()); gdi.addItem("PairSize", getPairOptions());
gdi.selectItemByData("PairSize", pairSize); gdi.selectItemByData("PairSize", pairSize);
@ -3333,22 +3492,22 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:").setSynchData(&lastFirstStart); gdi.addInput("FirstStart", oe->getAbsTime(firstStart), 10, 0, L"Första start:").setSynchData(&lastFirstStart);
if (method == DMPursuit || method == DMReversePursuit) { if (method == oEvent::DrawMethod::Pursuit || method == oEvent::DrawMethod::ReversePursuit) {
gdi.addInput("MaxAfter", lastMaxAfter, 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart").setSynchData(&lastMaxAfter); gdi.addInput("MaxAfter", lastMaxAfter, 10, 0, L"Maxtid efter:", L"Maximal tid efter ledaren för att delta i jaktstart").setSynchData(&lastMaxAfter);
gdi.addInput("TimeRestart", oe->getAbsTime(firstStart + 3600), 8, 0, L"Första omstartstid:"); gdi.addInput("TimeRestart", oe->getAbsTime(firstStart + 3600), 8, 0, L"Första omstartstid:");
gdi.addInput("ScaleFactor", lastScaleFactor, 8, 0, L"Tidsskalning:").setSynchData(&lastScaleFactor); gdi.addInput("ScaleFactor", lastScaleFactor, 8, 0, L"Tidsskalning:").setSynchData(&lastScaleFactor);
} }
if (method != DMSimultaneous) if (method != oEvent::DrawMethod::Simultaneous)
gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval); gdi.addInput("Interval", formatTime(interval), 10, 0, L"Startintervall (min):").setSynchData(&lastInterval);
if (method == DMRandom || method == DMSOFT || method == DMClumped && pc.getParentClass() == 0) if ((method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::Clumped || method == oEvent::DrawMethod::MeOS) && pc.getParentClass() == 0)
gdi.addInput("Vacanses", itow(vac), 10, 0, L"Antal vakanser:").setSynchData(&lastNumVac); gdi.addInput("Vacanses", itow(vac), 10, 0, L"Antal vakanser:").setSynchData(&lastNumVac);
if ((method == DMRandom || method == DMSOFT || method == DMSeeded) && pc.getNumStages() > 1 && pc.getClassType() != oClassPatrol) { if ((method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::Seeded || method == oEvent::DrawMethod::MeOS) && pc.getNumStages() > 1 && pc.getClassType() != oClassPatrol) {
gdi.addSelection("Leg", 90, 100, 0, L"Sträcka:", L"Sträcka att lotta"); gdi.addSelection("Leg", 90, 100, 0, L"Sträcka:", L"Sträcka att lotta");
for (unsigned k = 0; k<pc.getNumStages(); k++) for (unsigned k = 0; k < pc.getNumStages(); k++)
gdi.addItem("Leg", lang.tl("Sträcka X#" + itos(k+1)), k); gdi.addItem("Leg", lang.tl("Sträcka X#" + itos(k + 1)), k);
gdi.selectFirstItem("Leg"); gdi.selectFirstItem("Leg");
} }
@ -3373,12 +3532,12 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
gdi.fillRight(); gdi.fillRight();
if (method != DMSimultaneous) if (method != oEvent::DrawMethod::Simultaneous)
gdi.addButton("DoDraw", "Lotta klassen", ClassesCB, "Lotta om hela klassen"); gdi.addButton("DoDraw", "Lotta klassen", ClassesCB, "Lotta om hela klassen");
else else
gdi.addButton("DoDraw", "Tilldela", ClassesCB, "Tilldela starttider"); gdi.addButton("DoDraw", "Tilldela", ClassesCB, "Tilldela starttider");
if (method == DMRandom || method == DMSOFT) { if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::MeOS) {
gdi.addButton("DoDrawBefore", "Ej lottade, före", ClassesCB, "Lotta löpare som saknar starttid"); gdi.addButton("DoDrawBefore", "Ej lottade, före", ClassesCB, "Lotta löpare som saknar starttid");
gdi.addButton("DoDrawAfter", "Ej lottade, efter", ClassesCB, "Lotta löpare som saknar starttid"); gdi.addButton("DoDrawAfter", "Ej lottade, efter", ClassesCB, "Lotta löpare som saknar starttid");
} }
@ -3393,39 +3552,41 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
setMultiDayClass(gdi, multiDay, method); setMultiDayClass(gdi, multiDay, method);
EditChanged=false; EditChanged = false;
gdi.refresh(); gdi.refresh();
lastDrawMethod = method; lastDrawMethod = method;
} }
set<DrawMethod> TabClass::getSupportedDrawMethods(bool hasMulti) const { set<oEvent::DrawMethod> TabClass::getSupportedDrawMethods(bool hasMulti) const {
set<DrawMethod> base = { DMRandom, DMSOFT, DMClumped, DMSimultaneous, DMSeeded }; set<oEvent::DrawMethod> base = { oEvent::DrawMethod::Random, oEvent::DrawMethod::SOFT, oEvent::DrawMethod::Clumped,
oEvent::DrawMethod::MeOS, oEvent::DrawMethod::Simultaneous, oEvent::DrawMethod::Seeded };
if (hasMulti) { if (hasMulti) {
base.insert(DMPursuit); base.insert(oEvent::DrawMethod::Pursuit);
base.insert(DMReversePursuit); base.insert(oEvent::DrawMethod::ReversePursuit);
} }
return base; return base;
} }
void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaultMethod) { void TabClass::setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMethod defaultMethod) {
gdi.clearList("Method"); gdi.clearList("Method");
gdi.addItem("Method", lang.tl("Lottning"), DMRandom); gdi.addItem("Method", lang.tl("Lottning") + L" (MeOS)" , int(oEvent::DrawMethod::MeOS));
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT); gdi.addItem("Method", lang.tl("Lottning"), int(oEvent::DrawMethod::Random));
gdi.addItem("Method", lang.tl("Klungstart"), DMClumped); gdi.addItem("Method", lang.tl("SOFT-lottning"), int(oEvent::DrawMethod::SOFT));
gdi.addItem("Method", lang.tl("Gemensam start"), DMSimultaneous); gdi.addItem("Method", lang.tl("Klungstart"), int(oEvent::DrawMethod::Clumped));
gdi.addItem("Method", lang.tl("Seedad lottning"), DMSeeded); gdi.addItem("Method", lang.tl("Gemensam start"), int(oEvent::DrawMethod::Simultaneous));
gdi.addItem("Method", lang.tl("Seedad lottning"), int(oEvent::DrawMethod::Seeded));
if (hasMulti) { if (hasMulti) {
gdi.addItem("Method", lang.tl("Jaktstart"), DMPursuit); gdi.addItem("Method", lang.tl("Jaktstart"), int(oEvent::DrawMethod::Pursuit));
gdi.addItem("Method", lang.tl("Omvänd jaktstart"), DMReversePursuit); gdi.addItem("Method", lang.tl("Omvänd jaktstart"), int(oEvent::DrawMethod::ReversePursuit));
} }
else if (defaultMethod > 10) else if (int(defaultMethod) > 10)
defaultMethod = DMSOFT; defaultMethod = oEvent::DrawMethod::MeOS;
gdi.selectItemByData("Method", defaultMethod); gdi.selectItemByData("Method", int(defaultMethod));
if (gdi.hasField("Vacanses")) { if (gdi.hasField("Vacanses")) {
gdi.setInputStatus("Vacanses", !hasMulti); gdi.setInputStatus("Vacanses", !hasMulti);
@ -3706,6 +3867,8 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
} }
void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const { void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const {
if (!gdi.hasField("FairForking"))
return;
vector< vector<int> > forks; vector< vector<int> > forks;
vector< vector<int> > forksC; vector< vector<int> > forksC;
set< pair<int, int> > unfairLegs; set< pair<int, int> > unfairLegs;
@ -3762,9 +3925,15 @@ void TabClass::defineForking(gdioutput &gdi, bool clearSettings) {
gdi.dropLine(0.5); gdi.dropLine(0.5);
for (int k = 0; k < ns; k++) { for (int k = 0; k < ns; k++) {
LegTypes lt = pc->getLegType(k); LegTypes lt = pc->getLegType(k);
if (lt != LTIgnore) { if (lt != LTIgnore && lt != LTExtra) {
gdi.addString("leg"+ itos(k), 0, "Leg X: Do not modify.#" + itos(k+1)); wstring lnum = pc->getLegNumber(k);
gdi.addItem("AllStages", lang.tl("Leg X#" + itos(k+1)), k); int k2 = k + 1;
while (k2 < ns && (pc->getLegType(k2) == LTExtra || pc->getLegType(k2) == LTIgnore)) {
lnum += L"/" + pc->getLegNumber(k2);
k2++;
}
gdi.addString("leg"+ itos(k), 0, L"Leg X: Do not modify.#" + lnum);
gdi.addItem("AllStages", lang.tl(L"Leg X#" + lnum), k);
} }
} }
@ -4099,13 +4268,7 @@ void TabClass::updateSplitDistribution(gdioutput &gdi, int num, int tot) const {
gdi.refresh(); gdi.refresh();
} }
DrawMethod TabClass::getDefaultMethod(const set<DrawMethod> &allowedValues) const {
DrawMethod dm = (DrawMethod)oe->getPropertyInt("DefaultDrawMethod", DMSOFT);
if (allowedValues.count(dm))
return dm;
else
return DMSOFT;
}
vector< pair<wstring, size_t> > TabClass::getPairOptions() { vector< pair<wstring, size_t> > TabClass::getPairOptions() {
vector< pair<wstring, size_t> > res; vector< pair<wstring, size_t> > res;
@ -4179,6 +4342,12 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
while (gdi.hasField("@Course" + itos(legno))) { while (gdi.hasField("@Course" + itos(legno))) {
gdi.setInputStatus("@Course" + itos(legno++), !lockState || poolState); gdi.setInputStatus("@Course" + itos(legno++), !lockState || poolState);
} }
for (string s : {"MCourses", "StageCourses", "MAdd", "MRemove"}) {
if (gdi.hasField(s)) {
gdi.setInputStatus(s, !lockState || poolState);
}
}
} }
bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) { bool TabClass::warnDrawStartTime(gdioutput &gdi, const wstring &firstStart) {
@ -4275,6 +4444,7 @@ vector<DrawSettingsCSV> DrawSettingsCSV::read(gdioutput &gdi, const oEvent &oe,
set<int> usedId; set<int> usedId;
// Save settings with class // Save settings with class
int lineNo = 0; int lineNo = 0;
bool anyError = false;
for (auto &row : data) { for (auto &row : data) {
lineNo++; lineNo++;
if (row.empty()) if (row.empty())
@ -4285,8 +4455,8 @@ vector<DrawSettingsCSV> DrawSettingsCSV::read(gdioutput &gdi, const oEvent &oe,
continue; continue;
DrawSettingsCSV dl; DrawSettingsCSV dl;
try {
try {
if (row.size() <= 7) if (row.size() <= 7)
throw wstring(L"Rad X är ogiltig#" + itow(lineNo) + L": " + row[0] + L"..."); throw wstring(L"Rad X är ogiltig#" + itow(lineNo) + L": " + row[0] + L"...");
@ -4319,9 +4489,16 @@ vector<DrawSettingsCSV> DrawSettingsCSV::read(gdioutput &gdi, const oEvent &oe,
} }
catch (const wstring &exmsg) { catch (const wstring &exmsg) {
gdi.addString("", 0, exmsg).setColor(colorRed); gdi.addString("", 0, exmsg).setColor(colorRed);
anyError = true;
} }
} }
if (anyError && !output.empty()) {
gdi.dropLine();
gdi.refresh();
Sleep(3000);
}
return output; return output;
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -75,10 +75,10 @@ class TabClass :
map<int, ClassInfo> cInfoCache; map<int, ClassInfo> cInfoCache;
DrawInfo drawInfo; DrawInfo drawInfo;
void setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaultMethod); void setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMethod defaultMethod);
set<DrawMethod> getSupportedDrawMethods(bool multiDay) const; set<oEvent::DrawMethod> getSupportedDrawMethods(bool multiDay) const;
void drawDialog(gdioutput &gdi, DrawMethod method, const oClass &cls); void drawDialog(gdioutput &gdi, oEvent::DrawMethod method, const oClass &cls);
void pursuitDialog(gdioutput &gdi); void pursuitDialog(gdioutput &gdi);
@ -90,7 +90,7 @@ class TabClass :
bool hasWarnedStartTime; bool hasWarnedStartTime;
bool hasWarnedDirect; bool hasWarnedDirect;
bool tableMode; bool tableMode;
DrawMethod lastDrawMethod; oEvent::DrawMethod lastDrawMethod;
int lastSeedMethod; int lastSeedMethod;
bool lastSeedPreventClubNb; bool lastSeedPreventClubNb;
bool lastSeedReverse; bool lastSeedReverse;
@ -138,7 +138,9 @@ class TabClass :
void updateSplitDistribution(gdioutput &gdi, int numInClass, int tot) const; void updateSplitDistribution(gdioutput &gdi, int numInClass, int tot) const;
DrawMethod getDefaultMethod(const set<DrawMethod> &allowedValues) const; oEvent::DrawMethod getDefaultMethod(const set<oEvent::DrawMethod> &allowedValues) const;
void createDrawMethod(gdioutput& gdi);
void enableLoadSettings(gdioutput &gdi); void enableLoadSettings(gdioutput &gdi);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -134,7 +134,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
gdi.clearPage(true); gdi.clearPage(true);
oe->calculateTeamResults(false); oe->calculateTeamResults(false);
oe->sortTeams(ClassStartTime, 0, true); oe->sortTeams(ClassStartTime, 0, true);
oe->calculateResults(oEvent::RTClassResult); oe->calculateResults({}, oEvent::ResultType::ClassResult);
oe->sortRunners(ClassStartTime); oe->sortRunners(ClassStartTime);
int pay, paid; int pay, paid;
{ {
@ -561,7 +561,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
if (!file.empty()) { if (!file.empty()) {
pdfwriter pdf; pdfwriter pdf;
pdf.generatePDF(gdi, file, lang.tl("Faktura"), oe->getDCI().getString("Organizer"), gdi.getTL()); pdf.generatePDF(gdi, file, lang.tl("Faktura"), oe->getDCI().getString("Organizer"), gdi.getTL(), true);
gdi.openDoc(file.c_str()); gdi.openDoc(file.c_str());
} }
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -52,6 +52,8 @@
#include "recorder.h" #include "recorder.h"
#include "testmeos.h" #include "testmeos.h"
#include "importformats.h" #include "importformats.h"
#include "HTMLWriter.h"
#include "metalist.h"
#include <Shellapi.h> #include <Shellapi.h>
#include <algorithm> #include <algorithm>
@ -99,6 +101,9 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
bool longTimes = gdi.isChecked("LongTimes"); bool longTimes = gdi.isChecked("LongTimes");
wstring date = gdi.getText("Date"); wstring date = gdi.getText("Date");
if (!checkValidDate(date))
throw meosException(L"Felaktigt datum 'X' (Använd YYYY-MM-DD)#" + date);
if (longTimes) if (longTimes)
zt = L"00:00:00"; zt = L"00:00:00";
@ -674,9 +679,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
if (club == cmp) if (club == cmp)
club = L""; club = L"";
csvparser csv; bool clubCsv = !club.empty() && csvparser::iscsv(club) != csvparser::CSV::NoCSV;
bool clubCsv = !club.empty() && csv.iscsv(club.c_str()) != 0; bool cmpCsv = !cmp.empty() && csvparser::iscsv(cmp) != csvparser::CSV::NoCSV;
bool cmpCsv = !cmp.empty() && csv.iscsv(cmp.c_str()) != 0;
if (cmpCsv) { if (cmpCsv) {
if (!club.empty()) if (!club.empty())
@ -964,8 +968,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
vector<pTeam> newEntriesT, notTransferedT, failedTargetT; vector<pTeam> newEntriesT, notTransferedT, failedTargetT;
oe->transferResult(nextStage, method, newEntriesT, notTransferedT, failedTargetT); oe->transferResult(nextStage, method, newEntriesT, notTransferedT, failedTargetT);
nextStage.transferListsAndSave(*oe);
nextStage.save();
oe->updateTabs(true); oe->updateTabs(true);
gdi.dropLine(); gdi.dropLine();
@ -1549,7 +1552,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
switch (startType) { switch (startType) {
case SMCommon: case SMCommon:
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0", L"0", false, false, 1); oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0", L"0", false, oEvent::DrawMethod::Random, 1);
drawn = true; drawn = true;
break; break;
@ -1569,12 +1572,12 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
cls += cnf.classWithoutCourse[k]; cls += cnf.classWithoutCourse[k];
} }
if (!gdi.ask(L"ask:missingcourse#" + cls)) { if (!gdi.ask(L"ask:missingcourse#" + cls)) {
gdi.addString("", 0, "Skipper lottning"); gdi.addString("", 0, "Skippar lottning");
skip = true; skip = true;
} }
} }
if (!skip) if (!skip)
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00", L"2", true, true, 1); oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00", L"2", true, oEvent::DrawMethod::MeOS, 1);
drawn = true; drawn = true;
break; break;
} }
@ -1773,7 +1776,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->generateListInfo(par, gdi.getLineHeight(), li); oe->generateListInfo(par, gdi.getLineHeight(), li);
gdioutput tGdi("temp", gdi.getScale()); gdioutput tGdi("temp", gdi.getScale());
oe->generateList(tGdi, true, li, false); oe->generateList(tGdi, true, li, false);
tGdi.writeTableHTML(save, oe->getName(), 0); HTMLWriter::writeTableHTML(tGdi, save, oe->getName(), 0, 1.0);
tGdi.openDoc(save.c_str()); tGdi.openDoc(save.c_str());
} }
loadPage(gdi); loadPage(gdi);
@ -1858,7 +1861,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
oe->generateListInfo(par, gdi.getLineHeight(), li); oe->generateListInfo(par, gdi.getLineHeight(), li);
gdioutput tGdi("temp", gdi.getScale()); gdioutput tGdi("temp", gdi.getScale());
oe->generateList(tGdi, true, li, false); oe->generateList(tGdi, true, li, false);
tGdi.writeTableHTML(save, oe->getName(), 0); HTMLWriter::writeTableHTML(tGdi, save, oe->getName(), 0, 1.0);
tGdi.openDoc(save.c_str()); tGdi.openDoc(save.c_str());
} }
@ -2337,7 +2340,7 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
void TabCompetition::listBackups(gdioutput &gdi) { void TabCompetition::listBackups(gdioutput &gdi) {
wchar_t bf[260]; wchar_t bf[260];
getUserFile(bf, L""); getUserFile(bf, L"");
int yo = gdi.GetOffsetY(); int yo = gdi.getOffsetY();
gdi.clearPage(false); gdi.clearPage(false);
oe->enumerateBackups(bf); oe->enumerateBackups(bf);
@ -2393,10 +2396,17 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
gdi.addString("", 0, "se license.txt som levereras med programmet."); gdi.addString("", 0, "se license.txt som levereras med programmet.");
gdi.dropLine(); gdi.dropLine();
gdi.addString("", 1, "Vi stöder MeOS");
vector<wstring> supp; vector<wstring> supp;
vector<wstring> developSupp; vector<wstring> developSupp;
getSupporters(supp, developSupp); getSupporters(supp, developSupp);
gdi.addString("", fontMediumPlus, "MeOS utvecklinsstöd");
for (size_t k = 0; k<developSupp.size(); k++)
gdi.addStringUT(fontMedium, developSupp[k]).setColor(colorDarkGreen);
gdi.dropLine();
gdi.addString("", fontMediumPlus, "Vi stöder MeOS");
for (size_t k = 0; k<supp.size(); k++) for (size_t k = 0; k<supp.size(); k++)
gdi.addStringUT(0, supp[k]); gdi.addStringUT(0, supp[k]);
@ -2492,7 +2502,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
copyrightLine(gdi); copyrightLine(gdi);
gdi.addButton(gdi.GetPageX()-gdi.scaleLength(180), gdi.addButton(gdi.getPageX()-gdi.scaleLength(180),
gdi.getCY()-gdi.getButtonHeight(), gdi.getCY()-gdi.getButtonHeight(),
"Exit", "Avsluta", CompetitionCB); "Exit", "Avsluta", CompetitionCB);
gdi.setInputFocus("CmpSel", true); gdi.setInputFocus("CmpSel", true);
@ -3252,6 +3262,7 @@ void TabCompetition::selectTransferClasses(gdioutput &gdi, bool expand) {
gdi.addItem("ChangeClassType", lang.tl("Tillåt ny klass, inget totalresultat"), oEvent::TransferNoResult); gdi.addItem("ChangeClassType", lang.tl("Tillåt ny klass, inget totalresultat"), oEvent::TransferNoResult);
gdi.addItem("ChangeClassType", lang.tl("Tillåt ny klass, behåll resultat från annan klass"), oEvent::TransferAnyway); gdi.addItem("ChangeClassType", lang.tl("Tillåt ny klass, behåll resultat från annan klass"), oEvent::TransferAnyway);
gdi.selectItemByData("ChangeClassType", lastChangeClassType); gdi.selectItemByData("ChangeClassType", lastChangeClassType);
gdi.autoGrow("ChangeClassType");
if (expand) { if (expand) {
gdi.fillDown(); gdi.fillDown();
@ -3429,7 +3440,7 @@ void TabCompetition::entryForm(gdioutput &gdi, bool isGuide) {
gdi.popX(); gdi.popX();
gdi.dropLine(2.5); gdi.dropLine(2.5);
gdi.addInput("FileNameRank", L"", 48, 0, L"Ranking (IOF, xml)"); gdi.addInput("FileNameRank", L"", 48, 0, L"Ranking (IOF, xml, csv)");
gdi.dropLine(); gdi.dropLine();
gdi.addButton("BrowseEntries", "Bläddra...", CompetitionCB).setExtra(L"FileNameRank"); gdi.addButton("BrowseEntries", "Bläddra...", CompetitionCB).setExtra(L"FileNameRank");
gdi.popX(); gdi.popX();
@ -3445,7 +3456,7 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
filename[3] = gdi.getText("FileName"); filename[3] = gdi.getText("FileName");
filename[4] = gdi.getText("FileNameRank"); filename[4] = gdi.getText("FileNameRank");
csvparser csv; //csvparser csv;
for (int i = 0; i<5; i++) { for (int i = 0; i<5; i++) {
if (filename[i].empty()) if (filename[i].empty())
@ -3453,12 +3464,32 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
gdi.addString("", 0, L"Behandlar: X#" + filename[i]); gdi.addString("", 0, L"Behandlar: X#" + filename[i]);
int type=csv.iscsv(filename[i]); csvparser::CSV type = csvparser::iscsv(filename[i]);
if (i == 4 && (type == csvparser::CSV::OE || type == csvparser::CSV::Unknown)) {
if (type) { // Ranking
const wchar_t *File = filename[i].c_str(); const wchar_t *File = filename[i].c_str();
if (type==1) { gdi.addString("", 0, "Importerar ranking...");
gdi.refresh();
gdi.setWaitCursor(true);
vector<wstring> problems;
csvparser csv;
int count = csv.importRanking(*oe, File, problems);
if (count > 0) {
gdi.addString("", 0, "Klart. X värden tilldelade.#" + itos(count));
if (!problems.empty()) {
gdi.dropLine();
gdi.addString("", 0, "Varning: Följande deltagare har ett osäkert resultat:");
for (auto &p : problems)
gdi.addStringUT(0, p).setColor(colorDarkRed);
}
}
else gdi.addString("", 0, "Försöket misslyckades.");
}
else if (type != csvparser::CSV::NoCSV) {
const wchar_t *File = filename[i].c_str();
csvparser csv;
if (type == csvparser::CSV::OE) {
gdi.addString("", 0, "Importerar OE2003 csv-fil..."); gdi.addString("", 0, "Importerar OE2003 csv-fil...");
gdi.refresh(); gdi.refresh();
gdi.setWaitCursor(true); gdi.setWaitCursor(true);
@ -3467,7 +3498,7 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
} }
else gdi.addString("", 0, "Försöket misslyckades."); else gdi.addString("", 0, "Försöket misslyckades.");
} }
else if (type==2) { else if (type == csvparser::CSV::OS) {
gdi.addString("", 0, "Importerar OS2003 csv-fil..."); gdi.addString("", 0, "Importerar OS2003 csv-fil...");
gdi.refresh(); gdi.refresh();
gdi.setWaitCursor(true); gdi.setWaitCursor(true);
@ -3476,14 +3507,16 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
} }
else gdi.addString("", 0, "Försöket misslyckades."); else gdi.addString("", 0, "Försöket misslyckades.");
} }
else if (type==3) { else if (type == csvparser::CSV::RAID) {
gdi.addString("", 0, "Importerar RAID patrull csv-fil..."); gdi.addString("", 0, "Importerar RAID patrull csv-fil...");
gdi.setWaitCursor(true); gdi.setWaitCursor(true);
if (csv.importRAID(*oe, File)) { if (csv.importRAID(*oe, File)) {
gdi.addString("", 0, "Klart. X patruller importerade.#" + itos(csv.nimport)); gdi.addString("", 0, "Klart. X patruller importerade.#" + itos(csv.nimport));
} }
else gdi.addString("", 0, "Försöket misslyckades."); else gdi.addString("", 0, "Försöket misslyckades.");
}
else {
gdi.addString("", 0, "Försöket misslyckades.");
} }
} }
else { else {

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -179,13 +179,11 @@ void TabCourse::selectCourse(gdioutput &gdi, pCourse pc)
gdi.selectItemByData("CommonControl", cc); gdi.selectItemByData("CommonControl", cc);
} }
fillOtherCourses(gdi, *pc); fillOtherCourses(gdi, *pc, cc != 0);
pCourse sh = pc->getShorterVersion(); auto sh = pc->getShorterVersion();
gdi.check("Shorten", sh != 0); gdi.check("Shorten", sh.first);
gdi.setInputStatus("ShortCourse", sh != 0); gdi.setInputStatus("ShortCourse", sh.first);
if (sh) { gdi.selectItemByData("ShortCourse", sh.second ? sh.second->getId() : 0);
gdi.selectItemByData("ShortCourse", sh->getId());
}
} }
else { else {
gdi.setText("Name", L""); gdi.setText("Name", L"");
@ -283,13 +281,16 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
if (gdi.isChecked("Shorten")) { if (gdi.isChecked("Shorten")) {
ListBoxInfo ci; ListBoxInfo ci;
if (gdi.getSelectedItem("ShortCourse", ci) && oe->getCourse(ci.data)) { if (gdi.getSelectedItem("ShortCourse", ci) && oe->getCourse(ci.data)) {
pc->setShorterVersion(oe->getCourse(ci.data)); pc->setShorterVersion(true, oe->getCourse(ci.data));
}
else if (gdi.isChecked("WithLoops")) {
pc->setShorterVersion(true, nullptr);
} }
else else
throw meosException("Ange en avkortad banvariant"); throw meosException("Ange en avkortad banvariant");
} }
else else
pc->setShorterVersion(0); pc->setShorterVersion(false, 0);
if (gdi.hasField("Rogaining")) { if (gdi.hasField("Rogaining")) {
string t; string t;
@ -411,7 +412,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
if (!file.empty()) { if (!file.empty()) {
pdfwriter pdf; pdfwriter pdf;
pdf.generatePDF(gdi, file, L"Report", L"MeOS", gdi.getTL()); pdf.generatePDF(gdi, file, L"Report", L"MeOS", gdi.getTL(), true);
gdi.openDoc(file.c_str()); gdi.openDoc(file.c_str());
} }
} }
@ -420,6 +421,21 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
gdi.setInputStatus("CommonControl", w); gdi.setInputStatus("CommonControl", w);
if (w && gdi.getTextNo("CommonControl") == 0) if (w && gdi.getTextNo("CommonControl") == 0)
gdi.selectFirstItem("CommonControl"); gdi.selectFirstItem("CommonControl");
pCourse pc = oe->getCourse(courseId);
if (pc) {
pair<int, bool> sel = gdi.getSelectedItem("ShortCourse");
fillOtherCourses(gdi, *pc, w);
if (!w && sel.first == 0)
sel.second = false;
if (sel.second) {
gdi.selectItemByData("ShortCourse", sel.first);
}
else if (w) {
gdi.selectItemByData("ShortCourse", 0);
}
}
} }
else if (bi.id == "Shorten") { else if (bi.id == "Shorten") {
bool w = gdi.isChecked(bi.id); bool w = gdi.isChecked(bi.id);
@ -512,10 +528,11 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
gdi.popX(); gdi.popX();
gdi.dropLine(3); gdi.dropLine(3);
gdi.addSelection("Method", 200, 200, 0, L"Metod:"); gdi.addSelection("Method", 200, 200, 0, L"Metod:");
gdi.addItem("Method", lang.tl("Lottning"), DMRandom); gdi.addItem("Method", lang.tl("Lottning") + L" (MeOS)", int(oEvent::DrawMethod::MeOS));
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT); gdi.addItem("Method", lang.tl("Lottning"), int(oEvent::DrawMethod::Random));
gdi.addItem("Method", lang.tl("SOFT-lottning"), int(oEvent::DrawMethod::SOFT));
gdi.selectItemByData("Method", getDefaultMethod()); gdi.selectItemByData("Method", (int)getDefaultMethod());
gdi.dropLine(0.9); gdi.dropLine(0.9);
gdi.fillRight(); gdi.fillRight();
gdi.addButton("DoDrawCourse", "Lotta", CourseCB).setDefault(); gdi.addButton("DoDrawCourse", "Lotta", CourseCB).setDefault();
@ -530,7 +547,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
int vacances = gdi.getTextNo("Vacances"); int vacances = gdi.getTextNo("Vacances");
int fs = oe->getRelativeTime(firstStart); int fs = oe->getRelativeTime(firstStart);
int iv = convertAbsoluteTimeMS(minInterval); int iv = convertAbsoluteTimeMS(minInterval);
DrawMethod method = DrawMethod(gdi.getSelectedItem("Method").first); oEvent::DrawMethod method = oEvent::DrawMethod(gdi.getSelectedItem("Method").first);
courseDrawClasses[0].firstStart = fs; courseDrawClasses[0].firstStart = fs;
courseDrawClasses[0].vacances = vacances; courseDrawClasses[0].vacances = vacances;
courseDrawClasses[0].interval = iv; courseDrawClasses[0].interval = iv;
@ -549,7 +566,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
courseDrawClasses[k].interval = iv; courseDrawClasses[k].interval = iv;
} }
oe->drawList(courseDrawClasses, method == DMSOFT, 1, oEvent::drawAll); oe->drawList(courseDrawClasses, method, 1, oEvent::DrawType::DrawAll);
oe->addAutoBib(); oe->addAutoBib();
@ -852,13 +869,12 @@ bool TabCourse::loadPage(gdioutput &gdi) {
void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename, void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
oEvent *oe, bool addClasses) { oEvent *oe, bool addClasses) {
csvparser csv; if (csvparser::iscsv(filename) != csvparser::CSV::NoCSV) {
if (csv.iscsv(filename)) {
gdi.fillRight(); gdi.fillRight();
gdi.pushX(); gdi.pushX();
gdi.addString("", 0, "Importerar OCAD csv-fil..."); gdi.addString("", 0, "Importerar OCAD csv-fil...");
gdi.refreshFast(); gdi.refreshFast();
csvparser csv;
if (csv.importOCAD_CSV(*oe, filename, addClasses)) { if (csv.importOCAD_CSV(*oe, filename, addClasses)) {
gdi.addString("", 1, "Klart.").setColor(colorGreen); gdi.addString("", 1, "Klart.").setColor(colorGreen);
} }
@ -1044,7 +1060,7 @@ void TabCourse::fillCourseControls(gdioutput &gdi, const wstring &ctrl) {
gdi.addItem("CommonControl", item); gdi.addItem("CommonControl", item);
} }
void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs) { void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops) {
vector< pair<wstring, size_t> > ac; vector< pair<wstring, size_t> > ac;
oe->fillCourses(ac, true); oe->fillCourses(ac, true);
set<int> skipped; set<int> skipped;
@ -1057,6 +1073,9 @@ void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs) {
} }
vector< pair<wstring, size_t> > out; vector< pair<wstring, size_t> > out;
if (withLoops)
out.emplace_back(lang.tl("Färre slingor"), 0);
for (size_t k = 0; k < ac.size(); k++) { for (size_t k = 0; k < ac.size(); k++) {
if (!skipped.count(ac[k].second)) if (!skipped.count(ac[k].second))
out.push_back(ac[k]); out.push_back(ac[k]);
@ -1093,12 +1112,14 @@ void TabCourse::saveLegLengths(gdioutput &gdi) {
pc->synchronize(true); pc->synchronize(true);
} }
DrawMethod TabCourse::getDefaultMethod() const { oEvent::DrawMethod TabCourse::getDefaultMethod() const {
int dm = oe->getPropertyInt("DefaultDrawMethod", DMSOFT); int dm = oe->getPropertyInt("DefaultDrawMethod", int(oEvent::DrawMethod::MeOS));
if (dm == DMRandom) if (dm == (int)oEvent::DrawMethod::Random)
return DMRandom; return oEvent::DrawMethod::Random;
if (dm == (int)oEvent::DrawMethod::MeOS)
return oEvent::DrawMethod::MeOS;
else else
return DMSOFT; return oEvent::DrawMethod::SOFT;
} }
void TabCourse::clearCompetitionData() { void TabCourse::clearCompetitionData() {

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -24,7 +24,6 @@
#include "tabbase.h" #include "tabbase.h"
struct ClassDrawSpecification; struct ClassDrawSpecification;
enum DrawMethod;
class TabCourse : class TabCourse :
public TabBase public TabBase
@ -40,13 +39,13 @@ class TabCourse :
wstring point_reduction; wstring point_reduction;
void fillCourseControls(gdioutput &gdi, const wstring &ctrl); void fillCourseControls(gdioutput &gdi, const wstring &ctrl);
void fillOtherCourses(gdioutput &gdi, oCourse &crs); void fillOtherCourses(gdioutput &gdi, oCourse &crs, bool withLoops);
void saveLegLengths(gdioutput &gdi); void saveLegLengths(gdioutput &gdi);
vector<ClassDrawSpecification> courseDrawClasses; vector<ClassDrawSpecification> courseDrawClasses;
DrawMethod getDefaultMethod() const; oEvent::DrawMethod getDefaultMethod() const;
wstring encodeCourse(const wstring &in, bool firstStart, bool lastFinish); wstring encodeCourse(const wstring &in, bool firstStart, bool lastFinish);
void refreshCourse(const wstring &text, gdioutput &gdi); void refreshCourse(const wstring &text, gdioutput &gdi);

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -40,6 +40,7 @@ protected:
bool lastSplitState; bool lastSplitState;
bool lastLargeSize; bool lastLargeSize;
wstring lastHtmlTarget;
EStdListType getTypeFromResultIndex(int ix) const; EStdListType getTypeFromResultIndex(int ix) const;
@ -78,6 +79,9 @@ private:
TabList(const TabList &); TabList(const TabList &);
const TabList &operator = (const TabList &); const TabList &operator = (const TabList &);
map<string, int> htmlTemplateTag2Id;
map<int, wstring> html2IdToInfo;
string settingsTarget; string settingsTarget;
oListParam tmpSettingsParam; oListParam tmpSettingsParam;
void changeListSettingsTarget(gdioutput &oldWindow, gdioutput &newWindow); void changeListSettingsTarget(gdioutput &oldWindow, gdioutput &newWindow);
@ -93,8 +97,8 @@ private:
static void getResultIndividual(oListParam &par, ClassConfigInfo &cnf); static void getResultIndividual(oListParam &par, ClassConfigInfo &cnf);
static void getResultClub(oListParam &par, ClassConfigInfo &cnf); static void getResultClub(oListParam &par, ClassConfigInfo &cnf);
static void getStartPatrol(oListParam &par, ClassConfigInfo &cnf); static void getStartPatrol(oEvent &oe, oListParam &par, ClassConfigInfo &cnf);
static void getResultPatrol(oListParam &par, ClassConfigInfo &cnf); static void getResultPatrol(oEvent &oe, oListParam &par, ClassConfigInfo &cnf);
static void getStartTeam(oListParam &par, ClassConfigInfo &cnf); static void getStartTeam(oListParam &par, ClassConfigInfo &cnf);
static void getResultTeam(oListParam &par, ClassConfigInfo &cnf); static void getResultTeam(oListParam &par, ClassConfigInfo &cnf);
@ -102,6 +106,8 @@ private:
static void getResultRogaining(oListParam &par, ClassConfigInfo &cnf); static void getResultRogaining(oListParam &par, ClassConfigInfo &cnf);
static void readSettings(gdioutput &gdi, oListParam &par, bool forResult);
public: public:
/** Returns a collection of public lists. */ /** Returns a collection of public lists. */
void static getPublicLists(oEvent &oe, vector<oListParam> &lists); void static getPublicLists(oEvent &oe, vector<oListParam> &lists);
@ -121,8 +127,18 @@ public:
void rebuildList(gdioutput &gdi); void rebuildList(gdioutput &gdi);
void settingsResultList(gdioutput &gdi); void settingsResultList(gdioutput &gdi);
void loadClassSettings(gdioutput &gdi, string targetTag);
void handleClassSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi);
void loadSettings(gdioutput &gdi, string targetTag); void loadSettings(gdioutput &gdi, string targetTag);
void handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi); void handleListSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi);
void htmlSettings(gdioutput &gdi, string targetTag);
void handleHTMLSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi);
void loadRememberList(gdioutput &gdi, string targetTag);
void handleRememberSettings(gdioutput &gdi, BaseInfo &info, GuiEventType type, gdioutput &dest_gdi);
enum PrintSettingsSelection { enum PrintSettingsSelection {
Splits = 0, Splits = 0,
StartInfo = 1, StartInfo = 1,

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -473,7 +473,7 @@ int TabRunner::searchCB(gdioutput &gdi, int type, void *data) {
} }
pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) { pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
oe->synchronizeList(oLCardId, true, true); oe->synchronizeList(oListId::oLCardId);
TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab)); TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab));
tsi.storedInfo.clear(); tsi.storedInfo.clear();
@ -545,11 +545,8 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
RunnerStatus originalStatus = r->getStatus(); RunnerStatus originalStatus = r->getStatus();
r->setName(name, true); r->setName(name, true);
if (gdi.hasField("Bib")) { if (dynamic_cast<InputInfo &>(gdi.getBaseInfo("PTime")).changed()) {
const wstring &bib = gdi.getText("Bib"); savePunchTime(r, gdi);
wchar_t pat[32];
int num = oClass::extractBibPattern(bib, pat);
r->setBib(bib, num, num>0, false);
} }
bool noSetStatus = false; bool noSetStatus = false;
@ -578,7 +575,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
const bool hireChecked = gdi.isChecked("RentCard"); const bool hireChecked = gdi.isChecked("RentCard");
const bool hireState = r->isHiredCard(); const bool hireState = r->isHiredCard();
if (hireChecked && !hireState) { if (hireChecked && !hireState) {
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee")); r->getDI().setInt("CardFee", oe->getBaseCardFee());
} }
else if (!hireChecked && hireState) { else if (!hireChecked && hireState) {
r->getDI().setInt("CardFee", 0); r->getDI().setInt("CardFee", 0);
@ -638,6 +635,15 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
r->setClassId(classId, true); r->setClassId(classId, true);
if (gdi.hasField("Bib")) {
const wstring &bib = gdi.getText("Bib");
wchar_t pat[32];
int num = oClass::extractBibPattern(bib, pat);
bool lockedForking = r->getClassRef(true) && r->getClassRef(true)->lockedForking();
r->setBib(bib, num, num>0 && !lockedForking, false);
}
r->setCourseId(gdi.getSelectedItem("RCourse").first); r->setCourseId(gdi.getSelectedItem("RCourse").first);
RunnerStatus sIn = (RunnerStatus)gdi.getSelectedItem("Status").first; RunnerStatus sIn = (RunnerStatus)gdi.getSelectedItem("Status").first;
@ -649,7 +655,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
vector<int> mp; vector<int> mp;
r->evaluateCard(true, mp, 0, true); r->evaluateCard(true, mp, 0, true);
if (r->getClassId(true) != classId) { if (r->getClassId(true) != classId && r->getClassId(false) != classId) {
gdi.alert("Deltagarens klass styrs av laget."); gdi.alert("Deltagarens klass styrs av laget.");
} }
@ -963,7 +969,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
pRunner r = oe->getRunner(runnerId, 0); pRunner r = oe->getRunner(runnerId, 0);
if (getExtraWindow("ecosettings", true) == 0) { if (getExtraWindow("ecosettings", true) == 0) {
gdioutput *settings = createExtraWindow("ecosettings", L"Economy", 550, 350); gdioutput *settings = createExtraWindow("ecosettings", L"Economy", gdi.scaleLength(550), gdi.scaleLength(350), true);
TabRunner &dst = dynamic_cast<TabRunner&>(*settings->getTabs().get(TabType::TRunnerTab)); TabRunner &dst = dynamic_cast<TabRunner&>(*settings->getTabs().get(TabType::TRunnerTab));
dst.loadEconomy(*settings, *r); dst.loadEconomy(*settings, *r);
} }
@ -1236,7 +1242,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
(listenToPunches || oe->isReadOnly()) && currentMode == 5) { (listenToPunches || oe->isReadOnly()) && currentMode == 5) {
if (ei.getData() > 0) { if (ei.getData() > 0) {
vector<pRunner> rs; vector<pRunner> rs;
oe->getRunnersByCard(ei.getData(), rs); oe->getRunnersByCardNo(ei.getData(), true, oEvent::CardLookupProperty::Any, rs);
if (!rs.empty()) { if (!rs.empty()) {
runnersToReport.resize(rs.size()); runnersToReport.resize(rs.size());
for (size_t k = 0; k<rs.size(); k++) for (size_t k = 0; k<rs.size(); k++)
@ -1433,7 +1439,7 @@ int TabRunner::vacancyCB(gdioutput &gdi, int type, void *data)
int cardFee = 0; int cardFee = 0;
if (gdi.isChecked("RentCard")) { if (gdi.isChecked("RentCard")) {
cardFee = oe->getDI().getInt("CardFee"); cardFee = oe->getBaseCardFee();
r->getDI().setInt("CardFee", cardFee); r->getDI().setInt("CardFee", cardFee);
} }
else else
@ -1513,8 +1519,7 @@ void TabRunner::setCardNo(gdioutput &gdi, int cardNo)
} }
} }
void TabRunner::showRunnerReport(gdioutput &gdi) void TabRunner::showRunnerReport(gdioutput &gdi) {
{
gdi.clearPage(true); gdi.clearPage(true);
currentMode = 5; currentMode = 5;
@ -1529,7 +1534,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
gdi.fillRight(); gdi.fillRight();
gdi.addSelection("ReportRunner", 300, 300, RunnerCB); gdi.addSelection("ReportRunner", 300, 300, RunnerCB);
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll|oEvent::RunnerCompactMode); oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll | oEvent::RunnerCompactMode);
gdi.selectItemByData("ReportRunner", runnerId); gdi.selectItemByData("ReportRunner", runnerId);
if (!oe->isReadOnly()) { if (!oe->isReadOnly()) {
@ -1546,43 +1551,50 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
gdi.registerEvent("DataUpdate", RunnerCB); gdi.registerEvent("DataUpdate", RunnerCB);
gdi.registerEvent("ReadCard", RunnerCB); gdi.registerEvent("ReadCard", RunnerCB);
gdi.fillDown();
oe->calculateResults(oEvent::RTClassResult);
if (runnerId > 0) { if (runnerId > 0) {
runnersToReport.resize(1); runnersToReport.resize(1);
runnersToReport[0] = make_pair(runnerId, false); runnersToReport[0] = make_pair(runnerId, false);
} }
generateRunnerReport(*oe, gdi, runnersToReport);
if (runnersToReport.size() == 1)
runnerId = runnersToReport[0].first;
}
void TabRunner::generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport) {
gdi.fillDown();
cTeam t = 0; cTeam t = 0;
set<int> clsSet;
for (size_t k = 0; k < runnersToReport.size(); k++) { for (size_t k = 0; k < runnersToReport.size(); k++) {
pRunner r = oe->getRunner(runnersToReport[k].first, 0); pRunner r = oe.getRunner(runnersToReport[k].first, 0);
clsSet.insert(r->getClassId(true));
if (r && r->getTeam()) { if (r && r->getTeam()) {
pClass cls = r->getClassRef(true); pClass cls = r->getClassRef(true);
if (cls && cls->getClassType() == oClassPatrol) if (cls && cls->getClassType() != oClassRelay)
continue; continue;
if (t == 0) if (t == 0)
t = r->getTeam(); t = r->getTeam();
} }
} }
oe.calculateResults(clsSet, oEvent::ResultType::PreliminarySplitResults, true);
if (runnersToReport.size() == 1) oe.calculateResults(clsSet, oEvent::ResultType::ClassResult);
runnerId = runnersToReport[0].first;
if (t == 0) { if (t == 0) {
for (size_t k = 0; k < runnersToReport.size(); k++) for (size_t k = 0; k < runnersToReport.size(); k++)
runnerReport(gdi, runnersToReport[k].first, runnersToReport[k].second); runnerReport(oe, gdi, runnersToReport[k].first, runnersToReport[k].second);
} }
else { else {
oe->calculateTeamResults(false); oe.calculateTeamResults(false);
set<int> selectedRunners; set<int> selectedRunners;
bool selHasRes = false; bool selHasRes = false;
for (size_t k = 0; k < runnersToReport.size(); k++) { for (size_t k = 0; k < runnersToReport.size(); k++) {
selectedRunners.insert(runnersToReport[k].first); selectedRunners.insert(runnersToReport[k].first);
pRunner r = oe->getRunner(runnersToReport[k].first, 0); pRunner r = oe.getRunner(runnersToReport[k].first, 0);
if (r->getStatus() != StatusUnknown) if (r && r->hasOnCourseResult())
selHasRes = true; selHasRes = true;
} }
@ -1593,7 +1605,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
tInfo += L", +" + formatTime(t->getTimeAfter(-1)); tInfo += L", +" + formatTime(t->getTimeAfter(-1));
} }
else if (t->getStatus() != StatusUnknown) { else if (t->getStatus() != StatusUnknown) {
tInfo += L" " + t->getStatusS(); tInfo += L" " + t->getStatusS(true);
} }
gdi.addStringUT(fontMediumPlus, t->getClass(true)); gdi.addStringUT(fontMediumPlus, t->getClass(true));
@ -1613,10 +1625,10 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
bool selected = selectedRunners.count(r->getId()) > 0; bool selected = selectedRunners.count(r->getId()) > 0;
if (selHasRes) { if (selHasRes) {
runnerReport(gdi, r->getId(), !selected); runnerReport(oe, gdi, r->getId(), !selected);
} }
else { else {
runnerReport(gdi, r->getId(), !nextSelected); runnerReport(oe, gdi, r->getId(), !nextSelected);
} }
visitedSelected |= selected; visitedSelected |= selected;
@ -1625,8 +1637,8 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
} }
} }
void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) { void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
pRunner r = oe->getRunner(id, 0); pRunner r = oe.getRunner(id, 0);
if (!r || ! r->getClassRef(false)) if (!r || ! r->getClassRef(false))
return; return;
@ -1647,18 +1659,18 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
wstring str; wstring str;
if (r->getTeam() == 0) { if (r->getTeam() == 0) {
str = oe->formatListString(lRunnerTimeStatus, r); str = oe.formatListString(lRunnerTimeStatus, r);
} }
else { else {
str = oe->formatListString(lTeamLegTimeStatus, r); str = oe.formatListString(lTeamLegTimeStatus, r);
str += L" (" + oe->formatListString(lRunnerTimeStatus, r) + L")"; str += L" (" + oe.formatListString(lRunnerTimeStatus, r) + L")";
} }
gdi.dropLine(0.3); gdi.dropLine(0.3);
if (r->statusOK()) { if (r->statusOK()) {
int total, finished, dns; int total, finished, dns;
oe->getNumClassRunners(r->getClassId(true), r->getLegNumber(), total, finished, dns); oe.getNumClassRunners(r->getClassId(true), r->getLegNumber(), total, finished, dns);
if (r->getTeam() == 0) { if (r->getTeam() == 0) {
gdi.addString("", fontMediumPlus, L"Tid: X, nuvarande placering Y/Z.#" + str + L"#" + r->getPlaceS() + L"#" + itow(finished)); gdi.addString("", fontMediumPlus, L"Tid: X, nuvarande placering Y/Z.#" + str + L"#" + r->getPlaceS() + L"#" + itow(finished));
@ -1686,12 +1698,12 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
if (r->getFinishTime() > 0) if (r->getFinishTime() > 0)
gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS()); gdi.addString("", fontMedium, L"Måltid: X #" + r->getFinishTimeS());
const wstring &after = oe->formatListString(lRunnerTimeAfter, r); const wstring &after = oe.formatListString(lRunnerTimeAfter, r);
if (!after.empty()) { if (!after.empty()) {
gdi.addString("", fontMedium, L"Tid efter: X #" + after); gdi.addString("", fontMedium, L"Tid efter: X #" + after);
} }
const wstring &lost = oe->formatListString(lRunnerMissedTime, r); const wstring &lost = oe.formatListString(lRunnerLostTime, r);
if (!lost.empty()) { if (!lost.empty()) {
gdi.addString("", fontMedium, L"Bomtid: X #" + lost).setColor(colorDarkRed); gdi.addString("", fontMedium, L"Bomtid: X #" + lost).setColor(colorDarkRed);
} }
@ -1798,7 +1810,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
} }
else { else {
vector<pFreePunch> punches; vector<pFreePunch> punches;
oe->getPunchesForRunner(r->getId(), punches); oe.getPunchesForRunner(r->getId(), punches);
int lastT = r->getStartTime(); int lastT = r->getStartTime();
for (size_t k = 0; k < punches.size(); k++) { for (size_t k = 0; k < punches.size(); k++) {
@ -1830,7 +1842,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
int t = punches[k]->getAdjustedTime(); int t = punches[k]->getAdjustedTime();
if (t>0) { if (t>0) {
int st = r->getStartTime(); int st = r->getStartTime();
gdi.addString("", yp + lh, cx, normalText, L"Klocktid: X#" + oe->getAbsTime(t), limit); gdi.addString("", yp + lh, cx, normalText, L"Klocktid: X#" + oe.getAbsTime(t), limit);
if (st > 0 && t > st) { if (st > 0 && t > st) {
wstring split = formatTimeHMS(t-st); wstring split = formatTimeHMS(t-st);
if (lastT>0 && st != lastT && lastT < t) if (lastT>0 && st != lastT && lastT < t)
@ -2036,7 +2048,6 @@ void TabRunner::showInForestList(gdioutput &gdi)
clearInForestData(); clearInForestData();
bool hasDNS; bool hasDNS;
oe->analyseDNS(unknown_dns, known_dns, known, unknown, hasDNS); oe->analyseDNS(unknown_dns, known_dns, known, unknown, hasDNS);
oe->setupCardHash(false);
if (!unknown.empty()) { if (!unknown.empty()) {
gdi.dropLine(); gdi.dropLine();
gdi.dropLine(0.5); gdi.dropLine(0.5);
@ -2070,8 +2081,6 @@ void TabRunner::showInForestList(gdioutput &gdi)
else else
gdi.disableInput("SetUnknown"); gdi.disableInput("SetUnknown");
oe->setupCardHash(true);
if (known.empty() && unknown.empty() && known_dns.empty()) { if (known.empty() && unknown.empty() && known_dns.empty()) {
gdi.addString("", 10, "inforestwarning"); gdi.addString("", 10, "inforestwarning");
} }
@ -2095,7 +2104,14 @@ void TabRunner::listRunners(gdioutput &gdi, const vector<pRunner> &r, bool filte
gdi.addStringUT(yp, xp+350, 0, r[k]->getClub(), 190); gdi.addStringUT(yp, xp+350, 0, r[k]->getClub(), 190);
int c = r[k]->getCardNo(); int c = r[k]->getCardNo();
if (c>0) { if (c>0) {
oe->getRunnersByCardNo(c, true, true, out); {
vector<pRunner> o2;
oe->getRunnersByCardNo(c, false, oEvent::CardLookupProperty::SkipNoStart, o2);
for (pRunner r : o2) {
if (!r->skip())
out.push_back(r);
}
}
if (out.size() <= 1) { if (out.size() <= 1) {
gdi.addStringUT(yp, xp+550, 0, "(" + itos(c) + ")", 190); gdi.addStringUT(yp, xp+550, 0, "(" + itos(c) + ")", 190);
} }
@ -2186,7 +2202,6 @@ void disablePunchCourseChange(gdioutput &gdi)
gdi.disableInput("PTime"); gdi.disableInput("PTime");
gdi.setText("PTime", L""); gdi.setText("PTime", L"");
gdi.selectItemByData("Punches", -1); gdi.selectItemByData("Punches", -1);
} }
void disablePunchCourse(gdioutput &gdi) void disablePunchCourse(gdioutput &gdi)
@ -2206,37 +2221,47 @@ void UpdateStatus(gdioutput &gdi, pRunner r)
gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true); gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
} }
int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
{ DWORD rid = runnerId;
DWORD rid=runnerId;
if (!rid) if (!rid)
return 0; return 0;
pRunner r=oe->getRunner(rid, 0); pRunner r = oe->getRunner(rid, 0);
if (!r){ if (!r) {
gdi.alert("Deltagaren måste sparas innan stämplingar kan hanteras."); gdi.alert("Deltagaren måste sparas innan stämplingar kan hanteras.");
return 0; return 0;
} }
if (type == GUI_LISTBOXSELECT) {
ListBoxInfo bi = *(ListBoxInfo *)data;
if (bi.id == "Course") {
if (signed(bi.data) >= 0) {
pCourse pc = r->getCourse(true);
if (!pc) return 0;
return gdi.sendCtrlMessage("AddC");
}
}
}
else if (type == GUI_LISTBOX) {
ListBoxInfo bi = *(ListBoxInfo *)data;
if (type==GUI_LISTBOX){ if (bi.id == "Punches") {
ListBoxInfo bi=*(ListBoxInfo *)data;
if (bi.id=="Punches") {
if (bi.data != -1) { if (bi.data != -1) {
pCard card=r->getCard(); pCard card = r->getCard();
if (!card) return 0; if (!card) return 0;
pPunch punch = card->getPunchByIndex(bi.data); pPunch punch = card->getPunchByIndex(bi.data);
if (!punch) if (!punch)
throw meosException("Punch not found."); throw meosException("Punch not found.");
wstring ptime=punch->getTime(); wstring ptime;
if (punch->getTimeInt() > 0)
ptime = punch->getTime();
if (!ptime.empty()) {
gdi.enableInput("SaveC");
gdi.setText("PTime", ptime); gdi.setText("PTime", ptime);
}
gdi.enableInput("SaveC");
gdi.enableInput("RemoveC"); gdi.enableInput("RemoveC");
gdi.enableInput("PTime"); gdi.enableInput("PTime");
} }
@ -2244,46 +2269,44 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
gdi.disableInput("SaveC"); gdi.disableInput("SaveC");
gdi.disableInput("RemoveC"); gdi.disableInput("RemoveC");
gdi.setText("PTime", L""); gdi.setText("PTime", L"");
gdi.disableInput("PTime");
} }
disablePunchCourseAdd(gdi); disablePunchCourseAdd(gdi);
} }
else if (bi.id=="Course") { else if (bi.id == "Course") {
if (signed(bi.data)>=0) { if (signed(bi.data) >= 0) {
pCourse pc=r->getCourse(true); pCourse pc = r->getCourse(true);
if (!pc) return 0; if (!pc) return 0;
gdi.enableInput("AddC"); gdi.enableInput("AddC");
gdi.enableInput("AddAllC"); gdi.enableInput("AddAllC");
} }
else{ else {
gdi.disableInput("AddC"); gdi.disableInput("AddC");
gdi.disableInput("AddAllC"); gdi.disableInput("AddAllC");
} }
disablePunchCourseChange(gdi); disablePunchCourseChange(gdi);
} }
} }
else if (type==GUI_BUTTON){ else if (type == GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data; ButtonInfo bi = *(ButtonInfo *)data;
pCard card=r->getCard(); pCard card = r->getCard();
if (!card){ if (!card) {
if (!gdi.ask(L"ask:addpunches")) if (!gdi.ask(L"ask:addpunches"))
return 0; return 0;
card=oe->allocateCard(r); card = oe->allocateCard(r);
card->setCardNo(r->getCardNo()); card->setCardNo(r->getCardNo());
vector<int> mp; vector<int> mp;
r->addPunches(card, mp); r->addPunches(card, mp);
} }
if (bi.id=="AddC"){ if (bi.id == "AddC") {
vector<int> mp; vector<int> mp;
r->evaluateCard(true, mp); r->evaluateCard(true, mp);
pCourse pc=r->getCourse(true); pCourse pc = r->getCourse(true);
if (!pc) return 0; if (!pc) return 0;
@ -2292,7 +2315,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
if (!gdi.getSelectedItem("Course", lbi)) if (!gdi.getSelectedItem("Course", lbi))
return 0; return 0;
oControl *oc=pc->getControl(lbi.data); oControl *oc = pc->getControl(lbi.data);
if (!oc) return 0; if (!oc) return 0;
vector<int> nmp; vector<int> nmp;
@ -2301,7 +2324,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
r->evaluateCard(true, nmp, oc->getFirstNumber()); //Add this punch r->evaluateCard(true, nmp, oc->getFirstNumber()); //Add this punch
} }
else { else {
for (size_t k = 0; k<mp.size(); k++) { for (size_t k = 0; k < mp.size(); k++) {
if (oc->hasNumber(mp[k])) if (oc->hasNumber(mp[k]))
r->evaluateCard(true, nmp, mp[k]); //Add this punch r->evaluateCard(true, nmp, mp[k]); //Add this punch
} }
@ -2314,13 +2337,12 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
card->fillPunches(gdi, "Punches", pc); card->fillPunches(gdi, "Punches", pc);
UpdateStatus(gdi, r); UpdateStatus(gdi, r);
} }
else if (bi.id=="AddAllC"){ else if (bi.id == "AddAllC") {
vector<int> mp; vector<int> mp;
r->evaluateCard(true, mp); r->evaluateCard(true, mp);
vector<int>::iterator it=mp.begin(); vector<int>::iterator it = mp.begin();
while (it != mp.end()) {
while(it!=mp.end()){
vector<int> nmp; vector<int> nmp;
r->evaluateCard(true, nmp, *it); //Add this punch r->evaluateCard(true, nmp, *it); //Add this punch
++it; ++it;
@ -2336,14 +2358,14 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
r->hasManuallyUpdatedTimeStatus(); r->hasManuallyUpdatedTimeStatus();
UpdateStatus(gdi, r); UpdateStatus(gdi, r);
} }
else if (bi.id=="SaveC"){ else if (bi.id == "SaveC") {
//int time=oe->GetRelTime(); if (!savePunchTime(r, gdi))
return false;
ListBoxInfo lbi; ListBoxInfo lbi;
if (!gdi.getSelectedItem("Punches", lbi)) if (!gdi.getSelectedItem("Punches", lbi))
return 0; return 0;
/*
pCard pc=r->getCard(); pCard pc=r->getCard();
if (!pc) return 0; if (!pc) return 0;
@ -2355,11 +2377,11 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
pc->setPunchTime(pp, gdi.getText("PTime")); pc->setPunchTime(pp, gdi.getText("PTime"));
vector<int> mp;
r->evaluateCard(true, mp); r->evaluateCard(true, mp);
//synchronize SQL //synchronize SQL
card->synchronize(); card->synchronize();*/
vector<int> mp;
r->synchronize(); r->synchronize();
r->evaluateCard(true, mp); r->evaluateCard(true, mp);
r->hasManuallyUpdatedTimeStatus(); r->hasManuallyUpdatedTimeStatus();
@ -2371,6 +2393,30 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
} }
bool TabRunner::savePunchTime(pRunner r, gdioutput &gdi) {
ListBoxInfo lbi;
pCard card = r->getCard();
if (!card)
return false;
if (!gdi.getSelectedItem("Punches", lbi))
return 0;
pPunch pp = card->getPunchByIndex(lbi.data);
if (!pp)
return false;
card->setPunchTime(pp, gdi.getText("PTime"));
vector<int> mp;
r->evaluateCard(true, mp);
//synchronize SQL
card->synchronize();
return true;
}
bool TabRunner::loadPage(gdioutput &gdi) bool TabRunner::loadPage(gdioutput &gdi)
{ {
oe->reEvaluateAll(set<int>(), true); oe->reEvaluateAll(set<int>(), true);
@ -2503,6 +2549,7 @@ bool TabRunner::loadPage(gdioutput &gdi)
if (numSL > 0) if (numSL > 0)
gdi.fillRight(); gdi.fillRight();
if (!oe->getMeOSFeatures().withoutCourses(*oe)) {
gdi.addSelection("RCourse", numSL == 0 ? 220 : 180, 300, RunnerCB, L"Bana:"); gdi.addSelection("RCourse", numSL == 0 ? 220 : 180, 300, RunnerCB, L"Bana:");
oe->fillCourses(gdi, "RCourse", true); oe->fillCourses(gdi, "RCourse", true);
gdi.addItem("RCourse", lang.tl("[Klassens bana]"), 0); gdi.addItem("RCourse", lang.tl("[Klassens bana]"), 0);
@ -2524,6 +2571,7 @@ bool TabRunner::loadPage(gdioutput &gdi)
gdi.addItem("NumShort", data); gdi.addItem("NumShort", data);
gdi.popX(); gdi.popX();
} }
}
gdi.pushX(); gdi.pushX();
gdi.fillRight(); gdi.fillRight();
@ -2777,9 +2825,9 @@ bool TabRunner::canSetFinish(pRunner r) const {
pRunner TabRunner::warnDuplicateCard(int cno, pRunner r) { pRunner TabRunner::warnDuplicateCard(int cno, pRunner r) {
pRunner warnCardDupl = 0; pRunner warnCardDupl = 0;
if (!r->getCard()) { if (!r->getCard() && cno != 0) {
vector<pRunner> allR; vector<pRunner> allR;
oe->getRunners(0, 0, allR, false); oe->getRunnersByCardNo(cno, false, oEvent::CardLookupProperty::Any, allR);
for (size_t k = 0; k < allR.size(); k++) { for (size_t k = 0; k < allR.size(); k++) {
if (!r->canShareCard(allR[k], cno)) { if (!r->canShareCard(allR[k], cno)) {
warnCardDupl = allR[k]; warnCardDupl = allR[k];
@ -2815,10 +2863,14 @@ int TabRunner::numShorteningLevels() const {
map<int, int> known; map<int, int> known;
int res = 0; int res = 0;
for (size_t k = 0; k < allCrs.size(); k++) { for (size_t k = 0; k < allCrs.size(); k++) {
pCourse sh = allCrs[k]->getShorterVersion(); auto shInfo = allCrs[k]->getShorterVersion();
touch.clear(); pCourse cCourse = allCrs[k];
int count = 0; int count = 0;
if (shInfo.second) {
pCourse sh = shInfo.second;
touch.clear();
while (sh && !touch.count(sh->getId())) { while (sh && !touch.count(sh->getId())) {
cCourse = sh;
count++; count++;
map<int, int>::iterator r = known.find(sh->getId()); map<int, int>::iterator r = known.find(sh->getId());
if (r != known.end()) { if (r != known.end()) {
@ -2826,8 +2878,18 @@ int TabRunner::numShorteningLevels() const {
break; break;
} }
touch.insert(sh->getId()); touch.insert(sh->getId());
sh = sh->getShorterVersion(); shInfo = sh->getShorterVersion();
sh = shInfo.second;
} }
}
if (shInfo.first && !shInfo.second) {
// Course with loops
int nl = cCourse->getNumLoops();
if (nl > 0)
count += nl - 1;
}
known[allCrs[k]->getId()] = count; known[allCrs[k]->getId()] = count;
res = max(res, count); res = max(res, count);
} }
@ -2836,7 +2898,7 @@ int TabRunner::numShorteningLevels() const {
void TabRunner::updateNumShort(gdioutput &gdi, pCourse crs, pRunner r) { void TabRunner::updateNumShort(gdioutput &gdi, pCourse crs, pRunner r) {
if (gdi.hasField("NumShort")) { if (gdi.hasField("NumShort")) {
if (crs && crs->getShorterVersion()) { if (crs && crs->getShorterVersion().first) {
gdi.enableInput("NumShort"); gdi.enableInput("NumShort");
if (r) if (r)
gdi.selectItemByData("NumShort", r->getNumShortening()); gdi.selectItemByData("NumShort", r->getNumShortening());
@ -2871,7 +2933,6 @@ void TabRunner::autoGrowCourse(gdioutput &gdi) {
} }
} }
void TabRunner::EconomyHandler::init(oRunner &r) { void TabRunner::EconomyHandler::init(oRunner &r) {
oe = r.getEvent(); oe = r.getEvent();
runnerId = r.getId(); runnerId = r.getId();
@ -2938,7 +2999,6 @@ void TabRunner::EconomyHandler::save(gdioutput &gdi) {
int paid = oe->interpretCurrency(gdi.getText("PaidAmount")); int paid = oe->interpretCurrency(gdi.getText("PaidAmount"));
r.getDI().setInt("Paid", paid); r.getDI().setInt("Paid", paid);
if (paid != 0) { if (paid != 0) {
int m = gdi.getSelectedItem("").first; int m = gdi.getSelectedItem("").first;
if (m != 1000) if (m != 1000)

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -71,11 +71,12 @@ private:
vector<pRunner> known; vector<pRunner> known;
vector<pRunner> unknown; vector<pRunner> unknown;
void clearInForestData(); void clearInForestData();
bool savePunchTime(pRunner r, gdioutput &gdi);
PrinterObject splitPrinter; PrinterObject splitPrinter;
void showRunnerReport(gdioutput &gdi); void showRunnerReport(gdioutput &gdi);
void runnerReport(gdioutput &gdi, int id, bool compactReport); static void runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compactReport);
void showVacancyList(gdioutput &gdi, const string &method="", int classId=0); void showVacancyList(gdioutput &gdi, const string &method="", int classId=0);
void showCardsList(gdioutput &gdi); void showCardsList(gdioutput &gdi);
@ -122,7 +123,7 @@ public:
bool loadPage(gdioutput &gdi); bool loadPage(gdioutput &gdi);
bool loadPage(gdioutput &gdi, int runnerId); bool loadPage(gdioutput &gdi, int runnerId);
static void generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport);
TabRunner(oEvent *oe); TabRunner(oEvent *oe);
~TabRunner(void); ~TabRunner(void);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -119,8 +119,8 @@ int SportIdentCB(gdioutput *gdi, int type, void *data) {
int TabSI::siCB(gdioutput &gdi, int type, void *data) int TabSI::siCB(gdioutput &gdi, int type, void *data)
{ {
if (type==GUI_BUTTON) { if (type == GUI_BUTTON) {
ButtonInfo bi=*(ButtonInfo *)data; ButtonInfo bi = *(ButtonInfo *)data;
if (bi.id == "ClearMemory") { if (bi.id == "ClearMemory") {
if (gdi.ask(L"Do you want to clear the card memory?")) { if (gdi.ask(L"Do you want to clear the card memory?")) {
@ -149,21 +149,21 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
else if (bi.id == "CreateCompetition") { else if (bi.id == "CreateCompetition") {
createCompetitionFromCards(gdi); createCompetitionFromCards(gdi);
} }
else if (bi.id=="SIPassive") { else if (bi.id == "SIPassive") {
wstring port=gdi.getText("ComPortName"); wstring port = gdi.getText("ComPortName");
if (gSI->openComListen(port.c_str(), gdi.getTextNo("BaudRate"))) { if (gSI->openComListen(port.c_str(), gdi.getTextNo("BaudRate"))) {
gSI->startMonitorThread(port.c_str()); gSI->startMonitorThread(port.c_str());
loadPage(gdi); loadPage(gdi);
gdi.addString("", 1, L"Lyssnar på X.#"+port).setColor(colorDarkGreen); gdi.addString("", 1, L"Lyssnar på X.#" + port).setColor(colorDarkGreen);
} }
else else
gdi.addString("", 1, "FEL: Porten kunde inte öppnas").setColor(colorRed); gdi.addString("", 1, "FEL: Porten kunde inte öppnas").setColor(colorRed);
gdi.dropLine(); gdi.dropLine();
gdi.refresh(); gdi.refresh();
} }
else if (bi.id=="CancelTCP") else if (bi.id == "CancelTCP")
gdi.restore("TCP"); gdi.restore("TCP");
else if (bi.id=="StartTCP") { else if (bi.id == "StartTCP") {
gSI->tcpAddPort(gdi.getTextNo("tcpPortNo"), 0); gSI->tcpAddPort(gdi.getTextNo("tcpPortNo"), 0);
gdi.restore("TCP"); gdi.restore("TCP");
gSI->startMonitorThread(L"TCP"); gSI->startMonitorThread(L"TCP");
@ -174,16 +174,16 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
refillComPorts(gdi); refillComPorts(gdi);
gdi.refresh(); gdi.refresh();
} }
else if (bi.id=="StartSI") { else if (bi.id == "StartSI") {
wchar_t bf[64]; wchar_t bf[64];
ListBoxInfo lbi; ListBoxInfo lbi;
if (gdi.getSelectedItem("ComPort", lbi)) { if (gdi.getSelectedItem("ComPort", lbi)) {
swprintf_s(bf, 64, L"COM%d", lbi.data); swprintf_s(bf, 64, L"COM%d", lbi.data);
wstring port=bf; wstring port = bf;
if (lbi.text.substr(0, 3)==L"TCP") if (lbi.text.substr(0, 3) == L"TCP")
port=L"TCP"; port = L"TCP";
if (gSI->isPortOpen(port)) { if (gSI->isPortOpen(port)) {
gSI->closeCom(port.c_str()); gSI->closeCom(port.c_str());
@ -194,12 +194,12 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
} }
else { else {
gdi.fillDown(); gdi.fillDown();
if (port==L"TCP") { if (port == L"TCP") {
gdi.setRestorePoint("TCP"); gdi.setRestorePoint("TCP");
gdi.dropLine(); gdi.dropLine();
gdi.pushX(); gdi.pushX();
gdi.fillRight(); gdi.fillRight();
gdi.addInput("tcpPortNo", L"10000", 8,0, L"Port för TCP:"); gdi.addInput("tcpPortNo", L"10000", 8, 0, L"Port för TCP:");
gdi.dropLine(); gdi.dropLine();
gdi.addButton("StartTCP", "Starta", SportIdentCB); gdi.addButton("StartTCP", "Starta", SportIdentCB);
gdi.addButton("CancelTCP", "Avbryt", SportIdentCB); gdi.addButton("CancelTCP", "Avbryt", SportIdentCB);
@ -214,16 +214,16 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.addStringUT(0, lang.tl(L"Startar SI på ") + port + L"..."); gdi.addStringUT(0, lang.tl(L"Startar SI på ") + port + L"...");
gdi.refresh(); gdi.refresh();
if (gSI->openCom(port.c_str())){ if (gSI->openCom(port.c_str())) {
gSI->startMonitorThread(port.c_str()); gSI->startMonitorThread(port.c_str());
gdi.addStringUT(0, lang.tl(L"SI på ")+ port + L": "+lang.tl(L"OK")); gdi.addStringUT(0, lang.tl(L"SI på ") + port + L": " + lang.tl(L"OK"));
printSIInfo(gdi, port); printSIInfo(gdi, port);
SI_StationInfo *si = gSI->findStation(port); SI_StationInfo *si = gSI->findStation(port);
if (si && !si->extended()) if (si && !si->extended())
gdi.addString("", boldText, "warn:notextended").setColor(colorDarkRed); gdi.addString("", boldText, "warn:notextended").setColor(colorDarkRed);
} }
else{ else {
//Retry... //Retry...
Sleep(300); Sleep(300);
if (gSI->openCom(port.c_str())) { if (gSI->openCom(port.c_str())) {
@ -270,22 +270,22 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.refresh(); gdi.refresh();
} }
} }
else if (bi.id=="SIInfo") { else if (bi.id == "SIInfo") {
wchar_t bf[64]; wchar_t bf[64];
ListBoxInfo lbi; ListBoxInfo lbi;
if (gdi.getSelectedItem("ComPort", lbi)) if (gdi.getSelectedItem("ComPort", lbi))
{ {
if (lbi.text.substr(0,3)==L"TCP") if (lbi.text.substr(0, 3) == L"TCP")
swprintf_s(bf, 64, L"TCP"); swprintf_s(bf, 64, L"TCP");
else else
swprintf_s(bf, 64, L"COM%d", lbi.data); swprintf_s(bf, 64, L"COM%d", lbi.data);
gdi.fillDown(); gdi.fillDown();
gdi.addStringUT(0, lang.tl(L"Hämtar information om ") + wstring(bf)+ L"."); gdi.addStringUT(0, lang.tl(L"Hämtar information om ") + wstring(bf) + L".");
printSIInfo(gdi, bf); printSIInfo(gdi, bf);
gdi.refresh(); gdi.refresh();
} }
} }
else if (bi.id=="AutoDetect") else if (bi.id == "AutoDetect")
{ {
gdi.fillDown(); gdi.fillDown();
gdi.addString("", 0, "Söker efter SI-enheter... "); gdi.addString("", 0, "Söker efter SI-enheter... ");
@ -299,13 +299,13 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
wchar_t bf[128]; wchar_t bf[128];
gSI->closeCom(0); gSI->closeCom(0);
while(!ports.empty()) { while (!ports.empty()) {
int p=ports.front(); int p = ports.front();
swprintf_s(bf, 128, L"COM%d", p); swprintf_s(bf, 128, L"COM%d", p);
char bfn[128]; char bfn[128];
sprintf_s(bfn, 128, "COM%d", p); sprintf_s(bfn, 128, "COM%d", p);
gdi.addString((string("SIInfo")+bfn).c_str(), 0, L"#" + lang.tl(L"Startar SI på ") + wstring(bf) + L"..."); gdi.addString((string("SIInfo") + bfn).c_str(), 0, L"#" + lang.tl(L"Startar SI på ") + wstring(bf) + L"...");
gdi.refresh(); gdi.refresh();
if (gSI->openCom(bf)) { if (gSI->openCom(bf)) {
gSI->startMonitorThread(bf); gSI->startMonitorThread(bf);
@ -325,7 +325,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (si && !si->extended()) if (si && !si->extended())
gdi.addString("", boldText, "warn:notextended").setColor(colorDarkRed); gdi.addString("", boldText, "warn:notextended").setColor(colorDarkRed);
} }
else gdi.addStringUT(0, lang.tl(L"SI på ") + wstring(bf) + L": " +lang.tl(L"FEL, inget svar")); else gdi.addStringUT(0, lang.tl(L"SI på ") + wstring(bf) + L": " + lang.tl(L"FEL, inget svar"));
gdi.refresh(); gdi.refresh();
gdi.popX(); gdi.popX();
@ -352,8 +352,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
else if (bi.id == "TieOK") { else if (bi.id == "TieOK") {
tieCard(gdi); tieCard(gdi);
} }
else if (bi.id=="Interactive") { else if (bi.id == "Interactive") {
interactiveReadout=gdi.isChecked(bi.id); interactiveReadout = gdi.isChecked(bi.id);
gEvent->setProperty("Interactive", interactiveReadout); gEvent->setProperty("Interactive", interactiveReadout);
if (mode == ModeAssignCards) { if (mode == ModeAssignCards) {
@ -361,14 +361,14 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
showAssignCard(gdi, false); showAssignCard(gdi, false);
} }
} }
else if (bi.id=="Database") { else if (bi.id == "Database") {
useDatabase=gdi.isChecked(bi.id); useDatabase = gdi.isChecked(bi.id);
gEvent->setProperty("Database", useDatabase); gEvent->setProperty("Database", useDatabase);
} }
else if (bi.id=="PrintSplits") { else if (bi.id == "PrintSplits") {
printSplits=gdi.isChecked(bi.id); printSplits = gdi.isChecked(bi.id);
} }
else if (bi.id=="StartInfo") { else if (bi.id == "StartInfo") {
printStartInfo = gdi.isChecked(bi.id); printStartInfo = gdi.isChecked(bi.id);
} }
else if (bi.id == "UseManualInput") { else if (bi.id == "UseManualInput") {
@ -378,7 +378,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (manualInput) if (manualInput)
showManualInput(gdi); showManualInput(gdi);
} }
else if (bi.id=="Import") { else if (bi.id == "Import") {
int origin = bi.getExtraInt(); int origin = bi.getExtraInt();
vector< pair<wstring, wstring> > ext; vector< pair<wstring, wstring> > ext;
@ -399,7 +399,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
filterDate.clear(); filterDate.clear();
filterDate.push_back(lang.tl("Inget filter")); filterDate.push_back(lang.tl("Inget filter"));
for (set<string>::iterator it = dates.begin(); it!=dates.end(); ++it) for (set<string>::iterator it = dates.begin(); it != dates.end(); ++it)
filterDate.push_back(gdi.widen(*it)); filterDate.push_back(gdi.widen(*it));
gdi.dropLine(2); gdi.dropLine(2);
@ -415,7 +415,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.selectItemByData("ControlType", oPunch::PunchCheck); gdi.selectItemByData("ControlType", oPunch::PunchCheck);
gdi.addSelection("Filter", 150, 300, 0, L"Datumfilter:"); gdi.addSelection("Filter", 150, 300, 0, L"Datumfilter:");
for (size_t k = 0; k<filterDate.size(); k++) { for (size_t k = 0; k < filterDate.size(); k++) {
gdi.addItem("Filter", filterDate[k], k); gdi.addItem("Filter", filterDate[k], k);
} }
gdi.selectItemByData("Filter", 0); gdi.selectItemByData("Filter", 0);
@ -452,53 +452,52 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
} }
} }
} }
else if (bi.id=="SavePunches") { else if (bi.id == "SavePunches") {
int origin = bi.getExtraInt(); int origin = bi.getExtraInt();
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("ControlType", lbi); gdi.getSelectedItem("ControlType", lbi);
int type = lbi.data; int type = lbi.data;
gdi.getSelectedItem("Filter", lbi); gdi.getSelectedItem("Filter", lbi);
bool dofilter = signed(lbi.data)>0; bool dofilter = signed(lbi.data) > 0;
string filter = lbi.data < filterDate.size() ? gdi.narrow(filterDate[lbi.data]) : ""; string filter = lbi.data < filterDate.size() ? gdi.narrow(filterDate[lbi.data]) : "";
gdi.restore("Help"); gdi.restore("Help");
for (size_t k=0;k<punches.size();k++) { for (size_t k = 0; k < punches.size(); k++) {
if (dofilter && filter != punches[k].date) if (dofilter && filter != punches[k].date)
continue; continue;
oe->addFreePunch(punches[k].time, type, punches[k].card, true); oe->addFreePunch(punches[k].time, type, punches[k].card, true);
} }
punches.clear(); punches.clear();
if (origin==1) { if (origin == 1) {
TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab)); TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab));
tc.showInForestList(gdi); tc.showInForestList(gdi);
} }
} }
else if (bi.id=="SaveCards") { else if (bi.id == "SaveCards") {
int origin = bi.getExtraInt(); int origin = bi.getExtraInt();
gdi.restore("Help"); gdi.restore("Help");
oe->synchronizeList(oLCardId, true, false); oe->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
oe->synchronizeList(oLRunnerId, false, true); for (size_t k = 0; k < cards.size(); k++)
for (size_t k=0;k<cards.size();k++)
insertSICard(gdi, cards[k]); insertSICard(gdi, cards[k]);
oe->reEvaluateAll(set<int>(), true); oe->reEvaluateAll(set<int>(), true);
cards.clear(); cards.clear();
if (origin==1) { if (origin == 1) {
TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab)); TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab));
tc.showInForestList(gdi); tc.showInForestList(gdi);
} }
} }
else if (bi.id=="Save") { else if (bi.id == "Save") {
SICard sic(ConvertedTimeStatus::Hour24); SICard sic(ConvertedTimeStatus::Hour24);
sic.CheckPunch.Code = -1; sic.CheckPunch.Code = -1;
sic.CardNumber=gdi.getTextNo("SI"); sic.CardNumber = gdi.getTextNo("SI");
int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum()); int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum()); int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
if (f < s) { if (f < s) {
f += 24 * 3600; f += 24 * 3600;
} }
sic.FinishPunch.Time= f % (24*3600); sic.FinishPunch.Time = f % (24 * 3600);
sic.StartPunch.Time = s % (24*3600); sic.StartPunch.Time = s % (24 * 3600);
if (!gdi.isChecked("HasFinish")) { if (!gdi.isChecked("HasFinish")) {
sic.FinishPunch.Code = -1; sic.FinishPunch.Code = -1;
sic.FinishPunch.Time = 0; sic.FinishPunch.Time = 0;
@ -511,11 +510,11 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
double t = 0.1; double t = 0.1;
for (sic.nPunch = 0; sic.nPunch<unsigned(NC); sic.nPunch++) { for (sic.nPunch = 0; sic.nPunch<unsigned(NC); sic.nPunch++) {
sic.Punch[sic.nPunch].Code=gdi.getTextNo("C" + itos(sic.nPunch+1)); sic.Punch[sic.nPunch].Code = gdi.getTextNo("C" + itos(sic.nPunch + 1));
sic.Punch[sic.nPunch].Time=int(f*t+s*(1.0-t)) % (24*3600); sic.Punch[sic.nPunch].Time = int(f*t + s*(1.0 - t)) % (24 * 3600);
t += ((1.0-t) * (sic.nPunch + 1) / 10.0) * ((rand() % 100) + 400.0)/500.0; t += ((1.0 - t) * (sic.nPunch + 1) / 10.0) * ((rand() % 100) + 400.0) / 500.0;
if ((sic.nPunch%11) == 1 || 5 == (sic.nPunch%8)) if ((sic.nPunch % 11) == 1 || 5 == (sic.nPunch % 8))
t += min(0.2, 0.9-t); t += min(0.2, 0.9 - t);
} }
gdi.getRecorder().record("insertCard(" + itos(sic.CardNumber) + ", \"" + sic.serializePunches() + "\"); //Readout card"); gdi.getRecorder().record("insertCard(" + itos(sic.CardNumber) + ", \"" + sic.serializePunches() + "\"); //Readout card");
@ -532,15 +531,15 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gSI->addCard(sic); gSI->addCard(sic);
} }
else if (bi.id=="SaveP") { else if (bi.id == "SaveP") {
SICard sic(ConvertedTimeStatus::Hour24); SICard sic(ConvertedTimeStatus::Hour24);
sic.clear(0); sic.clear(0);
sic.FinishPunch.Code = -1; sic.FinishPunch.Code = -1;
sic.CheckPunch.Code = -1; sic.CheckPunch.Code = -1;
sic.StartPunch.Code = -1; sic.StartPunch.Code = -1;
sic.CardNumber=gdi.getTextNo("SI"); sic.CardNumber = gdi.getTextNo("SI");
int f=convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum()); int f = convertAbsoluteTimeHMS(gdi.getText("Finish"), oe->getZeroTimeNum());
if (f > 0) { if (f > 0) {
sic.FinishPunch.Time = f; sic.FinishPunch.Time = f;
sic.FinishPunch.Code = 1; sic.FinishPunch.Code = 1;
@ -549,7 +548,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
} }
int s=convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum()); int s = convertAbsoluteTimeHMS(gdi.getText("Start"), oe->getZeroTimeNum());
if (s > 0) { if (s > 0) {
sic.StartPunch.Time = s; sic.StartPunch.Time = s;
sic.StartPunch.Code = 1; sic.StartPunch.Code = 1;
@ -558,17 +557,17 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
return 0; return 0;
} }
sic.Punch[sic.nPunch].Code=gdi.getTextNo("C1"); sic.Punch[sic.nPunch].Code = gdi.getTextNo("C1");
sic.Punch[sic.nPunch].Time=convertAbsoluteTimeHMS(gdi.getText("C2"), oe->getZeroTimeNum()); sic.Punch[sic.nPunch].Time = convertAbsoluteTimeHMS(gdi.getText("C2"), oe->getZeroTimeNum());
sic.nPunch = 1; sic.nPunch = 1;
sic.punchOnly = true; sic.punchOnly = true;
gSI->addCard(sic); gSI->addCard(sic);
} }
else if (bi.id=="Cancel") { else if (bi.id == "Cancel") {
int origin = bi.getExtraInt(); int origin = bi.getExtraInt();
activeSIC.clear(0); activeSIC.clear(0);
punches.clear(); punches.clear();
if (origin==1) { if (origin == 1) {
TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab)); TabRunner &tc = dynamic_cast<TabRunner &>(*gdi.getTabs().get(TRunnerTab));
tc.showInForestList(gdi); tc.showInForestList(gdi);
return 0; return 0;
@ -578,20 +577,20 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
checkMoreCardsInQueue(gdi); checkMoreCardsInQueue(gdi);
return 0; return 0;
} }
else if (bi.id=="OK1") { else if (bi.id == "OK1") {
wstring name=gdi.getText("Runners"); wstring name = gdi.getText("Runners");
wstring club=gdi.getText("Club", true); wstring club = gdi.getText("Club", true);
if (name.length()==0){ if (name.length() == 0) {
gdi.alert("Alla deltagare måste ha ett namn."); gdi.alert("Alla deltagare måste ha ett namn.");
return 0; return 0;
} }
pRunner r=0; pRunner r = 0;
DWORD rid; DWORD rid;
bool lookup = true; bool lookup = true;
if (gdi.getData("RunnerId", rid) && rid>0) { if (gdi.getData("RunnerId", rid) && rid > 0) {
r = gEvent->getRunner(rid, 0); r = gEvent->getRunner(rid, 0);
if (r && r->getCard()) { if (r && r->getCard()) {
@ -634,29 +633,29 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.fillRight(); gdi.fillRight();
gdi.pushX(); gdi.pushX();
SICard si_copy=activeSIC; SICard si_copy = activeSIC;
gEvent->convertTimes(nullptr, si_copy); gEvent->convertTimes(nullptr, si_copy);
//Find matching class... //Find matching class...
vector<pClass> classes; vector<pClass> classes;
int dist = gEvent->findBestClass(activeSIC, classes); int dist = gEvent->findBestClass(activeSIC, classes);
if (classes.size()==1 && dist == 0 && si_copy.StartPunch.Time>0 && classes[0]->getType()!=L"tmp") { if (classes.size() == 1 && dist == 0 && si_copy.StartPunch.Time > 0 && classes[0]->getType() != L"tmp") {
//We have a match! //We have a match!
wstring club = gdi.getText("Club", true); wstring club = gdi.getText("Club", true);
if (club.length()==0 && oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) { if (club.length() == 0 && oe->getMeOSFeatures().hasFeature(MeOSFeatures::Clubs)) {
pClub noClub = oe->getClub(oe->getVacantClub(true)); pClub noClub = oe->getClub(oe->getVacantClub(true));
if (noClub) { if (noClub) {
noClub->synchronize(); noClub->synchronize();
club = noClub->getName(); club = noClub->getName();
} }
else else
club=lang.tl("Klubblös"); club = lang.tl("Klubblös");
} }
int year = 0; int year = 0;
pRunner r=gEvent->addRunner(gdi.getText("Runners"), club, pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
classes[0]->getId(), activeSIC.CardNumber, year, true); classes[0]->getId(), activeSIC.CardNumber, year, true);
gdi.setData("RunnerId", r->getId()); gdi.setData("RunnerId", r->getId());
@ -680,7 +679,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gEvent->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterNone); gEvent->fillClasses(gdi, "Classes", oEvent::extraNone, oEvent::filterNone);
gdi.setInputFocus("Classes"); gdi.setInputFocus("Classes");
if (classes.size()>0) if (classes.size() > 0)
gdi.selectItemByData("Classes", classes[0]->getId()); gdi.selectItemByData("Classes", classes[0]->getId());
gdi.dropLine(); gdi.dropLine();
@ -695,21 +694,21 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.addButton("NewClass", "Skapa ny klass", SportIdentCB); gdi.addButton("NewClass", "Skapa ny klass", SportIdentCB);
gdi.popX(); gdi.popX();
if (classes.size()>0) if (classes.size() > 0)
gdi.addString("FindMatch", 0, "Press Enter to continue").setColor(colorGreen); gdi.addString("FindMatch", 0, "Press Enter to continue").setColor(colorGreen);
gdi.dropLine(); gdi.dropLine();
gdi.refresh(); gdi.refresh();
return 0; return 0;
} }
else if (bi.id=="OK2") else if (bi.id == "OK2")
{ {
//New runner in existing class... //New runner in existing class...
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("Classes", lbi); gdi.getSelectedItem("Classes", lbi);
if (lbi.data==0 || lbi.data==-1) { if (lbi.data == 0 || lbi.data == -1) {
gdi.alert("Du måste välja en klass"); gdi.alert("Du måste välja en klass");
return 0; return 0;
} }
@ -723,7 +722,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
club = lang.tl("Klubblös"); club = lang.tl("Klubblös");
int year = 0; int year = 0;
pRunner r=gEvent->addRunner(gdi.getText("Runners"), club, pRunner r = gEvent->addRunner(gdi.getText("Runners"), club,
lbi.data, activeSIC.CardNumber, year, true); lbi.data, activeSIC.CardNumber, year, true);
r->setStartTimeS(gdi.getText("StartTime")); r->setStartTimeS(gdi.getText("StartTime"));
@ -734,14 +733,14 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
activeSIC.clear(&activeSIC); activeSIC.clear(&activeSIC);
processCard(gdi, r, copy); processCard(gdi, r, copy);
} }
else if (bi.id=="NewClass") { else if (bi.id == "NewClass") {
gdi.restore("restOK2", false); gdi.restore("restOK2", false);
gdi.popX(); gdi.popX();
gdi.dropLine(2); gdi.dropLine(2);
gdi.fillRight(); gdi.fillRight();
gdi.pushX(); gdi.pushX();
gdi.addInput("ClassName", gEvent->getAutoClassName(), 10,0, L"Klassnamn:"); gdi.addInput("ClassName", gEvent->getAutoClassName(), 10, 0, L"Klassnamn:");
gdi.dropLine(); gdi.dropLine();
gdi.addButton("Cancel", "Avbryt", SportIdentCB).setCancel(); gdi.addButton("Cancel", "Avbryt", SportIdentCB).setCancel();
@ -751,7 +750,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.refresh(); gdi.refresh();
gdi.popX(); gdi.popX();
} }
else if (bi.id=="OK3") { else if (bi.id == "OK3") {
pCourse pc = 0; pCourse pc = 0;
pClass pclass = 0; pClass pclass = 0;
@ -766,18 +765,19 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pc->setName(gdi.getText("ClassName")); pc->setName(gdi.getText("ClassName"));
} }
if (pc == 0) { if (pc == 0 && !gEvent->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
pc=gEvent->addCourse(gdi.getText("ClassName")); pc = gEvent->addCourse(gdi.getText("ClassName"));
for(unsigned i=0;i<activeSIC.nPunch; i++) for (unsigned i = 0; i < activeSIC.nPunch; i++)
pc->addControl(activeSIC.Punch[i].Code); pc->addControl(activeSIC.Punch[i].Code);
} }
if (pclass == 0) { if (pclass == 0) {
pclass=gEvent->addClass(gdi.getText("ClassName"), pc->getId()); pclass = gEvent->addClass(gdi.getText("ClassName"), pc ? pc->getId(): 0);
} }
else else if (pc)
pclass->setCourse(pc); pclass->setCourse(pc);
int year = 0; int year = 0;
pRunner r=gEvent->addRunner(gdi.getText("Runners"), gdi.getText("Club", true), pRunner r = gEvent->addRunner(gdi.getText("Runners"), gdi.getText("Club", true),
pclass->getId(), activeSIC.CardNumber, year, true); pclass->getId(), activeSIC.CardNumber, year, true);
r->setStartTimeS(gdi.getText("StartTime")); r->setStartTimeS(gdi.getText("StartTime"));
@ -787,13 +787,13 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
activeSIC.clear(&activeSIC); activeSIC.clear(&activeSIC);
processCard(gdi, r, copy_sic); processCard(gdi, r, copy_sic);
} }
else if (bi.id=="OK4") { else if (bi.id == "OK4") {
//Existing runner in existing class... //Existing runner in existing class...
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("Classes", lbi); gdi.getSelectedItem("Classes", lbi);
if (lbi.data==0 || lbi.data==-1) if (lbi.data == 0 || lbi.data == -1)
{ {
gdi.alert("Du måste välja en klass"); gdi.alert("Du måste välja en klass");
return 0; return 0;
@ -802,7 +802,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
DWORD rid; DWORD rid;
pRunner r; pRunner r;
if (gdi.getData("RunnerId", rid) && rid>0) if (gdi.getData("RunnerId", rid) && rid > 0)
r = gEvent->getRunner(rid, 0); r = gEvent->getRunner(rid, 0);
else r = gEvent->addRunner(lang.tl(L"Oparad bricka"), lang.tl("Okänd"), 0, 0, 0, false); else r = gEvent->addRunner(lang.tl(L"Oparad bricka"), lang.tl("Okänd"), 0, 0, 0, false);
@ -813,12 +813,11 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
activeSIC.clear(&activeSIC); activeSIC.clear(&activeSIC);
processCard(gdi, r, copy); processCard(gdi, r, copy);
} }
else if (bi.id=="EntryOK") { else if (bi.id == "EntryOK") {
storedInfo.clear(); storedInfo.clear();
oe->synchronizeList(oLRunnerId, true, false); oe->synchronizeList({ oListId::oLRunnerId, oListId::oLCardId });
oe->synchronizeList(oLCardId, false, true);
wstring name=gdi.getText("Name"); wstring name = gdi.getText("Name");
if (name.empty()) { if (name.empty()) {
gdi.alert("Alla deltagare måste ha ett namn."); gdi.alert("Alla deltagare måste ha ett namn.");
return 0; return 0;
@ -827,29 +826,46 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r = oe->getRunner(rid, 0); pRunner r = oe->getRunner(rid, 0);
int cardNo = gdi.getTextNo("CardNo"); int cardNo = gdi.getTextNo("CardNo");
pRunner cardRunner = oe->getRunnerByCardNo(cardNo, 0, true); pRunner cardRunner = oe->getRunnerByCardNo(cardNo, 0, oEvent::CardLookupProperty::ForReadout);
if (cardNo>0 && cardRunner!=0 && cardRunner!=r) { if (cardNo > 0 && cardRunner != 0 && cardRunner != r) {
gdi.alert(L"Bricknummret är upptaget (X).#" + cardRunner->getName() + L", " + cardRunner->getClass(true)); gdi.alert(L"Bricknummret är upptaget (X).#" + cardRunner->getName() + L", " + cardRunner->getClass(true));
return 0; return 0;
} }
ListBoxInfo lbi; ListBoxInfo lbi;
gdi.getSelectedItem("Class", lbi); gdi.getSelectedItem("Class", lbi);
pClass clz = oe->getClass(lbi.data);
if (signed(lbi.data)<=0) { if (!clz) {
if (oe->getNumClasses() > 0) { if (oe->getNumClasses() > 0) {
gdi.alert(L"Ingen klass vald"); gdi.alert(L"Ingen klass vald");
return 0; return 0;
} }
pClass pc = oe->getClassCreate(0, lang.tl(L"Öppen klass")); set<wstring> dmy;
lbi.data = pc->getId(); clz = oe->getClassCreate(0, lang.tl(L"Öppen klass"), dmy);
pc->setAllowQuickEntry(true); lbi.data = clz->getId();
pc->synchronize(); clz->setAllowQuickEntry(true);
clz->synchronize();
} }
bool updated = false; bool updated = false;
int year = 0; int year = 0;
bool warnClassFull = false;
if (!r || r->getClassRef(false) != clz) {
int numRemMaps = clz->getNumRemainingMaps(true);
if (numRemMaps != numeric_limits<int>::min()) {
if (clz->getNumRemainingMaps(true) > 0)
warnedClassOutOfMaps.erase(clz->getId());
else {
warnClassFull = true;
if (!warnedClassOutOfMaps.count(clz->getId())) {
warnedClassOutOfMaps.insert(clz->getId());
if (!gdi.ask(L"ask:outofmaps"))
return 0;
}
}
}
}
if (r==0) { if (r == 0) {
r = oe->addRunner(name, gdi.getText("Club", true), lbi.data, cardNo, year, true); r = oe->addRunner(name, gdi.getText("Club", true), lbi.data, cardNo, year, true);
r->setCardNo(0, false, false); // Clear to match below r->setCardNo(0, false, false); // Clear to match below
} }
@ -871,16 +887,17 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
updated = true; updated = true;
} }
lastClubId=r->getClubId(); lastClubId = r->getClubId();
lastClassId=r->getClassId(true); lastClassId = r->getClassId(true);
lastFee = gdi.getText("Fee", true); lastFee = gdi.getText("Fee", true);
int lastFeeNum = oe->interpretCurrency(lastFee); int lastFeeNum = oe->interpretCurrency(lastFee);
r->setCardNo(cardNo, true);//XXX r->setCardNo(cardNo, true);//XXX
oDataInterface di=r->getDI(); oDataInterface di = r->getDI();
int cardFee = gdi.isChecked("RentCard") ? oe->getBaseCardFee() : 0;
int cardFee = gdi.isChecked("RentCard") ? oe->getDI().getInt("CardFee") : 0;
di.setInt("CardFee", cardFee); di.setInt("CardFee", cardFee);
di.setInt("Fee", lastFeeNum); di.setInt("Fee", lastFeeNum);
r->setFlag(oRunner::FlagFeeSpecified, true); r->setFlag(oRunner::FlagFeeSpecified, true);
@ -889,12 +906,15 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
writePayMode(gdi, totFee, *r); writePayMode(gdi, totFee, *r);
di.setString("Phone", gdi.getText("Phone")); di.setString("Phone", gdi.getText("Phone"));
r->setFlag(oRunner::FlagTransferSpecified, gdi.hasField("AllStages")); r->setFlag(oRunner::FlagTransferSpecified, gdi.hasField("AllStages"));
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages")); r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
r->setStartTimeS(gdi.getText("StartTime")); r->setStartTimeS(gdi.getText("StartTime"));
wstring bibIn = gdi.getText("Bib");
wstring bib; wstring bib;
if (bibIn.empty()) {
switch (r->autoAssignBib()) { switch (r->autoAssignBib()) {
case oRunner::BibAssignResult::Assigned: case oRunner::BibAssignResult::Assigned:
bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib(); bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib();
@ -903,6 +923,11 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
bib = L", " + lang.tl(L"Ingen nummerlapp"); bib = L", " + lang.tl(L"Ingen nummerlapp");
break; break;
} }
}
else {
r->setBib(bibIn, 0, false, false);
bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib();
}
r->synchronize(); r->synchronize();
gdi.restore("EntryLine"); gdi.restore("EntryLine");
@ -918,14 +943,14 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
wstring info(bf); wstring info(bf);
if (r->getDI().getInt("CardFee") != 0) if (r->getDI().getInt("CardFee") != 0)
info+=lang.tl(L", Hyrbricka"); info += lang.tl(L", Hyrbricka");
vector< pair<wstring, size_t> > modes; vector< pair<wstring, size_t> > modes;
oe->getPayModes(modes); oe->getPayModes(modes);
wstring pm; wstring pm;
if (modes.size() > 1 && size_t(r->getPaymentMode()) < modes.size()) if (modes.size() > 1 && size_t(r->getPaymentMode()) < modes.size())
pm = L" (" + modes[r->getPaymentMode()].first + L")"; pm = L" (" + modes[r->getPaymentMode()].first + L")";
if (r->getDI().getInt("Paid")>0) if (r->getDI().getInt("Paid") > 0)
info += lang.tl(L", Betalat") + pm; info += lang.tl(L", Betalat") + pm;
bool warnPayment = r->getDI().getInt("Paid") < totFee && ( bool warnPayment = r->getDI().getInt("Paid") < totFee && (
@ -933,8 +958,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
r->getClubId() == oe->getVacantClubIfExist(true) || r->getClubId() == oe->getVacantClubIfExist(true) ||
r->getClubId() == oe->getVacantClubIfExist(false)); r->getClubId() == oe->getVacantClubIfExist(false));
if (bib.length()>0) if (bib.length() > 0)
info+=bib; info += bib;
if (updated) if (updated)
info += lang.tl(L" [Uppdaterad anmälan]"); info += lang.tl(L" [Uppdaterad anmälan]");
@ -949,18 +974,21 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (warnPayment) { if (warnPayment) {
gdi.addString("", fontMediumPlus, "Varning: avgiften kan ej faktureras").setColor(colorRed); gdi.addString("", fontMediumPlus, "Varning: avgiften kan ej faktureras").setColor(colorRed);
} }
if (warnClassFull) {
gdi.addString("", fontMediumPlus, "Varning: Kartorna är slut").setColor(colorRed);
}
generateStartInfo(gdi, *r); generateStartInfo(gdi, *r);
gdi.setRestorePoint("EntryLine"); gdi.setRestorePoint("EntryLine");
generateEntryLine(gdi, 0); generateEntryLine(gdi, 0);
} }
else if (bi.id=="EntryCancel") { else if (bi.id == "EntryCancel") {
gdi.restore("EntryLine"); gdi.restore("EntryLine");
storedInfo.clear(); storedInfo.clear();
generateEntryLine(gdi, 0); generateEntryLine(gdi, 0);
} }
else if (bi.id=="RentCard" || bi.id=="Paid" || bi.id == "AllStages") { else if (bi.id == "RentCard" || bi.id == "Paid" || bi.id == "AllStages") {
updateEntryInfo(gdi); updateEntryInfo(gdi);
} }
else if (bi.id == "ManualOK") { else if (bi.id == "ManualOK") {
@ -978,7 +1006,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
bool dnf = gdi.isChecked("StatusDNF"); bool dnf = gdi.isChecked("StatusDNF");
pRunner r = oe->getRunner(runnerMatchedId, 0); pRunner r = oe->getRunner(runnerMatchedId, 0);
if (r==0) if (r == 0)
throw meosException("Löparen hittades inte"); throw meosException("Löparen hittades inte");
if (r->getStatus() != StatusUnknown) { if (r->getStatus() != StatusUnknown) {
@ -1270,7 +1298,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
if (nr > 0) { if (nr > 0) {
r = oe->getRunnerByBibOrStartNo(text, false); r = oe->getRunnerByBibOrStartNo(text, false);
if (r == 0) if (r == 0)
r = oe->getRunnerByCardNo(nr, 0, true, true); r = oe->getRunnerByCardNo(nr, 0, oEvent::CardLookupProperty::ForReadout);
} }
if (nr == 0 && text.size() > 2) { if (nr == 0 && text.size() > 2) {
@ -1324,7 +1352,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
gdi.setInputStatus("TieOK", runnerMatchedId != -1); gdi.setInputStatus("TieOK", runnerMatchedId != -1);
} }
else if (ii.id == "SI") { else if (ii.id == "SI") {
pRunner r = oe->getRunnerByCardNo(_wtoi(ii.text.c_str()), 0, true, false); pRunner r = oe->getRunnerByCardNo(_wtoi(ii.text.c_str()), 0, oEvent::CardLookupProperty::ForReadout);
if (r && r->getStartTime() > 0) { if (r && r->getStartTime() > 0) {
gdi.setText("Start", r->getStartTimeS()); gdi.setText("Start", r->getStartTimeS());
gdi.check("HasStart", false); gdi.check("HasStart", false);
@ -1371,10 +1399,11 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
pRunner r=oe->getRunner(ii.getExtraInt(), 0); pRunner r=oe->getRunner(ii.getExtraInt(), 0);
r->synchronize(); r->synchronize();
if (r && r->getCardNo()!=si) { if (r && r->getCardNo() != si) {
if (si==0 || !oe->checkCardUsed(gdi,*r, si)) { if (si == 0 || !oe->checkCardUsed(gdi, *r, si)) {
r->setCardNo(si, false); r->setCardNo(si, false);
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
r->getDI().setInt("CardFee", oe->getBaseCardFee());
r->synchronize(); r->synchronize();
} }
@ -1470,7 +1499,7 @@ void TabSI::showReadPunches(gdioutput &gdi, vector<PunchInfo> &punches, set<stri
sprintf_s(bf, "%d.", k+1); sprintf_s(bf, "%d.", k+1);
gdi.addStringUT(yp, xp, 0, bf); gdi.addStringUT(yp, xp, 0, bf);
pRunner r = oe->getRunnerByCardNo(punches[k].card, punches[k].time); pRunner r = oe->getRunnerByCardNo(punches[k].card, punches[k].time, oEvent::CardLookupProperty::Any);
sprintf_s(bf, "%d", punches[k].card); sprintf_s(bf, "%d", punches[k].card);
gdi.addStringUT(yp, xp+40, 0, bf, 240); gdi.addStringUT(yp, xp+40, 0, bf, 240);
@ -1499,7 +1528,7 @@ void TabSI::showReadCards(gdioutput &gdi, vector<SICard> &cards)
sprintf_s(bf, "%d.", k+1); sprintf_s(bf, "%d.", k+1);
gdi.addStringUT(yp, xp, 0, bf); gdi.addStringUT(yp, xp, 0, bf);
pRunner r = oe->getRunnerByCardNo(cards[k].CardNumber, 0); pRunner r = oe->getRunnerByCardNo(cards[k].CardNumber, 0, oEvent::CardLookupProperty::Any);
sprintf_s(bf, "%d", cards[k].CardNumber); sprintf_s(bf, "%d", cards[k].CardNumber);
gdi.addStringUT(yp, xp+40, 0, bf, 240); gdi.addStringUT(yp, xp+40, 0, bf, 240);
@ -1836,8 +1865,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
} }
return; return;
} }
gEvent->synchronizeList(oLCardId, true, false); gEvent->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
gEvent->synchronizeList(oLRunnerId, false, true);
if (sic.punchOnly) { if (sic.punchOnly) {
processPunchOnly(gdi, sic); processPunchOnly(gdi, sic);
@ -1845,7 +1873,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
} }
pRunner r; pRunner r;
if (sic.runnerId == 0) if (sic.runnerId == 0)
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, false); r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, oEvent::CardLookupProperty::ForReadout);
else { else {
r = gEvent->getRunner(sic.runnerId, 0); r = gEvent->getRunner(sic.runnerId, 0);
sic.CardNumber = r->getCardNo(); sic.CardNumber = r->getCardNo();
@ -1923,7 +1951,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
if (!gdi.ask(bf)) { if (!gdi.ask(bf)) {
if (printSplits) { if (printSplits) {
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0); pRunner runner = getRunnerForCardSplitPrint(sic);
if (runner) if (runner)
generateSplits(runner, gdi); generateSplits(runner, gdi);
} }
@ -1936,7 +1964,8 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
} }
else { else {
if (printSplits) { if (printSplits) {
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0); pRunner runner = getRunnerForCardSplitPrint(sic);
if (runner) if (runner)
generateSplits(runner, gdi); generateSplits(runner, gdi);
} }
@ -1955,7 +1984,10 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
pRunner db_r = 0; pRunner db_r = 0;
if (sic.runnerId == 0) { if (sic.runnerId == 0) {
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, !readBefore); if (!readBefore)
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, oEvent::CardLookupProperty::ForReadout);
else
r = getRunnerForCardSplitPrint(sic);
if (!r && showDatabase()) { if (!r && showDatabase()) {
//Look up in database. //Look up in database.
@ -1966,15 +1998,18 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
} }
// If there is no class, auto create // If there is no class, auto create
if (interactiveReadout && oe->getNumClasses()==0) { if (interactiveReadout && oe->getNumClasses() == 0) {
gdi.fillDown(); gdi.fillDown();
gdi.dropLine(); gdi.dropLine();
gdi.addString("", 1, "Skapar saknad klass").setColor(colorGreen); gdi.addString("", 1, "Skapar saknad klass").setColor(colorGreen);
gdi.dropLine(); gdi.dropLine();
pCourse pc=gEvent->addCourse(lang.tl("Okänd klass")); pCourse pc = nullptr;
for(unsigned i=0;i<sic.nPunch; i++) if (!oe->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
pc = gEvent->addCourse(lang.tl("Okänd klass"));
for (unsigned i = 0; i < sic.nPunch; i++)
pc->addControl(sic.Punch[i].Code); pc->addControl(sic.Punch[i].Code);
gEvent->addClass(lang.tl(L"Okänd klass"), pc->getId())->setType(L"tmp"); }
gEvent->addClass(lang.tl(L"Okänd klass"), pc ? pc->getId() : 0)->setType(L"tmp");
} }
// Assign a class if not already done // Assign a class if not already done
@ -1999,6 +2034,28 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
} }
} }
pRunner TabSI::getRunnerForCardSplitPrint(const SICard &sic) const {
pRunner runner = 0;
vector<pRunner> out;
oe->getRunnersByCardNo(sic.CardNumber, false, oEvent::CardLookupProperty::SkipNoStart, out);
for (pRunner r : out) {
if (!r->getCard())
continue;
if (runner == 0)
runner = r;
else {
if (runner->getFinishTime() < r->getFinishTime())
runner = r; // Take the last finisher
// int nPunchBest = runner->getCard()->getNumControlPunches(oPunch::PunchStart, oPunch::PunchFinish);
// int nPunchCurrent = r->getCard()->getNumControlPunches(oPunch::PunchStart, oPunch::PunchFinish);
// if (abs(int(nPunchCurrent - activeSIC.nPunch)) < abs(int(nPunchBest - activeSIC.nPunch)))
// runner = r;
}
}
return runner;
}
void TabSI::startInteractive(gdioutput &gdi, const SICard &sic, pRunner r, pRunner db_r) void TabSI::startInteractive(gdioutput &gdi, const SICard &sic, pRunner r, pRunner db_r)
{ {
if (!r) { if (!r) {
@ -2093,7 +2150,7 @@ void TabSI::processInsertCard(const SICard &sic)
if (oe->isCardRead(sic)) if (oe->isCardRead(sic))
return; return;
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0, true); pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0, oEvent::CardLookupProperty::ForReadout);
pCard card = oe->allocateCard(runner); pCard card = oe->allocateCard(runner);
card->setReadId(sic); card->setReadId(sic);
card->setCardNo(sic.CardNumber); card->setCardNo(sic.CardNumber);
@ -2229,7 +2286,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
} }
pClass pclass = runner->getClassRef(true); pClass pclass = runner->getClassRef(true);
if (!runner->getCourse(false) && !csic.isManualInput()) { if (!runner->getCourse(false) && !csic.isManualInput() && !oe->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
if (pclass && !pclass->hasMultiCourse() && !pclass->hasDirectResult()) { if (pclass && !pclass->hasMultiCourse() && !pclass->hasDirectResult()) {
pCourse pcourse=gEvent->addCourse(pclass->getName()); pCourse pcourse=gEvent->addCourse(pclass->getName());
@ -2353,7 +2410,10 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
rc.bottom+=gdi.getLineHeight(); rc.bottom+=gdi.getLineHeight();
if (runner->getStatus()==StatusOK) { if (runner->getStatus()==StatusOK) {
gEvent->calculateResults(oEvent::RTClassResult); set<int> clsSet;
if (runner->getClassId(false))
clsSet.insert(runner->getClassId(true));
gEvent->calculateResults(clsSet, oEvent::ResultType::ClassResult);
if (runner->getTeam()) if (runner->getTeam())
gEvent->calculateTeamResults(runner->getLegNumber(), false); gEvent->calculateTeamResults(runner->getLegNumber(), false);
bool qfClass = runner->getClassId(false) != runner->getClassId(true); bool qfClass = runner->getClassId(false) != runner->getClassId(true);
@ -2391,7 +2451,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
} }
} }
else { else {
wstring msg=lang.tl(L"Status: ") + lang.tl(runner->getStatusS()); wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true);
if (!MP.empty()) { if (!MP.empty()) {
msg=msg + L", ("; msg=msg + L", (";
@ -2507,7 +2567,7 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
name=wstring(sic.lastName) + L", " + wstring(sic.firstName); name=wstring(sic.lastName) + L", " + wstring(sic.firstName);
gdi.setText("Name", name); gdi.setText("Name", name);
if (gdi.hasField("Club")) if (gdi.hasField("Club") && !club.empty())
gdi.setText("Club", club); gdi.setText("Club", club);
if (club.empty() && gdi.hasField("Club")) if (club.empty() && gdi.hasField("Club"))
@ -2567,11 +2627,11 @@ void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
currentAssignIndex = storedAssigneIndex; currentAssignIndex = storedAssigneIndex;
return; return;
} }
if (r->getCardNo()==0 || if (r->getCardNo() == 0 ||
gdi.ask(L"Skriv över existerande bricknummer?")) { gdi.ask(L"Skriv över existerande bricknummer?")) {
r->setCardNo(sic.CardNumber, false); r->setCardNo(sic.CardNumber, false);
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee")); r->getDI().setInt("CardFee", oe->getBaseCardFee());
r->synchronize(); r->synchronize();
gdi.setText(ii->id, sicode); gdi.setText(ii->id, sicode);
} }
@ -2582,10 +2642,8 @@ void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
checkMoreCardsInQueue(gdi); checkMoreCardsInQueue(gdi);
} }
void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) {
{ oe->synchronizeList({ oListId::oLRunnerId, oListId::oLCardId });
oe->synchronizeList(oLRunnerId, true, false);
oe->synchronizeList(oLCardId, false, true);
gdi.restore("EntryLine", false); gdi.restore("EntryLine", false);
gdi.setRestorePoint("EntryLine"); gdi.setRestorePoint("EntryLine");
@ -2651,16 +2709,22 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
gdi.dropLine(-0.2); gdi.dropLine(-0.2);
gdi.addInput("StartTime", storedInfo.storedStartTime, 5, 0, L""); gdi.addInput("StartTime", storedInfo.storedStartTime, 5, 0, L"");
gdi.setCX(gdi.getCX()+gdi.scaleLength(50)); gdi.setCX(gdi.getCX() + gdi.scaleLength(20));
gdi.dropLine(0.2);
gdi.addString("", 0, "Nummerlapp:");
gdi.dropLine(-0.2);
gdi.addInput("Bib", L"", 5, 0, L"");
gdi.setCX(gdi.getCX()+gdi.scaleLength(20));
gdi.dropLine(0.2); gdi.dropLine(0.2);
gdi.setCX(gdi.getCX()+gdi.scaleLength(5));
gdi.addString("", 0, "Telefon:"); gdi.addString("", 0, "Telefon:");
gdi.dropLine(-0.2); gdi.dropLine(-0.2);
gdi.addInput("Phone", storedInfo.storedPhone, 12, 0, L""); gdi.addInput("Phone", storedInfo.storedPhone, 12, 0, L"");
gdi.dropLine(0.2); gdi.dropLine(0.2);
gdi.setCX(gdi.getCX()+gdi.scaleLength(50)); gdi.setCX(gdi.getCX()+gdi.scaleLength(20));
gdi.addCheckbox("RentCard", "Hyrbricka", SportIdentCB, storedInfo.rentState); gdi.addCheckbox("RentCard", "Hyrbricka", SportIdentCB, storedInfo.rentState);
if (oe->hasNextStage()) if (oe->hasNextStage())
@ -2681,6 +2745,7 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
gdi.setText("Fee", oe->formatCurrency(dci.getInt("Fee"))); gdi.setText("Fee", oe->formatCurrency(dci.getInt("Fee")));
gdi.setText("Phone", dci.getString("Phone")); gdi.setText("Phone", dci.getString("Phone"));
gdi.setText("Bib", r->getBib());
gdi.check("RentCard", dci.getInt("CardFee") != 0); gdi.check("RentCard", dci.getInt("CardFee") != 0);
if (gdi.hasField("Paid")) if (gdi.hasField("Paid"))
@ -2876,7 +2941,8 @@ void TabSI::tieCard(gdioutput &gdi) {
bool rent = gdi.isChecked("RentCardTie"); bool rent = gdi.isChecked("RentCardTie");
r->setCardNo(card, true, false); r->setCardNo(card, true, false);
r->getDI().setInt("CardFee", rent ? oe->getDI().getInt("CardFee") : 0);
r->getDI().setInt("CardFee", rent ? oe->getBaseCardFee() : 0);
r->synchronize(true); r->synchronize(true);
gdi.restore("ManualTie"); gdi.restore("ManualTie");
@ -3373,9 +3439,17 @@ void TabSI::StoredStartInfo::clear() {
} }
void TabSI::clearCompetitionData() { void TabSI::clearCompetitionData() {
printSplits = false;
interactiveReadout = oe->getPropertyInt("Interactive", 1) != 0;
useDatabase = oe->getPropertyInt("Database", 1) != 0;
printSplits = false;
printStartInfo = false;
manualInput = oe->getPropertyInt("ManualInput", 0) == 1;
savedCardUniqueId = 1; savedCardUniqueId = 1;
checkedCardFlags.clear(); checkedCardFlags.clear();
currentAssignIndex = 0; currentAssignIndex = 0;
warnedClassOutOfMaps.clear();
} }
SICard &TabSI::getCard(int id) const { SICard &TabSI::getCard(int id) const {
@ -3529,7 +3603,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
wstring cp = r[k]->getCompleteIdentification(); wstring cp = r[k]->getCompleteIdentification();
if (r[k]->getStatus() != StatusUnknown) if (r[k]->getStatus() != StatusUnknown)
cp += L" " + r[k]->getStatusS(); cp += L" " + r[k]->getStatusS(true);
else else
cp += makeDash(L" -"); cp += makeDash(L" -");

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -71,6 +71,8 @@ private:
vector<SICard> cards; vector<SICard> cards;
vector<wstring> filterDate; vector<wstring> filterDate;
set<int> warnedClassOutOfMaps;
int runnerMatchedId; int runnerMatchedId;
bool printErrorShown; bool printErrorShown;
void printProtected(gdioutput &gdi, gdioutput &gdiprint); void printProtected(gdioutput &gdi, gdioutput &gdiprint);
@ -132,7 +134,6 @@ private:
// Insert card without converting times and with/without runner // Insert card without converting times and with/without runner
void processInsertCard(const SICard &csic); void processInsertCard(const SICard &csic);
void generateSplits(const pRunner r, gdioutput &gdi); void generateSplits(const pRunner r, gdioutput &gdi);
int logcounter; int logcounter;
csvparser *logger; csvparser *logger;
@ -141,6 +142,8 @@ private:
void insertSICardAux(gdioutput &gdi, SICard &sic); void insertSICardAux(gdioutput &gdi, SICard &sic);
pRunner getRunnerForCardSplitPrint(const SICard &sic) const;
// Ask if card is to be overwritten // Ask if card is to be overwritten
bool askOverwriteCard(gdioutput &gdi, pRunner r) const; bool askOverwriteCard(gdioutput &gdi, pRunner r) const;
@ -246,7 +249,7 @@ public:
TabType getType() const {return TSITab;} TabType getType() const {return TSITab;}
void insertSICard(gdioutput &gdi, SICard &sic); void insertSICard(gdioutput &gdi, SICard &sic);
void clearQueue() { CardQueue.clear(); }
void refillComPorts(gdioutput &gdi); void refillComPorts(gdioutput &gdi);
bool loadPage(gdioutput &gdi); bool loadPage(gdioutput &gdi);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -39,6 +39,7 @@
#include "TabSpeaker.h" #include "TabSpeaker.h"
#include "TabList.h" #include "TabList.h"
#include "TabRunner.h"
#include "speakermonitor.h" #include "speakermonitor.h"
#include "meosexception.h" #include "meosexception.h"
@ -100,6 +101,34 @@ int TabSpeaker::handleEvent(gdioutput &gdi, const EventInfo &ei)
return 0; return 0;
} }
namespace {
class ReportMode : public GuiHandler {
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) final {
TabBase *tb = gdi.getTabs().get(TabType::TSpeakerTab);
TabSpeaker *list = dynamic_cast<TabSpeaker *>(tb);
if (list) {
auto oe = list->getEvent();
if (type == GUI_INPUTCHANGE) {
InputInfo &ii = dynamic_cast<InputInfo &>(info);
int nr = _wtoi(ii.text.c_str());
if (nr > 0) {
pRunner r = oe->getRunnerByBibOrStartNo(ii.text, false);
if (r) {
list->setSelectedRunner(*r);
gdi.sendCtrlMessage("Report");
}
}
}
}
}
public:
virtual ~ReportMode() {}
};
ReportMode reportHandler;
}
int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu) int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
{ {
if (bu.id=="Settings") { if (bu.id=="Settings") {
@ -188,6 +217,37 @@ int TabSpeaker::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.addTable(oe->getPunchesTB(), gdi.getCX(), gdi.getCY()); gdi.addTable(oe->getPunchesTB(), gdi.getCX(), gdi.getCY());
gdi.refresh(); gdi.refresh();
} }
else if (bu.id == "Report") {
classId = -2;
if (gdi.hasData("ReportMode")) {
gdi.restore("ReportMode", false);
}
else {
gdi.restore("speaker", false);
gdi.pushX();
gdi.fillRight();
gdi.addSelection("ReportRunner", 300, 300, tabSpeakerCB);
gdi.dropLine(0.2);
gdi.addString("", 0, "Nummerlapp:");
gdi.dropLine(-0.2);
gdi.addInput("FindRunner", L"", 6, 0, L"", L"Nummerlapp").setHandler(&reportHandler);
gdi.setRestorePoint("ReportMode");
}
gdi.setData("ReportMode", 1);
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll | oEvent::RunnerCompactMode);
gdi.selectItemByData("ReportRunner", runnerId);
gdi.dropLine(3);
gdi.popX();
gdi.registerEvent("DataUpdate", tabSpeakerCB);
vector<pair<int, bool>> runnersToReport;
if (runnerId > 0) {
runnersToReport.emplace_back(runnerId, false);
}
TabRunner::generateRunnerReport(*oe, gdi, runnersToReport);
gdi.refresh();
}
else if (bu.id == "Priority") { else if (bu.id == "Priority") {
gdi.clearPage(false); gdi.clearPage(false);
gdi.addString("", boldLarge, "Bevakningsprioritering"); gdi.addString("", boldLarge, "Bevakningsprioritering");
@ -424,7 +484,7 @@ void TabSpeaker::drawTimeLine(gdioutput &gdi) {
} }
void TabSpeaker::updateTimeLine(gdioutput &gdi) { void TabSpeaker::updateTimeLine(gdioutput &gdi) {
int storedY = gdi.GetOffsetY(); int storedY = gdi.getOffsetY();
int storedHeight = gdi.getHeight(); int storedHeight = gdi.getHeight();
bool refresh = gdi.hasData("TimeLineLoaded"); bool refresh = gdi.hasData("TimeLineLoaded");
@ -442,7 +502,7 @@ void TabSpeaker::updateTimeLine(gdioutput &gdi) {
gdi.pushX(); gdi.pushY(); gdi.pushX(); gdi.pushY();
gdi.updatePos(0,0,0, storedHeight); gdi.updatePos(0,0,0, storedHeight);
gdi.popX(); gdi.popY(); gdi.popX(); gdi.popY();
gdi.SetOffsetY(storedY); gdi.setOffsetY(storedY);
SpeakerMonitor &sm = *getSpeakerMonitor(); SpeakerMonitor &sm = *getSpeakerMonitor();
int limit = 1000; int limit = 1000;
@ -864,9 +924,9 @@ int TabSpeaker::deducePreviousControl(int classId, int leg, int control) {
int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu) int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
{ {
if (bu.id=="Leg") { if (bu.id == "Leg") {
if (classId>0) { if (classId > 0) {
selectedControl[classId].setLeg(bu.data>=1000, bu.data%1000); selectedControl[classId].setLeg(bu.data >= 1000, bu.data % 1000);
generateControlList(gdi, classId); generateControlList(gdi, classId);
gdi.setRestorePoint("speaker"); gdi.setRestorePoint("speaker");
gdi.setRestorePoint("SpeakerList"); gdi.setRestorePoint("SpeakerList");
@ -899,11 +959,14 @@ int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
int classId = int(bu.data); int classId = int(bu.data);
loadPriorityClass(gdi, classId); loadPriorityClass(gdi, classId);
} }
else if (bu.id == "ReportRunner") {
runnerId = bu.data;
gdi.sendCtrlMessage("Report");
}
return 0; return 0;
} }
bool TabSpeaker::loadPage(gdioutput &gdi) bool TabSpeaker::loadPage(gdioutput &gdi) {
{
oe->checkDB(); oe->checkDB();
gdi.clearPage(false); gdi.clearPage(false);
@ -925,12 +988,19 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
int cx=basex; int cx=basex;
int cy=basey; int cy=basey;
int cb=1; int cb=1;
for (set<int>::iterator it=classesToWatch.begin();it!=classesToWatch.end();++it) { vector<pClass> clsToWatch;
char classid[32]; for (int cid : classesToWatch) {
sprintf_s(classid, "cid%d", *it); pClass pc = oe->getClass(cid);
pClass pc=oe->getClass(*it);
if (pc) { if (pc) {
clsToWatch.push_back(pc);
}
}
sort(clsToWatch.begin(), clsToWatch.end(), [](const pClass &a, const pClass &b) {return *a < *b; });
for (auto pc : clsToWatch) {
char classid[32];
sprintf_s(classid, "cid%d", pc->getId());
gdi.addButton(cx, cy, bw, classid, L"#" + pc->getName(), tabSpeakerCB, L"", false, false); gdi.addButton(cx, cy, bw, classid, L"#" + pc->getName(), tabSpeakerCB, L"", false, false);
cx+=bw; cx+=bw;
cb++; cb++;
@ -941,8 +1011,8 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
cy+=gdi.getButtonHeight()+4; cy+=gdi.getButtonHeight()+4;
} }
} }
}
bool pm = false;
int db = 0; int db = 0;
if (classesToWatch.empty()) { if (classesToWatch.empty()) {
gdi.addString("", boldLarge, "Speakerstöd"); gdi.addString("", boldLarge, "Speakerstöd");
@ -956,11 +1026,23 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
cb = 1, cx = basex, db = 0; cb = 1, cx = basex, db = 0;
cy += gdi.getButtonHeight()+4; cy += gdi.getButtonHeight()+4;
} else db += bw; } else db += bw;
gdi.addButton(cx+db, cy, bw/5, "ZoomIn", "+", tabSpeakerCB, "Zooma in (Ctrl + '+')", false, false); pm = true;
db += bw/5+2;
gdi.addButton(cx+db, cy, bw/5, "ZoomOut", makeDash(L"-"), tabSpeakerCB, L"Zooma ut (Ctrl + '-')", false, false);
db += bw/5+2;
} }
gdi.addButton(cx + db, cy, bw - 2, "Report", "Rapportläge", tabSpeakerCB, "Visa detaljerad rapport för viss deltagare", false, false);
if (++cb>nbtn) {
cb = 1, cx = basex, db = 0;
cy += gdi.getButtonHeight() + 4;
}
else db += bw;
if (pm) {
gdi.addButton(cx + db, cy, bw / 5, "ZoomIn", "+", tabSpeakerCB, "Zooma in (Ctrl + '+')", false, false);
db += bw / 5 + 2;
gdi.addButton(cx + db, cy, bw / 5, "ZoomOut", makeDash(L"-"), tabSpeakerCB, L"Zooma ut (Ctrl + '-')", false, false);
db += bw / 5 + 2;
}
gdi.addButton(cx+db, cy, bw-2, "Settings", "Inställningar...", tabSpeakerCB, "Välj vilka klasser och kontroller som bevakas", false, false); gdi.addButton(cx+db, cy, bw-2, "Settings", "Inställningar...", tabSpeakerCB, "Välj vilka klasser och kontroller som bevakas", false, false);
if (++cb>nbtn) { if (++cb>nbtn) {
cb = 1, cx = basex, db = 0; cb = 1, cx = basex, db = 0;
@ -978,13 +1060,12 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
cy += gdi.getButtonHeight()+4; cy += gdi.getButtonHeight()+4;
} else db += bw; } else db += bw;
gdi.addButton(cx+db, cy, bw-2, "LiveResult", "Liveresultat", tabSpeakerCB, "Visa rullande tider mellan kontroller i helskärmsläge", false, false); gdi.addButton(cx+db, cy, bw-2, "LiveResult", "Direkt tidtagning", tabSpeakerCB, "Visa rullande tider mellan kontroller i helskärmsläge", false, false);
if (++cb>nbtn) { if (++cb>nbtn) {
cb = 1, cx = basex, db = 0; cb = 1, cx = basex, db = 0;
cy += gdi.getButtonHeight()+4; cy += gdi.getButtonHeight()+4;
} else db += bw; } else db += bw;
if (!ownWindow) { if (!ownWindow) {
gdi.addButton(cx+db, cy, bw-2, "Priority", "Prioritering", tabSpeakerCB, "Välj löpare att prioritera bevakning för", false, false); gdi.addButton(cx+db, cy, bw-2, "Priority", "Prioritering", tabSpeakerCB, "Välj löpare att prioritera bevakning för", false, false);
if (++cb>nbtn) { if (++cb>nbtn) {
@ -1028,6 +1109,11 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
if (gdi.hasField(btn)) if (gdi.hasField(btn))
gdi.sendCtrlMessage(btn); gdi.sendCtrlMessage(btn);
} }
else if (classId == -2) {
string btn = "Report";
if (gdi.hasField(btn))
gdi.sendCtrlMessage(btn);
}
else if (classId > 0) { else if (classId > 0) {
string btn = "cid" + itos(classId); string btn = "cid" + itos(classId);
if (gdi.hasField(btn)) if (gdi.hasField(btn))
@ -1054,6 +1140,7 @@ void TabSpeaker::clearCompetitionData()
delete speakerMonitor; delete speakerMonitor;
speakerMonitor = 0; speakerMonitor = 0;
runnerId = -1;
} }
void TabSpeaker::manualTimePage(gdioutput &gdi) const void TabSpeaker::manualTimePage(gdioutput &gdi) const
@ -1101,7 +1188,7 @@ void TabSpeaker::storeManualTime(gdioutput &gdi)
pRunner r=oe->getRunnerByBibOrStartNo(r_str, false); pRunner r=oe->getRunnerByBibOrStartNo(r_str, false);
int r_no = _wtoi(r_str.c_str()); int r_no = _wtoi(r_str.c_str());
if (!r) if (!r)
r=oe->getRunnerByCardNo(r_no, itime); r=oe->getRunnerByCardNo(r_no, itime, oEvent::CardLookupProperty::Any);
wstring Name; wstring Name;
int sino=r_no; int sino=r_no;
@ -1153,8 +1240,7 @@ void TabSpeaker::loadPriorityClass(gdioutput &gdi, int classId) {
} }
void TabSpeaker::savePriorityClass(gdioutput &gdi) { void TabSpeaker::savePriorityClass(gdioutput &gdi) {
oe->synchronizeList(oLRunnerId, true, false); oe->synchronizeList({ oListId::oLRunnerId,oListId::oLTeamId });
oe->synchronizeList(oLTeamId, false, true);
for (size_t k = 0; k<runnersToSet.size(); k++) { for (size_t k = 0; k<runnersToSet.size(); k++) {
pRunner r = oe->getRunner(runnersToSet[k], 0); pRunner r = oe->getRunner(runnersToSet[k], 0);
@ -1223,6 +1309,9 @@ void TabSpeaker::getSettings(gdioutput &gdi, multimap<string, wstring> &settings
if (classId == -1) { if (classId == -1) {
settings.insert(make_pair("currentClass", L"@Events")); settings.insert(make_pair("currentClass", L"@Events"));
} }
else if (classId == -2) {
settings.insert(make_pair("currentClass", L"@Report"));
}
for (auto ctrl : controlsToWatch) { for (auto ctrl : controlsToWatch) {
settings.insert(make_pair("control", itow(ctrl))); settings.insert(make_pair("control", itow(ctrl)));
@ -1249,6 +1338,9 @@ void TabSpeaker::importSettings(gdioutput &gdi, multimap<string, wstring> &setti
if (s.second == L"@Events") { if (s.second == L"@Events") {
classId = -1; classId = -1;
} }
else if (s.second == L"@Report") {
classId = -2;
}
else { else {
pClass cls = oe->getClass(s.second); pClass cls = oe->getClass(s.second);
classId = cls ? cls->getId() : 0; classId = cls ? cls->getId() : 0;

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -58,6 +58,9 @@ private:
set<int> controlsToWatch; set<int> controlsToWatch;
set<int> classesToWatch; set<int> classesToWatch;
// For runner report
int runnerId = -1;
int lastControlToWatch; int lastControlToWatch;
int lastClassToWatch; int lastClassToWatch;
@ -100,6 +103,8 @@ private:
static wstring getSpeakerSettingsFile(); static wstring getSpeakerSettingsFile();
public: public:
void setSelectedRunner(const oRunner &r) { runnerId = r.getId(); }
bool onClear(gdioutput &gdi); bool onClear(gdioutput &gdi);
void loadPriorityClass(gdioutput &gdi, int classId); void loadPriorityClass(gdioutput &gdi, int classId);
void savePriorityClass(gdioutput &gdi); void savePriorityClass(gdioutput &gdi);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -188,7 +188,7 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.enableInput("Undo"); gdi.enableInput("Undo");
gdi.enableInput("Remove"); gdi.enableInput("Remove");
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone); oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterOnlyMulti);
gdi.selectItemByData("RClass", t->getClassId(false)); gdi.selectItemByData("RClass", t->getClassId(false));
gdi.selectItemByData("Teams", t->getId()); gdi.selectItemByData("Teams", t->getId());
@ -205,6 +205,10 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
gdi.setText("PointIn", t->getInputPoints()); gdi.setText("PointIn", t->getInputPoints());
} }
if (gdi.hasField("NoRestart")) {
gdi.check("NoRestart", t->preventRestart());
}
loadTeamMembers(gdi, 0, 0, t); loadTeamMembers(gdi, 0, 0, t);
} }
else { else {
@ -320,6 +324,10 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
if (gdi.hasField("Fee")) if (gdi.hasField("Fee"))
t->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee"))); t->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
if (gdi.hasField("NoRestart"))
t->preventRestart(gdi.isChecked("NoRestart"));
t->apply(false, 0, false); t->apply(false, 0, false);
if (gdi.hasField("Club")) { if (gdi.hasField("Club")) {
@ -436,7 +444,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
r->setCardNo(cardNo, true); r->setCardNo(cardNo, true);
if (gdi.isChecked("RENT" + itos(i))) if (gdi.isChecked("RENT" + itos(i)))
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee")); r->getDI().setInt("CardFee", oe->getBaseCardFee());
else else
r->getDI().setInt("CardFee", 0); r->getDI().setInt("CardFee", 0);
@ -617,15 +625,14 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
bool rExists = r != 0; bool rExists = r != 0;
pRunner old = oe->getRunnerByCardNo(card, 0, true, true); pRunner old = oe->getRunnerByCardNo(card, 0, oEvent::CardLookupProperty::CardInUse);
if (old && r != old) { if (old && r != old) {
throw meosException(L"Brickan används av X.#" + old->getName() ); throw meosException(L"Brickan används av X.#" + old->getName() );
} }
pClub clb = 0; pClub clb = 0;
if (!rExists) { if (!rExists) {
pRunner rOrig = oe->getRunnerByCardNo(card, 0, false, false); pRunner rOrig = oe->getRunnerByCardNo(card, 0, oEvent::CardLookupProperty::Any);
if (rOrig) if (rOrig)
clb = rOrig->getClubRef(); clb = rOrig->getClubRef();
} }
@ -636,7 +643,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(false), card, 0, false); r = oe->addRunner(name, clb ? clb->getId() : t->getClubId(), t->getClassId(false), card, 0, false);
} }
if (rent) if (rent)
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee")); r->getDI().setInt("CardFee", oe->getBaseCardFee());
t->synchronize(); t->synchronize();
pRunner oldR = t->getRunner(leg); pRunner oldR = t->getRunner(leg);
@ -653,13 +660,17 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
oldR->synchronize(true); oldR->synchronize(true);
t->setRunner(leg, r, true); t->setRunner(leg, r, true);
t->checkValdParSetup(); t->checkValdParSetup();
if (oldR->isAnnonumousTeamMember())
oe->removeRunner({ oldR->getId() });
t->synchronize(true);
} }
} }
else { else {
t->setRunner(leg, r, true); t->setRunner(leg, r, true);
t->checkValdParSetup(); t->checkValdParSetup();
t->synchronize(true);
} }
selectTeam(gdi, t); selectTeam(gdi, t);
} }
else if (bi.id == "Browse") { else if (bi.id == "Browse") {
@ -1017,7 +1028,6 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
pClass pc=oe->getClass(lbi.data); pClass pc=oe->getClass(lbi.data);
if (pc) { if (pc) {
vector<pRunner> rCache;
for(unsigned i=0;i<pc->getNumStages();i++){ for(unsigned i=0;i<pc->getNumStages();i++){
char bf[16]; char bf[16];
sprintf_s(bf, "R%d", i); sprintf_s(bf, "R%d", i);
@ -1027,7 +1037,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
sprintf_s(bf, "SI%d", i); sprintf_s(bf, "SI%d", i);
int cno = r->getCardNo(); int cno = r->getCardNo();
gdi.setText(bf, cno > 0 ? itow(cno) : L""); gdi.setText(bf, cno > 0 ? itow(cno) : L"");
warnDuplicateCard(gdi, bf, cno, r, rCache); warnDuplicateCard(gdi, bf, cno, r);
} }
} }
} }
@ -1094,14 +1104,14 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
int cno = gdi.getTextNo("DirCard"); int cno = gdi.getTextNo("DirCard");
if (cno > 0 && gdi.getText("DirName").empty()) { if (cno > 0 && gdi.getText("DirName").empty()) {
bool matched = false; bool matched = false;
pRunner r = oe->getRunnerByCardNo(cno, 0, true, false); pRunner r = oe->getRunnerByCardNo(cno, 0, oEvent::CardLookupProperty::ForReadout);
if (r && (r->getStatus() == StatusUnknown || r->getStatus() == StatusDNS) ) { if (r && (r->getStatus() == StatusUnknown || r->getStatus() == StatusDNS) ) {
// Switch to exactly this runner. Has not run before // Switch to exactly this runner. Has not run before
gdi.setText("DirName", r->getName())->setExtra(r->getId()); gdi.setText("DirName", r->getName())->setExtra(r->getId());
matched = true; matched = true;
} }
else { else {
r = oe->getRunnerByCardNo(cno, 0, false, false); r = oe->getRunnerByCardNo(cno, 0, oEvent::CardLookupProperty::Any);
if (r) { if (r) {
// Copy only the name. // Copy only the name.
gdi.setText("DirName", r->getName())->setExtra(0); gdi.setText("DirName", r->getName())->setExtra(0);
@ -1130,8 +1140,7 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
int cardNo = _wtoi(ii.text.c_str()); int cardNo = _wtoi(ii.text.c_str());
pTeam t = oe->getTeam(teamId); pTeam t = oe->getTeam(teamId);
if (t) { if (t) {
vector<pRunner> rc; warnDuplicateCard(gdi, ii.id, cardNo, t->getRunner(i));
warnDuplicateCard(gdi, ii.id, cardNo, t->getRunner(i), rc);
} }
break; break;
} }
@ -1209,7 +1218,6 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
gdi.addString("", yp, xp + dx[3], 0, "Hyrd:"); gdi.addString("", yp, xp + dx[3], 0, "Hyrd:");
gdi.addString("", yp, xp + dx[5], 0, "Status:"); gdi.addString("", yp, xp + dx[5], 0, "Status:");
gdi.dropLine(0.5); gdi.dropLine(0.5);
vector<pRunner> rCache;
for (unsigned i=0;i<pc->getNumStages();i++) { for (unsigned i=0;i<pc->getNumStages();i++) {
yp = gdi.getCY(); yp = gdi.getCY();
@ -1249,7 +1257,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
if (hasSI) { if (hasSI) {
int cno = r->getCardNo(); int cno = r->getCardNo();
gdi.setText(bf_si, cno > 0 ? itow(cno) : L""); gdi.setText(bf_si, cno > 0 ? itow(cno) : L"");
warnDuplicateCard(gdi, bf_si, cno, r, rCache); warnDuplicateCard(gdi, bf_si, cno, r);
gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0); gdi.check("RENT" + itos(i), r->getDCI().getInt("CardFee") != 0);
} }
string sid = "STATUS"+itos(i); string sid = "STATUS"+itos(i);
@ -1259,7 +1267,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
ti->setColor(colorGreen); ti->setColor(colorGreen);
} }
else if (r->getStatus() != StatusUnknown) { else if (r->getStatus() != StatusUnknown) {
TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS() + L", " + r->getRunningTimeS(), false); TextInfo * ti = (TextInfo *)gdi.setText(sid, r->getStatusS(false) + L", " + r->getRunningTimeS(), false);
if (ti) if (ti)
ti->setColor(colorRed); ti->setColor(colorRed);
} }
@ -1378,7 +1386,7 @@ bool TabTeam::loadPage(gdioutput &gdi)
} }
gdi.addSelection("RClass", 170, 300, TeamCB, L"Klass:"); gdi.addSelection("RClass", 170, 300, TeamCB, L"Klass:");
oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterNone); oe->fillClasses(gdi, "RClass", oEvent::extraNone, oEvent::filterOnlyMulti);
gdi.addItem("RClass", lang.tl("Ny klass"), 0); gdi.addItem("RClass", lang.tl("Ny klass"), 0);
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy)) if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy))
@ -1432,6 +1440,9 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.popX(); gdi.popX();
gdi.selectItemByData("Status", 0); gdi.selectItemByData("Status", 0);
if (oe->hasAnyRestartTime()) {
gdi.addCheckbox("NoRestart", "Förhindra omstart", 0, false, "Förhindra att laget deltar i någon omstart");
}
gdi.dropLine(1.5); gdi.dropLine(1.5);
const bool multiDay = oe->hasPrevStage(); const bool multiDay = oe->hasPrevStage();
@ -1491,18 +1502,18 @@ bool TabTeam::loadPage(gdioutput &gdi)
rc.left = posXForButtons; rc.left = posXForButtons;
rc.top = posYForButtons; rc.top = posYForButtons;
gdi.setCY(posYForButtons + gdi.scaleLength(4)); gdi.setCY(posYForButtons + gdi.scaleLength(10));
gdi.setCX(posXForButtons + gdi.getLineHeight()); gdi.setCX(posXForButtons + gdi.getLineHeight());
gdi.fillDown(); gdi.fillDown();
gdi.addString("", 1, "Verktyg"); gdi.addString("", fontMediumPlus, "Verktyg");
gdi.dropLine(0.3); gdi.dropLine(0.3);
gdi.fillRight(); gdi.fillRight();
gdi.addButton("ImportTeams", "Importera laguppställningar", TeamCB); gdi.addButton("ImportTeams", "Importera laguppställningar", TeamCB);
gdi.addButton("AddTeamMembers", "Skapa anonyma lagmedlemmar", TeamCB, "Fyll obesatta sträckor i alla lag med anonyma tillfälliga lagmedlemmar (N.N.)"); gdi.addButton("AddTeamMembers", "Skapa anonyma lagmedlemmar", TeamCB, "Fyll obesatta sträckor i alla lag med anonyma tillfälliga lagmedlemmar (N.N.)");
rc.right = gdi.getCX() + gdi.getLineHeight(); rc.right = gdi.getCX() + gdi.getLineHeight();
gdi.dropLine(1.5); gdi.dropLine(2);
rc.bottom = gdi.getHeight(); rc.bottom = gdi.getHeight();
gdi.addRectangle(rc, colorLightCyan); gdi.addRectangle(rc, colorLightBlue);
gdi.setRestorePoint(); gdi.setRestorePoint();
@ -1692,7 +1703,7 @@ pRunner TabTeam::findRunner(const wstring &name, int cardNo) const {
if (cardNo != 0) { if (cardNo != 0) {
vector<pRunner> pr; vector<pRunner> pr;
oe->getRunnersByCard(cardNo, pr); oe->getRunnersByCardNo(cardNo, true, oEvent::CardLookupProperty::Any, pr);
for (size_t k = 0; k < pr.size(); k++) { for (size_t k = 0; k < pr.size(); k++) {
wstring a = canonizeName(pr[k]->getName().c_str()); wstring a = canonizeName(pr[k]->getName().c_str());
if (a == n) if (a == n)
@ -1876,6 +1887,7 @@ void TabTeam::processChangeRunner(gdioutput &gdi, pTeam t, int leg, pRunner r) {
void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) { void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
vector<int> mp; vector<int> mp;
bool removeAnnonumousTeamMember = false;
if (r->getTeam()) { if (r->getTeam()) {
pTeam otherTeam = r->getTeam(); pTeam otherTeam = r->getTeam();
@ -1890,7 +1902,11 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
else if (oldR) { else if (oldR) {
t->setRunner(leg, 0, false); t->setRunner(leg, 0, false);
t->synchronize(true); t->synchronize(true);
if (r->getClassRef(false) && r->getClassRef(false)->isTeamClass())
oldR->setClassId(0, false);
else
oldR->setClassId(r->getClassId(false), true); oldR->setClassId(r->getClassId(false), true);
removeAnnonumousTeamMember = oldR->isAnnonumousTeamMember();
oldR->evaluateCard(true, mp, 0, true); oldR->evaluateCard(true, mp, 0, true);
oldR->synchronize(true); oldR->synchronize(true);
} }
@ -1900,6 +1916,9 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
t->checkValdParSetup(); t->checkValdParSetup();
t->apply(true, 0, false); t->apply(true, 0, false);
t->synchronize(true); t->synchronize(true);
if (removeAnnonumousTeamMember)
oe->removeRunner({ oldR->getId() });
} }
void TabTeam::clearCompetitionData() { void TabTeam::clearCompetitionData() {
@ -1911,16 +1930,15 @@ void TabTeam::clearCompetitionData() {
currentMode = 0; currentMode = 0;
} }
bool TabTeam::warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r, vector<pRunner> &allRCache) { bool TabTeam::warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r) {
pRunner warnCardDupl = 0; pRunner warnCardDupl = 0;
if (r && !r->getCard()) { if (r && !r->getCard() && cno != 0) {
if (allRCache.empty()) // Fill cache if not initialized vector<pRunner> allR;
oe->getRunners(0, 0, allRCache, false); oe->getRunnersByCardNo(cno, true, oEvent::CardLookupProperty::Any, allR);
for (pRunner ar : allR) {
for (size_t k = 0; k < allRCache.size(); k++) { if (!r->canShareCard(ar, cno)) {
if (!r->canShareCard(allRCache[k], cno)) { warnCardDupl = ar;
warnCardDupl = allRCache[k];
break; break;
} }
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -70,7 +70,7 @@ private:
vector<TeamLineup> teamLineup; vector<TeamLineup> teamLineup;
// Returns true if the warning concerns the same team // Returns true if the warning concerns the same team
bool warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r, vector<pRunner> &allRCache); bool warnDuplicateCard(gdioutput &gdi, string id, int cno, pRunner r);
void switchRunners(pTeam team, int leg, pRunner r, pRunner oldR); void switchRunners(pTeam team, int leg, pRunner r, pRunner oldR);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1023,8 +1023,8 @@ void Table::initEmpty() {
void drawSymbol(gdioutput &gdi, HDC hDC, int height, void drawSymbol(gdioutput &gdi, HDC hDC, int height,
const TextInfo &ti, const wstring &symbol, bool highLight) { const TextInfo &ti, const wstring &symbol, bool highLight) {
int cx = ti.xp - gdi.GetOffsetX() + ti.xlimit/2; int cx = ti.xp - gdi.getOffsetX() + ti.xlimit/2;
int cy = ti.yp - gdi.GetOffsetY() + height/2 - 2; int cy = ti.yp - gdi.getOffsetY() + height/2 - 2;
int h = int(height * 0.4); int h = int(height * 0.4);
int w = h/3; int w = h/3;
h-=2; h-=2;

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -10,7 +10,7 @@
#endif // _MSC_VER > 1000 #endif // _MSC_VER > 1000
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@ Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
#include "Printer.h" #include "Printer.h"
AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol, AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol,
int marginPercent, bool animate) : int marginPercent, bool animate, bool respectPageBreak) :
nCol(nCol), animate(animate), page(-1), gdiRef(0) { nCol(nCol), animate(animate), page(-1), gdiRef(0) {
lastTime = 0; lastTime = 0;
@ -56,7 +56,7 @@ AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol,
pageInfo.yMM2PrintK = 0; pageInfo.yMM2PrintK = 0;
list<RectangleInfo> rectangles; list<RectangleInfo> rectangles;
pageInfo.renderPages(gdi.getTL(), rectangles, false, pages); pageInfo.renderPages(gdi.getTL(), rectangles, false, respectPageBreak, pages);
} }
AnimationData::~AnimationData() { AnimationData::~AnimationData() {
@ -194,8 +194,8 @@ void AnimationData::threadRender(gdioutput *gdi, size_t sp, int delay) {
} }
void AnimationData::renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, int x, int y, int animateDelay) { void AnimationData::renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, int x, int y, int animateDelay) {
int ox = gdi.GetOffsetX(); int ox = gdi.getOffsetX();
int oy = gdi.GetOffsetY(); int oy = gdi.getOffsetY();
int top = 10000; int top = 10000;
for (const auto &text : page.text) { for (const auto &text : page.text) {
@ -203,8 +203,8 @@ void AnimationData::renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, i
top = min<int>(top, text.ti.yp); top = min<int>(top, text.ti.yp);
} }
} }
gdi.SetOffsetY(-y+top-margin/2); gdi.setOffsetY(-y+top-margin/2);
gdi.SetOffsetX(-x); gdi.setOffsetX(-x);
int currentRow = 0; int currentRow = 0;
for (auto &text : page.text) { for (auto &text : page.text) {
@ -214,8 +214,8 @@ void AnimationData::renderSubPage(HDC hDC, gdioutput &gdi, RenderedPage &page, i
} }
gdi.RenderString(text.ti, hDC); gdi.RenderString(text.ti, hDC);
} }
gdi.SetOffsetY(ox); gdi.setOffsetY(ox);
gdi.SetOffsetX(oy); gdi.setOffsetX(oy);
} }
void AnimationData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) { void AnimationData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -54,7 +54,7 @@ class AnimationData : public GuiHandler {
public: public:
AnimationData(gdioutput &gdi, int timePerPage, int nCol, AnimationData(gdioutput &gdi, int timePerPage, int nCol,
int marginPercent, bool animate); int marginPercent, bool animate, bool respectPageBreak);
~AnimationData(); ~AnimationData();
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type); void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,4 +1,27 @@
#pragma once #pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include <vector> #include <vector>
#include "gdioutput.h" #include "gdioutput.h"

View File

@ -1,4 +1,25 @@
#pragma once #pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
class AutoCompleteInfo; class AutoCompleteInfo;
class gdioutput; class gdioutput;

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -115,6 +115,7 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
cnf.clear(); cnf.clear();
cnf.hasMultiEvent = hasPrevStage() || hasNextStage(); cnf.hasMultiEvent = hasPrevStage() || hasNextStage();
map<int, vector<const oRunner *>> runnerPerClass;
for (it = Classes.begin(); it != Classes.end(); ++it) { for (it = Classes.begin(); it != Classes.end(); ++it) {
if (it->isRemoved()) if (it->isRemoved())
@ -129,6 +130,57 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
if (it->getCourse() == 0) if (it->getCourse() == 0)
cnf.classWithoutCourse.push_back(it->getName()); //MultiCourse not analysed... cnf.classWithoutCourse.push_back(it->getName()); //MultiCourse not analysed...
if (it->isQualificationFinalBaseClass())
cnf.knockout.push_back(it->getId());
if (Courses.empty() || (it->getCourse(false) == nullptr && it->getCourse(0,0, false) == nullptr) ||
(it->getCourse(false) && it->getCourse(false)->getNumControls() == 0)) {
if (!it->isQualificationFinalBaseClass()) {
// No course.
if (runnerPerClass.empty()) {
for (auto &r : Runners) {
if (!r.skip() && r.getClassRef(false) != nullptr)
runnerPerClass[r.getClassId(true)].push_back(&r);
}
}
map<int, int> punches;
int cntSample = 0;
for (auto r : runnerPerClass[it->getId()]) {
if (r->getCard()) {
for (auto &p : r->getCard()->punches) {
int tc = p.getTypeCode();
if (tc > 30)
++punches[tc];
}
if (++cntSample > 10)
break;
}
}
bool single = true, extra = true;
if (cntSample > 3) {
int usedControlCodes = 0;
for (auto &p : punches) {
if (p.second >= cntSample / 2)
usedControlCodes++;
}
if (usedControlCodes == 1)
extra = false;
else if (usedControlCodes > 1)
single = false;
}
if (single)
cnf.lapcountsingle.push_back(it->getId());
if (extra)
cnf.lapcountextra.push_back(it->getId());
}
}
if ( !it->hasCoursePool() ) { if ( !it->hasCoursePool() ) {
for (size_t k = 0; k< it->MultiCourse.size(); k++) { for (size_t k = 0; k< it->MultiCourse.size(); k++) {
if (it->MultiCourse[k].size() > 1) if (it->MultiCourse[k].size() > 1)

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -44,6 +44,11 @@ public:
vector<int> rogainingClasses; vector<int> rogainingClasses;
vector<int> knockout;
vector<int> lapcountsingle;
vector<int> lapcountextra;
// True if predefined forking // True if predefined forking
bool hasMultiCourse; bool hasMultiCourse;

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -63,35 +63,40 @@ csvparser::~csvparser()
} }
int csvparser::iscsv(const wstring &file) csvparser::CSV csvparser::iscsv(const wstring &file) {
{ ifstream fin(file);
fin.open(file);
if (!fin.good()) if (!fin.good())
return false; return CSV::NoCSV;
char bf[2048]; char bf[2048];
bool isCSVType = false;
while (fin.good() && !isCSVType) {
fin.getline(bf, 2048); fin.getline(bf, 2048);
isCSVType = strlen(bf) >= 3;
while(fin.good() && strlen(bf)<3) }
fin.getline(bf, 2048);
fin.close(); fin.close();
vector<char *> sp; vector<char *> sp;
split(bf, sp); split(bf, sp);
if (sp.size() > 0) {
string sp0 = sp[0];
if (sp0.find("<?xml") != string::npos)
return CSV::NoCSV;
}
if (sp.size()==1 && strcmp(sp[0], "RAIDDATA")==0) if (sp.size()==1 && strcmp(sp[0], "RAIDDATA")==0)
return 3; return CSV::RAID;
if (sp.size()<5)//No csv if (sp.size()<2)//No csv
return 0; return CSV::NoCSV;
if (_stricmp(sp[1], "Descr")==0 || _stricmp(sp[1], "Namn")==0 if (_stricmp(sp[1], "Descr")==0 || _stricmp(sp[1], "Namn")==0
|| _stricmp(sp[1], "Descr.")==0 || _stricmp(sp[1], "Navn")==0) //OS-fil (SWE/ENG)?? || _stricmp(sp[1], "Descr.")==0 || _stricmp(sp[1], "Navn")==0) //OS-fil (SWE/ENG)??
return 2; return CSV::OS;
else return 1; //OE?! else return CSV::OE; //OE?!
} }
RunnerStatus ConvertOEStatus(int i) RunnerStatus ConvertOEStatus(int i)
{ {
@ -126,20 +131,13 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
enum {OSRsname=0, OSRfname=1, OSRyb=2, OSRsex=3, OSRstart=4, enum {OSRsname=0, OSRfname=1, OSRyb=2, OSRsex=3, OSRstart=4,
OSRfinish=5, OSRstatus=7, OSRcard=8, OSRrentcard=9}; OSRfinish=5, OSRstatus=7, OSRcard=8, OSRrentcard=9};
/*
fin.open(file);
if (!fin.good())
return false;
char bf[1024];
fin.getline(bf, 1024);
*/
nimport=0; nimport=0;
list< vector<wstring> > allLines; list< vector<wstring> > allLines;
parse(file, allLines); parse(file, allLines);
//vector<wchar_t *> sp;
list< vector<wstring> >::iterator it = allLines.begin(); list< vector<wstring> >::iterator it = allLines.begin();
set<wstring> matchedClasses;
// Skip first line // Skip first line
while (++it != allLines.end()) { while (++it != allLines.end()) {
//fin.getline(bf, 1024); //fin.getline(bf, 1024);
@ -161,7 +159,7 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
//Create class with this class number... //Create class with this class number...
int ClassId=wtoi(sp[OSclassno]); int ClassId=wtoi(sp[OSclassno]);
event.getClassCreate(ClassId, sp[OSclass]); event.getClassCreate(ClassId, sp[OSclass], matchedClasses);
//Club is autocreated... //Club is autocreated...
pTeam team=event.addTeam(sp[OSclub] + L" " + sp[OSdesc], ClubId, ClassId); pTeam team=event.addTeam(sp[OSclub] + L" " + sp[OSdesc], ClubId, ClassId);
@ -210,10 +208,10 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
r->setFinishTime( event.convertAbsoluteTime(sp[rindex+OSRfinish]) ); r->setFinishTime( event.convertAbsoluteTime(sp[rindex+OSRfinish]) );
if (sp[rindex+OSRstatus].length()>0) if (sp[rindex+OSRstatus].length()>0)
r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, false); r->setStatus( ConvertOEStatus( wtoi(sp[rindex+OSRstatus]) ), true, false, false);
if (r->getStatus()==StatusOK && r->getRunningTime()==0) if (r->getStatus()==StatusOK && r->getRunningTime()==0)
r->setStatus(StatusUnknown, true, false); r->setStatus(StatusUnknown, true, false, false);
r->addClassDefaultFee(false); r->addClassDefaultFee(false);
@ -244,24 +242,14 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
OErent=35, OEfee=36, OEpaid=37, OEcourseno=38, OEcourse=39, OErent=35, OEfee=36, OEpaid=37, OEcourseno=38, OEcourse=39,
OElength=40}; OElength=40};
/* fin.open(file);
if (!fin.good())
return false;
char bf[1024];
fin.getline(bf, 1024);
*/
list< vector<wstring> > allLines; list< vector<wstring> > allLines;
parse(file, allLines); parse(file, allLines);
list< vector<wstring> >::iterator it = allLines.begin(); list< vector<wstring> >::iterator it = allLines.begin();
set<wstring> matchedClasses;
// Skip first line // Skip first line
nimport=0; nimport=0;
while (++it != allLines.end()) { while (++it != allLines.end()) {
//fin.getline(bf, 1024);
//split(bf, sp);
const vector<wstring> &sp = *it; const vector<wstring> &sp = *it;
if (sp.size()>20) { if (sp.size()>20) {
nimport++; nimport++;
@ -348,7 +336,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
//Autocreate class if it does not exist... //Autocreate class if it does not exist...
int classId=wtoi(sp[OEclassno]); int classId=wtoi(sp[OEclassno]);
if (classId>0 && !pr->hasFlag(oAbstractRunner::FlagUpdateClass)) { if (classId>0 && !pr->hasFlag(oAbstractRunner::FlagUpdateClass)) {
pClass pc=event.getClassCreate(classId, sp[OEclass]); pClass pc=event.getClassCreate(classId, sp[OEclass], matchedClasses);
if (pc) { if (pc) {
pc->synchronize(); pc->synchronize();
@ -675,6 +663,8 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
list< vector<wstring> > allLines; list< vector<wstring> > allLines;
parse(file, allLines); parse(file, allLines);
set<wstring> matchedClasses;
list< vector<wstring> >::iterator it = allLines.begin(); list< vector<wstring> >::iterator it = allLines.begin();
nimport=0; nimport=0;
while (++it != allLines.end()) { while (++it != allLines.end()) {
@ -686,7 +676,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
int ClubId=0; int ClubId=0;
//Create class with this class number... //Create class with this class number...
int ClassId=wtoi(sp[RAIDclassid]); int ClassId=wtoi(sp[RAIDclassid]);
pClass pc = event.getClassCreate(ClassId, sp[RAIDclass]); pClass pc = event.getClassCreate(ClassId, sp[RAIDclass], matchedClasses);
ClassId = pc->getId(); ClassId = pc->getId();
//Club is autocreated... //Club is autocreated...
@ -1357,3 +1347,127 @@ void csvparser::importTeamLineup(const wstring &file,
data.pop_front(); data.pop_front();
} }
} }
int csvparser::importRanking(oEvent &oe, const wstring &file, vector<wstring> &problems) {
list< vector<wstring> > data;
parse(file, data);
size_t idIx = -1;
size_t nameIx = 1;
size_t lastNameIx = -1;
size_t rankIx = -1;
map<int64_t, pair<wstring, int> > id2Rank;
map<wstring, pair<int, bool> > name2RankDup;
bool first = true;
for (auto &rank : data) {
if (first) {
first = false;
bool any = false;
for (size_t i = 0; i < rank.size(); i++) {
wstring s = canonizeName(rank[i].c_str());
if (s.find(L"name") != wstring::npos && (s.find(L"last") != wstring::npos || s.find(L"family") != wstring::npos) && lastNameIx == -1) {
lastNameIx = i;
any = true;
}
else if (s.find(L"name") != wstring::npos && (s.find(L"first") != wstring::npos || s.find(L"given") != wstring::npos) && nameIx == -1) {
nameIx = i;
any = true;
}
else if (s.find(L" id") != wstring::npos && idIx == -1) {
idIx = i;
any = true;
}
else if (s.find(L"position") != wstring::npos && rankIx == -1) {
rankIx = i;
any = true;
}
}
if (idIx == -1)
idIx = 0;
if (nameIx == -1)
nameIx = 1;
if (lastNameIx == -1)
lastNameIx = 2;
if (rankIx == -1)
rankIx = 4;
if (any)
continue;
}
if (rank.size() <= rankIx)
continue;
int rpos = _wtoi(rank[rankIx].c_str());
if (rpos <= 0)
continue;
wstring name;
if (nameIx < rank.size()) {
name = rank[nameIx];
if (lastNameIx < rank.size()) {
name += L" " + rank[lastNameIx];
}
}
if (name.empty())
continue;
auto res = name2RankDup.emplace(name, make_pair(rpos, false));
if (!res.second)
res.first->second.second = true; // Duplicate names
if (idIx < rank.size()) {
int64_t id = oBase::converExtIdentifierString(rank[idIx]);
if (id != 0)
id2Rank[id] = make_pair(name, rpos);
}
}
if ((name2RankDup.size() < data.size() / 2 || name2RankDup.empty()) &&
(id2Rank.size() < data.size() / 2 || id2Rank.empty())) {
throw meosException(L"Felaktigt rankingformat i X. Förväntat: Y#" + file + L"#ID; First name; Last name; Rank");
}
vector<pRunner> runners;
oe.getRunners(-1, -1, runners);
int count = 0;
vector<pRunner> remRunners;
for (pRunner r : runners) {
int64_t id = r->getExtIdentifier();
auto res = id2Rank.find(id);
if (res != id2Rank.end() && r->matchName(res->second.first)) {
r->getDI().setInt("Rank", res->second.second);
r->synchronize(true);
count++;
}
else
remRunners.push_back(r);
}
for (pRunner r : remRunners) {
auto res = name2RankDup.find(r->getName());
if (r->getRaceNo() > 0)
continue;
if (res != name2RankDup.end()) {
if (res->second.second)
problems.push_back(r->getCompleteIdentification());
else {
res->second.second = true;
r->getDI().setInt("Rank", res->second.first);
r->synchronize(true);
count++;
}
}
}
return count;
}

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -134,10 +134,21 @@ public:
bool importCards(const oEvent &oe, const wstring &file, bool importCards(const oEvent &oe, const wstring &file,
vector<SICard> &punches); vector<SICard> &punches);
int split(char *line, vector<char *> &split); int importRanking(oEvent &oe, const wstring &file, vector<wstring> & problems);
int split(wchar_t *line, vector<wchar_t *> &split);
static int split(char *line, vector<char *> &split);
static int split(wchar_t *line, vector<wchar_t *> &split);
enum class CSV {
NoCSV,
Unknown,
RAID,
OE,
OS,
};
static CSV iscsv(const wstring &file);
int iscsv(const wstring &file);
csvparser(); csvparser();
virtual ~csvparser(); virtual ~csvparser();

View File

@ -752,7 +752,7 @@ Radera tävlingen = Smaž závod
Radera vakanser = Odstraň vakanty Radera vakanser = Odstraň vakanty
Radiotider, kontroll = Radio-čas, kontrola Radiotider, kontroll = Radio-čas, kontrola
Ranking = Ranking Ranking = Ranking
Ranking (IOF, xml) = Ranking (IOF, xml) Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
Rapport inför = Protokol pro Rapport inför = Protokol pro
Rapporter = Protokoly Rapporter = Protokoly
Rapportläge = Režim protokolu Rapportläge = Režim protokolu
@ -2295,7 +2295,7 @@ help:rest = MeOS REST API ti umožní přístup k datům závodu skrze webové s
Server startad på X = Server běžící na portu X Server startad på X = Server běžící na portu X
Inconsistent qualification rule, X = Nekonzistentní kvalifikační pravidlo, X Inconsistent qualification rule, X = Nekonzistentní kvalifikační pravidlo, X
help:LockStartList = MeOS neprovede aktualizaci zamknuté kategorie přestože kvalifikační výsledky jsou změněny. help:LockStartList = MeOS neprovede aktualizaci zamknuté kategorie přestože kvalifikační výsledky jsou změněny.
Kval-Final-Schema = Načti kvalifikační schéma Kval/final-schema = Načti kvalifikační schéma
Lås startlista = Zamkni startovku Lås startlista = Zamkni startovku
FilterNoCancel = Není zrušeno FilterNoCancel = Není zrušeno
CourseStartTime = Trať, čas startu CourseStartTime = Trať, čas startu

View File

@ -1014,7 +1014,7 @@ Kunde inte öppna tävlingen = Kan ikke åbne løbet
Kunde inte ansluta till Eventor = Kunne ikke forbinde til Eventor Kunde inte ansluta till Eventor = Kunne ikke forbinde til Eventor
Kunde inte ladda upp tävlingen (X) = Kunne ikke uploade løbet (X) Kunde inte ladda upp tävlingen (X) = Kunne ikke uploade løbet (X)
Kunde inte ladda X\n\n(Y) = Kunne ikke indlæse X\n\n(Y) Kunde inte ladda X\n\n(Y) = Kunne ikke indlæse X\n\n(Y)
Kval-Final-Schema = Kval-Finale-Skema Kval/final-schema = Kval/Finale-Skema
Kvar-i-skogen = Løbere i skoven Kvar-i-skogen = Løbere i skoven
Kvinna = Kvinde Kvinna = Kvinde
Kvinnor = Kvinder Kvinnor = Kvinder
@ -1468,7 +1468,7 @@ Radera tävlingen = Slet løbet
Radera vakanser = Slet vakante Radera vakanser = Slet vakante
radio X = radio X radio X = radio X
Radiotider, kontroll = Radiotider, post Radiotider, kontroll = Radiotider, post
Ranking (IOF, xml) = Rangliste (IOF, XML) Ranking (IOF, xml, csv) = Rangliste (IOF, xml, csv)
Ranking = Rangliste Ranking = Rangliste
Rapport = Rapport Rapport = Rapport
Rapport inför = Rapport før Rapport inför = Rapport før

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -27,13 +27,18 @@
#include "meos_util.h" #include "meos_util.h"
#include "progress.h" #include "progress.h"
#include "meosexception.h" #include "meosexception.h"
#include <winsock2.h>
#include <iphlpapi.h>
#include <cassert>
#include <sys/stat.h> #include <sys/stat.h>
#include <io.h> #include <io.h>
#include <fcntl.h> #include <fcntl.h>
#include <process.h> #include <process.h>
#pragma comment(lib, "IPHLPAPI.lib")
#define INET_ADDRSTRLEN 16
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// Construction/Destruction // Construction/Destruction
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -472,3 +477,124 @@ bool Download::httpSendReqEx(HINTERNET hConnect, bool https, const wstring &dest
InternetCloseHandle(hRequest); InternetCloseHandle(hRequest);
return true; return true;
} }
void ListIpAddresses(vector<string>& ipAddrs)
{
ipAddrs.clear();
IP_ADAPTER_ADDRESSES* adapter_addresses(NULL);
IP_ADAPTER_ADDRESSES* adapter(NULL);
const int KB = 1024;
// Start with a 16 KB buffer and resize if needed -
// multiple attempts in case interfaces change while
// we are in the middle of querying them.
DWORD adapter_addresses_buffer_size = 16 * 1024;
for (int attempts = 0; attempts != 3; ++attempts)
{
adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addresses_buffer_size);
assert(adapter_addresses);
DWORD error = ::GetAdaptersAddresses(
AF_UNSPEC,
GAA_FLAG_SKIP_ANYCAST |
GAA_FLAG_SKIP_MULTICAST |
GAA_FLAG_SKIP_DNS_SERVER |
GAA_FLAG_SKIP_FRIENDLY_NAME,
NULL,
adapter_addresses,
&adapter_addresses_buffer_size);
if (ERROR_SUCCESS == error) {
// We're done here, people!
break;
}
else if (ERROR_BUFFER_OVERFLOW == error)
{
// Try again with the new size
free(adapter_addresses);
adapter_addresses = NULL;
continue;
}
else {
// Unexpected error code - log and throw
free(adapter_addresses);
adapter_addresses = NULL;
return;
}
}
// Iterate through all of the adapters
for (adapter = adapter_addresses; NULL != adapter; adapter = adapter->Next)
{
// Skip loopback adapters
if (IF_TYPE_SOFTWARE_LOOPBACK == adapter->IfType)
{
continue;
}
// Parse all IPv4 and IPv6 addresses
for (
IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
NULL != address;
address = address->Next)
{
auto family = address->Address.lpSockaddr->sa_family;
if (AF_INET == family)
{
// IPv4
SOCKADDR_IN* ipv4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);
char str_buffer[INET_ADDRSTRLEN] = { 0 };
//inet_ntop(AF_INET, &(ipv4->sin_addr), str_buffer, INET_ADDRSTRLEN);
auto &id = ipv4->sin_addr.S_un.S_un_b;
if (id.s_b1 == 169 && id.s_b2 == 254)
continue; // Not usable
sprintf_s(str_buffer, "%u.%u.%u.%u", id.s_b1, id.s_b2, id.s_b3, id.s_b4);
ipAddrs.emplace_back(str_buffer);
}
else if (AF_INET6 == family)
{/*
// IPv6
SOCKADDR_IN6* ipv6 = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);
char str_buffer[INET6_ADDRSTRLEN] = { 0 };
inet_ntop(AF_INET6, &(ipv6->sin6_addr), str_buffer, INET6_ADDRSTRLEN);
std::string ipv6_str(str_buffer);
// Detect and skip non-external addresses
bool is_link_local(false);
bool is_special_use(false);
if (0 == ipv6_str.find("fe"))
{
char c = ipv6_str[2];
if (c == '8' || c == '9' || c == 'a' || c == 'b')
{
is_link_local = true;
}
}
else if (0 == ipv6_str.find("2001:0:"))
{
is_special_use = true;
}
if (!(is_link_local || is_special_use))
{
ipAddrs.mIpv6.push_back(ipv6_str);
}*/
}
else
{
// Skip all other types of addresses
continue;
}
}
}
// Cleanup
free(adapter_addresses);
adapter_addresses = NULL;
}

View File

@ -7,7 +7,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -619,9 +619,9 @@ Mata in radiotider manuellt = Enter radio times by hand
Max antal gemensamma kontroller = Max number common controls Max antal gemensamma kontroller = Max number common controls
Max parallellt startande = Max. number parallel start Max parallellt startande = Max. number parallel start
Max. vakanser (per klass) = Max. vacancy (per class) Max. vakanser (per klass) = Max. vacancy (per class)
Maximal tid efter ledaren för att delta i jaktstart = Maximal time after leader to participate in pursuit. Maximal tid efter ledaren för att delta i jaktstart = Maximal time behind leader to participate in pursuit.
Maxtid = OMT Maxtid = OMT
Maxtid efter = Maximum time after Maxtid efter = Maximum time behind
MeOS = MeOS MeOS = MeOS
MeOS lokala datakatalog är = MeOS local data folder is MeOS lokala datakatalog är = MeOS local data folder is
MeOS Resultatkiosk = MeOS Result Kiosk MeOS Resultatkiosk = MeOS Result Kiosk
@ -685,7 +685,7 @@ Ogiltig föregående/efterföljande etapp = Invalid previous/next stage
Ogiltig första starttid. Måste vara efter nolltid = Invalid first start time. Must be after zero time Ogiltig första starttid. Måste vara efter nolltid = Invalid first start time. Must be after zero time
Ogiltig omstartstid = Invalid restart time Ogiltig omstartstid = Invalid restart time
Ogiltig repdragningstid = Invalid rope time Ogiltig repdragningstid = Invalid rope time
Ogiltig starttid i 'X' på sträcka Y = Invalid start time in 'X' on leg Y Ogiltig starttid i 'X' på sträcka Y = Invalid start time for 'X' on leg Y
Ogiltig starttid: X = Invalid start time: X Ogiltig starttid: X = Invalid start time: X
Ogiltig tid = Invalid time Ogiltig tid = Invalid time
Ogiltigt bricknummer X = Invalid card number X Ogiltigt bricknummer X = Invalid card number X
@ -753,7 +753,7 @@ Radera tävlingen = Remove Competition
Radera vakanser = Delete Vacancies Radera vakanser = Delete Vacancies
Radiotider, kontroll = Radio times, control Radiotider, kontroll = Radio times, control
Ranking = Ranking Ranking = Ranking
Ranking (IOF, xml) = Ranking (IOF, xml) Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
Rapport inför = Report for Rapport inför = Report for
Rapporter = Reports Rapporter = Reports
Rapportläge = Report Mode Rapportläge = Report Mode
@ -804,7 +804,7 @@ Runner = Competitor
RunnerBib = Competitor's bib RunnerBib = Competitor's bib
RunnerCard = Card number RunnerCard = Card number
RunnerClassCoursePlace = Position on course within class RunnerClassCoursePlace = Position on course within class
RunnerClassCourseTimeAfter = Time after on course within class RunnerClassCourseTimeAfter = Time behind on course within class
RunnerClub = Competitor's club RunnerClub = Competitor's club
RunnerCompleteName = Complete name RunnerCompleteName = Complete name
RunnerCourse = Competitor's course RunnerCourse = Competitor's course
@ -820,17 +820,17 @@ RunnerRank = Ranking
RunnerRogainingPoint = Rogaining points RunnerRogainingPoint = Rogaining points
RunnerStart = Competitor's start time RunnerStart = Competitor's start time
RunnerStartNo = Competitor's start number RunnerStartNo = Competitor's start number
RunnerTempTimeAfter = Competitor's time after at selected control RunnerTempTimeAfter = Competitor's time behind at selected control
RunnerTempTimeStatus = Competitor's time / status at selected control RunnerTempTimeStatus = Competitor's time / status at selected control
RunnerTime = Competitor's time RunnerTime = Competitor's time
RunnerTimeAfter = Competitor's time after RunnerTimeAfter = Competitor's time behind
RunnerTimeAfterDiff = Competitor's time after difference RunnerTimeAfterDiff = Competitor's time behind difference
RunnerTimeLost = Competitor's lost time RunnerTimeLost = Competitor's lost time
RunnerTimePlaceFixed = Time when Competitor's place is set RunnerTimePlaceFixed = Time when Competitor's place is set
RunnerTimeStatus = Competitor's time / status RunnerTimeStatus = Competitor's time / status
RunnerTotalPlace = Competitor's total place RunnerTotalPlace = Competitor's total place
RunnerTotalTime = Competitor's total time RunnerTotalTime = Competitor's total time
RunnerTotalTimeAfter = Competitor's total time after RunnerTotalTimeAfter = Competitor's total time behind
RunnerTotalTimeStatus = Competitor's total time / status RunnerTotalTimeStatus = Competitor's total time / status
RunnerUMMasterPoint = Uppsala möte, master points RunnerUMMasterPoint = Uppsala möte, master points
SI X inläst. Brickan tillhör Y som saknar klass = SI X was read out. The card belongs to Y, who has no class SI X inläst. Brickan tillhör Y som saknar klass = SI X was read out. The card belongs to Y, who has no class
@ -1038,7 +1038,7 @@ Tabelläge = Table Mode
Team = Team Team = Team
TeamBib = Team's bib TeamBib = Team's bib
TeamClub = Team's club TeamClub = Team's club
TeamLegTimeAfter = Team's time after on leg TeamLegTimeAfter = Team's time behind on leg
TeamLegTimeStatus = Team's time / status on leg TeamLegTimeStatus = Team's time / status on leg
TeamName = Team name TeamName = Team name
TeamPlace = Team's place TeamPlace = Team's place
@ -1049,7 +1049,7 @@ TeamStart = Team's start time
TeamStartNo = Team's start number TeamStartNo = Team's start number
TeamStatus = Team status TeamStatus = Team status
TeamTime = Team's time TeamTime = Team's time
TeamTimeAfter = Team's time after TeamTimeAfter = Team's time behind
TeamTimeStatus = Team's time / status TeamTimeStatus = Team's time / status
Telefon = Phone Telefon = Phone
Test = Test Test = Test
@ -1060,9 +1060,9 @@ Text: X = Text: X
Textfiler = Text files Textfiler = Text files
Textstorlek = Text size Textstorlek = Text size
Tid = Time Tid = Time
Tid efter: X = Time after: X Tid efter: X = Time behind: X
Tid efter: X; har tagit in Y = Time after: X; gained Y Tid efter: X; har tagit in Y = Time behind: X; gained Y
Tid efter: X; har tappat Y = Time after: X; lost Y Tid efter: X; har tappat Y = Time behind: X; lost Y
Tid in = Time in Tid in = Time in
Tid: X, nuvarande placering Y/Z = Time: X, current place Y/Z Tid: X, nuvarande placering Y/Z = Time: X, current place Y/Z
Tidsavdrag: X poäng = Point reduction: X points Tidsavdrag: X poäng = Point reduction: X points
@ -1174,7 +1174,7 @@ Varning: deltagare med blankt namn påträffad. MeOS kräver att alla deltagare
Varning: lag utan namn påträffat. MeOS kräver att alla lag har ett namn, och tilldelar namnet 'N.N.' = Warning: A team without name was found. MeOS requires a name and has assigned the name 'N.N.' Varning: lag utan namn påträffat. MeOS kräver att alla lag har ett namn, och tilldelar namnet 'N.N.' = Warning: A team without name was found. MeOS requires a name and has assigned the name 'N.N.'
Verkställ = Apply Verkställ = Apply
Version X = Version X Version X = Version X
Vi stöder MeOS = We support MeOS Vi stöder MeOS = We Support MeOS
Viktiga händelser = Important events Viktiga händelser = Important events
Vill du flytta löpare från X till Y och ta bort Z? = Do you want to move runners from X to Y and remove Z? Vill du flytta löpare från X till Y och ta bort Z? = Do you want to move runners from X to Y and remove Z?
Vill du klistra in X nya rader i tabellen? = Do you want to paste X new rows into the table? Vill du klistra in X nya rader i tabellen? = Do you want to paste X new rows into the table?
@ -1401,7 +1401,7 @@ väntas till X om någon minut, och kan i så fall ta en Y plats = is expected t
väntas till X om någon minut, och kan i så fall ta ledningen = is expected to X in a minute, and can take the lead väntas till X om någon minut, och kan i så fall ta ledningen = is expected to X in a minute, and can take the lead
växeln = the changeover växeln = the changeover
växlar på X plats med tiden Y = changes over as X with time Y växlar på X plats med tiden Y = changes over as X with time Y
växlar på X plats, efter Y, på tiden Z = changes over at a X place, after Y, with time Z växlar på X plats, efter Y, på tiden Z = changes over at a X place, behind Y, with time Z
växlar på delad X plats med tiden Y = changes over as X with time Y växlar på delad X plats med tiden Y = changes over as X with time Y
warn:changedtimezero = Changing the zero time for a competition with results is not recommended.\n\nDo you wish to proceed anyway? warn:changedtimezero = Changing the zero time for a competition with results is not recommended.\n\nDo you wish to proceed anyway?
warn:olddbversion = The database is in use by a later version of MeOS. Upgrading is recommended. warn:olddbversion = The database is in use by a later version of MeOS. Upgrading is recommended.
@ -1506,8 +1506,8 @@ Rogainingresultat - %s = Rogaining results - %s
TeamPlaceDiff = Team's place difference (this stages) TeamPlaceDiff = Team's place difference (this stages)
TeamTotalPlace = Team's summed place (all stages) TeamTotalPlace = Team's summed place (all stages)
TeamTotalTime = Team's summed time (all stages) TeamTotalTime = Team's summed time (all stages)
TeamTotalTimeAfter = Team's summed time after (all stages) TeamTotalTimeAfter = Team's summed time behind (all stages)
TeamTotalTimeDiff = Team's summed time after difference (this stage) TeamTotalTimeDiff = Team's summed time behind difference (this stage)
TeamTotalTimeStatus = Team's summed time or status (all stages) TeamTotalTimeStatus = Team's summed time or status (all stages)
Vill du dumpa aktuellt tävling och skapa en testtävling? = Do you want to dump the current competition and create a test competition? Vill du dumpa aktuellt tävling och skapa en testtävling? = Do you want to dump the current competition and create a test competition?
Radera alla klubbar = Delete All Clubs Radera alla klubbar = Delete All Clubs
@ -1614,7 +1614,7 @@ Höger = Right
PunchControlCode = Control code PunchControlCode = Control code
PunchControlNumber = Punch code PunchControlNumber = Punch code
PunchControlPlace = Place, leg to control PunchControlPlace = Place, leg to control
PunchControlPlaceAcc = Place, total after control PunchControlPlaceAcc = Place, total at control
PunchLostTime = Time lost at control PunchLostTime = Time lost at control
Slå ihop text med föregående = Merge with previous Slå ihop text med föregående = Merge with previous
Textjustering = Text adjustment Textjustering = Text adjustment
@ -1825,7 +1825,7 @@ Status code for not finishing = Status code for not finishing
Status code for not starting = Status code for not starting Status code for not starting = Status code for not starting
Points as computed by your point method = Points as computed by your point method Points as computed by your point method = Points as computed by your point method
Time as computed by your time method = Time as computed by your time method Time as computed by your time method = Time as computed by your time method
Time after leg winner = Time after leg winner Time after leg winner = Time behind leg winner
Finish time for each team member = Finish time for each team member Finish time for each team member = Finish time for each team member
Matched control ids (-1 for unmatched) for each team member = Matched control ids (-1 for unmatched) for each team member Matched control ids (-1 for unmatched) for each team member = Matched control ids (-1 for unmatched) for each team member
Punch codes for each team member = Punch codes for each team member Punch codes for each team member = Punch codes for each team member
@ -1952,7 +1952,7 @@ Hela banan = Entire course
Ogiltigt maximalt intervall = Invalid maximum interval Ogiltigt maximalt intervall = Invalid maximum interval
Startintervallet får inte vara kortare än basintervallet = A start interval may not be shorter than the base interval Startintervallet får inte vara kortare än basintervallet = A start interval may not be shorter than the base interval
Ett startintervall måste vara en multipel av basintervallet = A start interval must be a multiple of the base interval Ett startintervall måste vara en multipel av basintervallet = A start interval must be a multiple of the base interval
Ogiltigt minimalt intervall = Invalid minimal interval Ogiltigt minimalt intervall = Invalid shortest interval
Ogiltigt basintervall = Invalid base interval Ogiltigt basintervall = Invalid base interval
Country = Country Country = Country
CourseShortening = Course shortening CourseShortening = Course shortening
@ -2010,7 +2010,7 @@ Tabellverktyg = Table tools
Antal reserverade nummerlappsnummer mellan klasser = Number of reserved bib numbers between classes Antal reserverade nummerlappsnummer mellan klasser = Number of reserved bib numbers between classes
help:bibs = You can handle bibs automatically or manually. Here you can assign bibs manually for a certain class by specifying the method Manual and provide the first number in the class.\n\nThe method automatic works in the same way, with the difference that MeOS will update the bibs of all classes at once. Although it is possible to make this setting here, it is better to use the Quick settings for classes to get an overview over all classes.\n\nUse the method Automatic together with the methods None or Consecutive, which means that the last number in the preceding class is used as first number. The number of reserved bibs specifies the jump made in the numbering between classes.\n\nFor team classes you can specify how the competitors´ bibs relate to the team´s bib. It can be the Same, Independent, Increasing (Team 1: 101, 102, 103, 104, Team 2: 111, 112, 113, 114 etc) or Leg (100-1, 100-2, 100-3 etc). help:bibs = You can handle bibs automatically or manually. Here you can assign bibs manually for a certain class by specifying the method Manual and provide the first number in the class.\n\nThe method automatic works in the same way, with the difference that MeOS will update the bibs of all classes at once. Although it is possible to make this setting here, it is better to use the Quick settings for classes to get an overview over all classes.\n\nUse the method Automatic together with the methods None or Consecutive, which means that the last number in the preceding class is used as first number. The number of reserved bibs specifies the jump made in the numbering between classes.\n\nFor team classes you can specify how the competitors´ bibs relate to the team´s bib. It can be the Same, Independent, Increasing (Team 1: 101, 102, 103, 104, Team 2: 111, 112, 113, 114 etc) or Leg (100-1, 100-2, 100-3 etc).
RunnerGeneralPlace = Competitor's team's or individual place RunnerGeneralPlace = Competitor's team's or individual place
RunnerGeneralTimeAfter = Competitor's team's or individual time after RunnerGeneralTimeAfter = Competitor's team's or individual time behind
RunnerGeneralTimeStatus = Competitor's team's or individual time / status RunnerGeneralTimeStatus = Competitor's team's or individual time / status
open_error = Failed to open X.\n\nY. open_error = Failed to open X.\n\nY.
open_error_locked = This competition is already open in MeOS.\n\nYou have to use a database to open more than one instance of the competition. open_error_locked = This competition is already open in MeOS.\n\nYou have to use a database to open more than one instance of the competition.
@ -2296,7 +2296,7 @@ help:rest = MeOS REST API lets you access competition data via a web connection.
Server startad på X = Server running on port X Server startad på X = Server running on port X
Inconsistent qualification rule, X = Inconsistent qualification rule, X Inconsistent qualification rule, X = Inconsistent qualification rule, X
help:LockStartList = MeOS will not update assignement to a locked class even if qualification results are altered. help:LockStartList = MeOS will not update assignement to a locked class even if qualification results are altered.
Kval-Final-Schema = Load qualification scheme Kval/final-schema = Qualification/final scheme
Lås startlista = Lock start list Lås startlista = Lock start list
FilterNoCancel = Not cancelled FilterNoCancel = Not cancelled
CourseStartTime = Course, start time CourseStartTime = Course, start time
@ -2321,3 +2321,89 @@ Finish order = Finish order
First to finish = First to finish First to finish = First to finish
Individual result by finish time = Individual result by finish time Individual result by finish time = Individual result by finish time
Endast tidtagning = Only timing Endast tidtagning = Only timing
AllPunches = All punches
CoursePunches = Punches (on course)
FilterNamedControl = Named controls
FilterNotFinish = Exclude finish
LineBreak = Line break
PunchAbsTime = Punch, real time
PunchTimeSinceLast = Time between controls
PunchTotalTime = Time to control
PunchName = Punch, control name
PunchNamedSplit = Time since last named control
PunchSplitTime = Time since last control (split time)
ClassLiveResult = Live results (radio times), class-wise
Felaktigt datum 'X' (Använd YYYY-MM-DD) = Incorrect date 'X' (Use YYYY-MM-DD)
FilterAnyResult = With radio time/result
Liveresultat, radiotider = Live results with radio times
PunchTotalTimeAfter = Time behind at control
RunnerCheck = Time for check punch
RunnerId = Competitor's external ID
StartTimeClass = Start time, class
ask:outofmaps = Out of maps. Do you want to add this competitor anyway?
Varning: Kartorna är slut = Warning: Out of maps
X går vidare, klass enligt ranking = X qualified, class by ranking
Vill du ta bort schemat? = Do you want to remove the scheme?
ask:removescheme = Results are lost if you remove the scheme. Do you wish to continue?
ClassKnockoutTotalResult = Class, knock-out total result
Support intermediate legs = Support specified relay leg
help:custom_text_lines = You can insert custom specific data by typing [Symbol Name]. Available symbols can be seen in the list to the right.\n\n Example: Well done [RunnerName]!
Importerar ranking = Importing ranking
Klart. X värden tilldelade = Complete. Assigned X values.
Felaktigt rankingformat i X. Förväntat: Y = Incorrect ranking format in X.\nExpected: Y
Importerar RAID patrull csv-fil = Importing RAID patrol data
Varning: Följande deltagare har ett osäkert resultat = Warning: The assignments for the following competitors is unclear
Direkt tidtagning = Timekeeping Live
Klassval för 'X' = Class selection for 'X'
Endast tidtagning (utan banor) = Only timekeeping (no courses)
Knockout total = Knock-out summary
Varvräkning = Count laps
Varvräkning med mellantid = Count laps with extra time
Without courses = Without courses
Timekeeping = Timekeeping
Endast grundläggande (enklast möjligt) = Basic functionality only
Endast tidtagning (utan banor), stafett = Only timekeeping (no courses), relay
Individuellt = Individual
Lag och stafett = Team and relay
Övrigt = Miscellaneous
htmlhelp = HTML can be exported as a structured table or as a freely formatted document (more similar to the MeOS lists). You can also use export templates for custom formatting: columns, JavaScript base page flips, automatic scrolling, etc. It is possible to add custom templates by adding '.template' files in MeOS data folder. If you use a template there is a number of parameters to set below. The exact interpretation depends on the template..\n\nIf you select <Store Settings> the list and its settings is stored permanently in the competition. You can then access the list by using MeOS as a web server (The service 'Information Server') or export the list automatically at regular intervals.
HTML Export = HTML Export
HTML Export för 'X' = HTML Export of 'X'
Lagra inställningar = Store settings
Kolumner = Columns
Rader = Rows
HTML formaterad genom listinställningar = HTML formatted by list settings
Begränsa antal rader per sida = Limit rows per page
Färre slingor = Fewer loops
RunnerGrossTime = Competitor's time before adjustment
TeamGrossTime = Team's time before adjustment
Visa detaljerad rapport för viss deltagare = Show a detailed report for a specific competor
Förhindra att laget deltar i någon omstart = Prevent that the team takes part in a restart
Förhindra omstart = Prevent restart
Ej omstart = No restart
Visa rubrik mellan listorna = Show heading between lists
Slå ihop med befintlig lista = Merge with existing list
Från löpardatabasen = From runner database
Från löpardatabasen i befintliga klubbar = From runner database in existing clubs
Med direktanmälan = With direct entry
Tillåt anmälan = Allow Entry
Anyone = Anyone
Bricknummer = Card number
Anmäl andra = New entry
Anmälan mottagen = Accepted entry
Automatisk omladdning = Automatic update
Till vilka klasser = To which classes
Vem får anmäla sig = Who may enter
Anmälan måste hanteras manuellt = Your entry requires manual processing.
EFilterAPIEntry = Entries via API
Visa rubrik = Show title
Rad X är ogiltig = Row X is invalid
Klassen X är listad flera gånger = The class X is listed several times
Ogiltig starttid X = Invalid start time X
Ogiltigt startintervall X = Invalid start interval X
Hittar inte klass X = Cannot X not found
MeOS utvecklinsstöd = MeOS Development Support
info:pageswithcolumns = Show the list one page at the time, with the specified number of columns. Automatically reload data for each round.
Pages with columns = Pages with columns
Pages with columns, no header = Pages with columns, no header
Externa adresser = External links

View File

@ -753,7 +753,7 @@ Radera tävlingen = Supprimer la compétition
Radera vakanser = Supprimer les vacants Radera vakanser = Supprimer les vacants
Radiotider, kontroll = Heures radio, poste Radiotider, kontroll = Heures radio, poste
Ranking = Classement Ranking = Classement
Ranking (IOF, xml) = Classement (IOF, xml) Ranking (IOF, xml, csv) = Classement (IOF, xml, csv)
Rapport inför = Rapport pour Rapport inför = Rapport pour
Rapporter = Rapports Rapporter = Rapports
Rapportläge = Mode rapport Rapportläge = Mode rapport

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2012 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@
************************************************************************/ ************************************************************************/
#pragma once #pragma once
enum gdiFonts { enum gdiFonts {
@ -46,6 +47,7 @@ enum gdiFonts {
const int pageNewPage=100; const int pageNewPage=100;
//const int pageReserveHeight=101; //const int pageReserveHeight=101;
const int pagePageInfo=102; const int pagePageInfo=102;
const int pageNewChapter = 103;
const int textRight=256; const int textRight=256;
const int textCenter=512; const int textCenter=512;

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -102,7 +102,8 @@ EventInfo::EventInfo() : callBack(0), keyEvent(KC_NONE) {}
bool gdioutput::skipTextRender(int format) { bool gdioutput::skipTextRender(int format) {
format &= 0xFF; format &= 0xFF;
return format == pageNewPage || return format == pageNewPage ||
format == pagePageInfo; format == pagePageInfo ||
format == pageNewChapter;
} }
#ifndef MEOSDB #ifndef MEOSDB
@ -117,6 +118,7 @@ gdioutput::gdioutput(const string &_tag, double _scale) :
isTestMode = false; isTestMode = false;
} }
extern gdioutput *gdi_main;
gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) : gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) :
recorder((Recorder *)0, false) { recorder((Recorder *)0, false) {
@ -125,8 +127,12 @@ gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) :
tabs = 0; tabs = 0;
setWindow(hWnd); setWindow(hWnd);
constructor(_scale); constructor(_scale);
if (gdi_main) {
isTestMode = false; isTestMode = gdi_main->isTestMode;
if (isTestMode)
cmdAnswers.swap(gdi_main->cmdAnswers);
}
else isTestMode = false;
} }
void gdioutput::constructor(double _scale) void gdioutput::constructor(double _scale)
@ -1559,7 +1565,7 @@ ListBoxInfo &gdioutput::addSelection(int x, int y, const string &id, int width,
lbi.xp=x; lbi.xp=x;
lbi.yp=y; lbi.yp=y;
lbi.width = scale*width; lbi.width = scale*width;
lbi.height = scale*height; lbi.height = scale*30;
lbi.id=id; lbi.id=id;
lbi.callBack=cb; lbi.callBack=cb;
@ -3098,6 +3104,11 @@ bool gdioutput::hasField(const string &id) const
return true; return true;
} }
for (auto &tl : TL) {
if (tl.id == id)
return true;
}
return false; return false;
} }
@ -3651,8 +3662,8 @@ void gdioutput::refreshSmartFromSnapshot(bool allowMoveOffset) {
} }
} }
int maxOffsetY=max<int>(GetPageY()-clientRC.bottom, 0); int maxOffsetY=max<int>(getPageY()-clientRC.bottom, 0);
int maxOffsetX=max<int>(GetPageX()-clientRC.right, 0); int maxOffsetX=max<int>(getPageX()-clientRC.right, 0);
int noy = OffsetY - offset.second; int noy = OffsetY - offset.second;
int nox = OffsetX - offset.first; int nox = OffsetX - offset.first;
if ((offset.first != 0 && nox>0 && nox<maxOffsetX) || (offset.second != 0 && noy>0 && noy<maxOffsetY) ) { if ((offset.first != 0 && nox>0 && nox<maxOffsetX) || (offset.second != 0 && noy>0 && noy<maxOffsetY) ) {
@ -5215,8 +5226,8 @@ bool gdioutput::clipOffset(int PageX, int PageY, int &MaxOffsetX, int &MaxOffset
int oy=OffsetY; int oy=OffsetY;
int ox=OffsetX; int ox=OffsetX;
MaxOffsetY=max(GetPageY()-PageY, 0); MaxOffsetY=max(getPageY()-PageY, 0);
MaxOffsetX=max(GetPageX()-PageX, 0); MaxOffsetX=max(getPageX()-PageX, 0);
if (OffsetY<0) OffsetY=0; if (OffsetY<0) OffsetY=0;
else if (OffsetY>MaxOffsetY) else if (OffsetY>MaxOffsetY)
@ -5856,7 +5867,7 @@ int gdioutput::setHighContrastMaxWidth() {
OutputDebugString("Set high contrast\n"); OutputDebugString("Set high contrast\n");
#endif #endif
double w = GetPageX(); double w = getPageX();
double s = rc.right / w; double s = rc.right / w;
if (!highContrast || (fabs(s-1.0) > 1e-3 && (s * scale) >= 1.0) ) { if (!highContrast || (fabs(s-1.0) > 1e-3 && (s * scale) >= 1.0) ) {
lockRefresh = true; lockRefresh = true;
@ -6441,12 +6452,18 @@ const string &gdioutput::recodeToNarrow(const wstring &input) {
return output; return output;
} }
/*
const string &gdioutput::toUTF8(const string &input) const {
return toUTF8(toWide(input));
}*/
const string &gdioutput::toUTF8(const wstring &winput) const { const wstring &gdioutput::fromUTF8(const string &input) {
wstring &output = StringCache::getInstance().wget();
size_t alloc = input.length() + 1;
output.resize(alloc);
wchar_t *ptr = &output[0];
int wlen = MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.length(), ptr, alloc);
ptr[wlen] = 0;
output.resize(wlen);
return output;
}
const string &gdioutput::toUTF8(const wstring &winput) {
string &output = StringCache::getInstance().get(); string &output = StringCache::getInstance().get();
size_t alloc = winput.length()*4+32; size_t alloc = winput.length()*4+32;
output.resize(alloc); output.resize(alloc);
@ -6957,3 +6974,21 @@ AutoCompleteInfo &gdioutput::addAutoComplete(const string &key) {
void gdioutput::clearAutoComplete(const string &key) { void gdioutput::clearAutoComplete(const string &key) {
autoCompleteInfo.reset(); autoCompleteInfo.reset();
} }
int gdioutput::getPageY() const {
if (hideBG || backgroundColor1 != -1)
return max(MaxY, 100);
else
return max(MaxY, 100) + scaleLength(60);
}
int gdioutput::getPageX() const {
int xlimit = 100;
for (auto &b : BI)
xlimit = max(b.xp + b.width, xlimit);
if (hideBG || backgroundColor1 != -1 || xlimit >= MaxX)
return max(MaxX, xlimit);
else
return max(MaxX, xlimit) + scaleLength(60);
}

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -122,7 +122,7 @@ protected:
bool startDoc(PrinterObject &po); bool startDoc(PrinterObject &po);
bool getSelectedItem(ListBoxInfo &lbi); bool getSelectedItem(ListBoxInfo &lbi);
bool doPrint(PrinterObject &po, PageInfo &pageInfo, pEvent oe); bool doPrint(PrinterObject &po, PageInfo &pageInfo, pEvent oe, bool respectPageBreak);
PrinterObject *po_default; PrinterObject *po_default;
@ -329,7 +329,8 @@ public:
static const wstring &widen(const string &input); static const wstring &widen(const string &input);
static const string &narrow(const wstring &input); static const string &narrow(const wstring &input);
const string &toUTF8(const wstring &input) const; static const string &toUTF8(const wstring &input);
static const wstring &fromUTF8(const string &input);
//void setEncoding(FontEncoding encoding); //void setEncoding(FontEncoding encoding);
//FontEncoding getEncoding() const; //FontEncoding getEncoding() const;
@ -400,16 +401,8 @@ public:
void disableTables(); void disableTables();
void pasteText(const char *id); void pasteText(const char *id);
void print(pEvent oe, Table *t = 0, bool printMeOSHeader = true, bool noMargin = false, bool respectPageBreak = true);
bool writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const; void print(PrinterObject &po, pEvent oe, bool printMeOSHeader = true, bool noMargin=false, bool respectPageBreak = true);
bool writeTableHTML(const wstring &file, const wstring &title, int refreshTimeOut) const;
bool writeTableHTML(ostream &fout,
const wstring &title,
bool simpleFormat,
int refreshTimeOut) const;
void print(pEvent oe, Table *t=0, bool printMeOSHeader=true, bool noMargin=false);
void print(PrinterObject &po, pEvent oe, bool printMeOSHeader=true, bool noMargin=false);
void printSetup(PrinterObject &po); void printSetup(PrinterObject &po);
void destroyPrinterDC(PrinterObject &po); void destroyPrinterDC(PrinterObject &po);
@ -488,12 +481,12 @@ public:
void updateScrollbars() const; void updateScrollbars() const;
void SetOffsetY(int oy){OffsetY=oy;} void setOffsetY(int oy) {OffsetY=oy;}
void SetOffsetX(int ox){OffsetX=ox;} void setOffsetX(int ox) {OffsetX=ox;}
int GetPageY(){return max(MaxY, 100)+60;} int getPageY() const;
int GetPageX(){return max(MaxX, 100)+100;} int getPageX() const;
int GetOffsetY(){return OffsetY;} int getOffsetY() const {return OffsetY;}
int GetOffsetX(){return OffsetX;} int getOffsetX() const {return OffsetX;}
void RenderString(TextInfo &ti, const wstring &text, HDC hDC); void RenderString(TextInfo &ti, const wstring &text, HDC hDC);
void RenderString(TextInfo &ti, HDC hDC=0); void RenderString(TextInfo &ti, HDC hDC=0);
@ -753,7 +746,7 @@ public:
void setDBErrorState(bool state); void setDBErrorState(bool state);
friend int TablesCB(gdioutput *gdi, int type, void *data); friend int TablesCB(gdioutput *gdi, int type, void *data);
friend class Table; friend class Table;
friend gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y); friend gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y, bool fixedSize);
gdioutput(const string &tag, double _scale); gdioutput(const string &tag, double _scale);
gdioutput(double _scale, HWND hWndTarget, const PrinterObject &defprn); gdioutput(double _scale, HWND hWndTarget, const PrinterObject &defprn);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -154,7 +154,7 @@ public:
TextInfo &changeFont(const wstring &fnt) {font = fnt; return *this;} //Note: size not updated TextInfo &changeFont(const wstring &fnt) {font = fnt; return *this;} //Note: size not updated
bool isFormatInfo() const { return format == pageNewPage || format == pagePageInfo; } bool isFormatInfo() const { return format == pageNewPage || format == pagePageInfo || format == pageNewChapter; }
int getHeight() {return int(textRect.bottom-textRect.top);} int getHeight() {return int(textRect.bottom-textRect.top);}
gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);} gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);}

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1017,8 +1017,8 @@ void DynamicResult::getSymbolInfo(int ix, wstring &name, wstring &desc) const {
void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const { void DynamicResult::prepareCalculations(oEvent &oe, bool prepareForTeam, int inputNumber) const {
compile(false); compile(false);
oe.calculateResults(oEvent::RTClassResult); oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult);
oe.calculateResults(oEvent::RTTotalResult); oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult);
declareSymbols(MRScore, true); declareSymbols(MRScore, true);
if (prepareForTeam) { if (prepareForTeam) {
@ -1344,7 +1344,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
controlId.first == oPunch::PunchStart) { controlId.first == oPunch::PunchStart) {
if (!totalResults) { if (!totalResults) {
oe.calculateResults(oEvent::RTClassResult, true); oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult, true);
for (pRunner r : runners) { for (pRunner r : runners) {
ri.status = r->getStatus(); ri.status = r->getStatus();
if (ri.status == StatusUnknown) { if (ri.status == StatusUnknown) {
@ -1373,7 +1373,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
} }
} }
else { else {
oe.calculateResults(oEvent::RTTotalResult, true); oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult, true);
for (pRunner r : runners) { for (pRunner r : runners) {
ri.status = r->getTotalStatus(); ri.status = r->getTotalStatus();
if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) { if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) {

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -539,7 +539,7 @@ Radera tävlingen = Wettkampf löschen
Radera vakanser = Vakantplätze löschen Radera vakanser = Vakantplätze löschen
Radiotider, kontroll = Funkposten-Zeiten, Posten Radiotider, kontroll = Funkposten-Zeiten, Posten
Ranking = Ranking Ranking = Ranking
Ranking (IOF, xml) = Ranking (IOF, xml) Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
Rapport inför = Bericht für Rapport inför = Bericht für
Rapporter = Berichte Rapporter = Berichte
Redigera deltagaren = Teilnehmer bearbeiten Redigera deltagaren = Teilnehmer bearbeiten

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,3 +1,4 @@
<image source="/meos?image=meos"><br>
<h1>Documentation of MeOS REST API</h1> <h1>Documentation of MeOS REST API</h1>
<h2>Competition</h2> <h2>Competition</h2>

View File

@ -1,4 +1,26 @@
#include "stdafx.h" /************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#include "stdafx.h"
#include "image.h" #include "image.h"
#include "png/png.h" #include "png/png.h"
#include <vector> #include <vector>

View File

@ -1,4 +1,26 @@
#pragma once /************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#pragma once
#include <map> #include <map>
#include <vector> #include <vector>
@ -12,8 +34,6 @@ public:
private: private:
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
static HBITMAP read_png_file(const wstring &filename, int &width, int &height, ImageMethod method); static HBITMAP read_png_file(const wstring &filename, int &width, int &height, ImageMethod method);
static HBITMAP read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method); static HBITMAP read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method);
static HBITMAP read_png(vector<uint8_t> &data, int &width, int &height, ImageMethod method); static HBITMAP read_png(vector<uint8_t> &data, int &width, int &height, ImageMethod method);
@ -31,6 +51,8 @@ public:
HBITMAP loadImage(int resource, ImageMethod method); HBITMAP loadImage(int resource, ImageMethod method);
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
int getWidth(int resource); int getWidth(int resource);
int getHeight(int resource); int getHeight(int resource);
void drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height); void drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height);

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2017 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -109,7 +109,7 @@ InfoTeam::InfoTeam(int id) : InfoBaseCompetitor(id) {
} }
bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &includeCls, const set<int> &ctrls) { bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &includeCls, const set<int> &ctrls, bool allowDeletion) {
bool changed = false; bool changed = false;
if (oe.getName() != name) { if (oe.getName() != name) {
name = oe.getName(); name = oe.getName();
@ -170,6 +170,8 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
vector<pClass> cls; vector<pClass> cls;
oe.getClasses(cls, false); oe.getClasses(cls, false);
for (size_t k = 0; k < cls.size(); k++) { for (size_t k = 0; k < cls.size(); k++) {
if (cls[k]->getQualificationFinal())
continue;
int wid = cls[k]->getId(); int wid = cls[k]->getId();
if (!includeCls.count(wid)) if (!includeCls.count(wid))
continue; continue;
@ -207,7 +209,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
// Check if something was deleted // Check if something was deleted
for (map<int, InfoOrganization>::iterator it = organizations.begin(); it != organizations.end();) { for (map<int, InfoOrganization>::iterator it = organizations.begin(); it != organizations.end();) {
if (!knownId.count(it->first)) { if (!knownId.count(it->first)) {
int oid = it->first;
organizations.erase(it++); organizations.erase(it++);
if (allowDeletion)
deleteMap.emplace_back("org", oid);
else
forceComplete = true; forceComplete = true;
} }
else else
@ -218,8 +225,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
vector<pTeam> t; vector<pTeam> t;
oe.getTeams(0, t, false); oe.getTeams(0, t, false);
for (size_t k = 0; k < t.size(); k++) { for (size_t k = 0; k < t.size(); k++) {
if (!includeCls.count(t[k]->getClassId(true))) int cid = t[k]->getClassId(true);
if (!includeCls.count(cid))
continue; continue;
if (cid != 0 && t[k]->getClassRef(false)->getQualificationFinal() != nullptr)
continue;
int wid = t[k]->getId(); int wid = t[k]->getId();
knownId.insert(wid); knownId.insert(wid);
map<int, InfoTeam>::iterator res = teams.find(wid); map<int, InfoTeam>::iterator res = teams.find(wid);
@ -232,7 +243,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
// Check if something was deleted // Check if something was deleted
for (map<int, InfoTeam>::iterator it = teams.begin(); it != teams.end();) { for (map<int, InfoTeam>::iterator it = teams.begin(); it != teams.end();) {
if (!knownId.count(it->first)) { if (!knownId.count(it->first)) {
int tid = it->first;
teams.erase(it++); teams.erase(it++);
if (allowDeletion)
deleteMap.emplace_back("tm", tid);
else
forceComplete = true; forceComplete = true;
} }
else else
@ -243,8 +259,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
vector<pRunner> r; vector<pRunner> r;
oe.getRunners(0, 0, r, false); oe.getRunners(0, 0, r, false);
for (size_t k = 0; k < r.size(); k++) { for (size_t k = 0; k < r.size(); k++) {
if (!includeCls.count(r[k]->getClassId(true))) int cid = r[k]->getClassId(true);
if (!includeCls.count(cid))
continue; continue;
if (cid != 0 && r[k]->getClassRef(true)->getQualificationFinal() != nullptr)
continue;
int wid = r[k]->getId(); int wid = r[k]->getId();
knownId.insert(wid); knownId.insert(wid);
map<int, InfoCompetitor>::iterator res = competitors.find(wid); map<int, InfoCompetitor>::iterator res = competitors.find(wid);
@ -257,7 +277,11 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
// Check if something was deleted // Check if something was deleted
for (map<int, InfoCompetitor>::iterator it = competitors.begin(); it != competitors.end();) { for (map<int, InfoCompetitor>::iterator it = competitors.begin(); it != competitors.end();) {
if (!knownId.count(it->first)) { if (!knownId.count(it->first)) {
int rid = it->first;
competitors.erase(it++); competitors.erase(it++);
if (allowDeletion)
deleteMap.emplace_back("cmp", rid);
else
forceComplete = true; forceComplete = true;
} }
else else
@ -265,7 +289,7 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
} }
knownId.clear(); knownId.clear();
return !toCommit.empty() || forceComplete; return !toCommit.empty() || forceComplete || !deleteMap.empty();
} }
void InfoCompetition::needCommit(InfoBase &obj) { void InfoCompetition::needCommit(InfoBase &obj) {
@ -499,7 +523,8 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &r) { bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &r) {
bool ch = synchronizeBase(r); bool ch = synchronizeBase(r);
changeTotalSt = r.getEvent()->hasPrevStage() || r.getLegNumber()>0; // Always write full attributes bool isQF = r.getClassRef(false) && r.getClassRef(false)->getQualificationFinal() != nullptr;
changeTotalSt = r.getEvent()->hasPrevStage() || (r.getLegNumber()>0 && !isQF); // Always write full attributes
int s = StatusOK; int s = StatusOK;
int legInput = 0; int legInput = 0;
@ -521,7 +546,7 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
legInput = r.getTotalTimeInput() * 10; legInput = r.getTotalTimeInput() * 10;
s = r.getTotalStatusInput(); s = r.getTotalStatusInput();
} }
else if (t && r.getLegNumber() > 0) { else if (t && !isQF && r.getLegNumber() > 0) {
legInput = t->getLegRunningTime(r.getLegNumber() - 1, false) * 10; legInput = t->getLegRunningTime(r.getLegNumber() - 1, false) * 10;
s = t->getLegStatus(r.getLegNumber() - 1, false); s = t->getLegStatus(r.getLegNumber() - 1, false);
} }
@ -549,7 +574,7 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
vector<RadioTime> newRT; vector<RadioTime> newRT;
if (r.getClassId(false) > 0) { if (r.getClassId(false) > 0) {
const vector<int> &radios = cmp.getControls(r.getClassId(false), r.getLegNumber()); const vector<int> &radios = cmp.getControls(r.getClassId(true), r.getLegNumber());
for (size_t k = 0; k < radios.size(); k++) { for (size_t k = 0; k < radios.size(); k++) {
RadioTime radioTime; RadioTime radioTime;
RunnerStatus s_split; RunnerStatus s_split;
@ -693,12 +718,21 @@ void InfoCompetition::getDiffXML(xmlbuffer &xml) {
return; return;
} }
xml.setComplete(false); xml.setComplete(false);
vector<pair<string, wstring>> prop = { make_pair("id", L""), make_pair("delete", L"true") };
for (auto &dm : deleteMap) {
prop[0].second = itow(dm.second);
xml.startTag(dm.first.c_str(), prop);
xml.endTag();
}
for (list<InfoBase *>::iterator it = toCommit.begin(); it != toCommit.end(); ++it) { for (list<InfoBase *>::iterator it = toCommit.begin(); it != toCommit.end(); ++it) {
(*it)->serialize(xml, true); (*it)->serialize(xml, true);
} }
} }
void InfoCompetition::commitComplete() { void InfoCompetition::commitComplete() {
deleteMap.clear();
toCommit.clear(); toCommit.clear();
forceComplete = false; forceComplete = false;
} }
@ -767,8 +801,6 @@ void xmlbuffer::write(const char *tag,
blocks.back().value = value; blocks.back().value = value;
} }
void xmlbuffer::startXML(xmlparser &xml, const wstring &dest) { void xmlbuffer::startXML(xmlparser &xml, const wstring &dest) {
xml.openOutput(dest.c_str(), false); xml.openOutput(dest.c_str(), false);
if (complete) { if (complete) {

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -227,6 +227,7 @@ protected:
map<int, InfoOrganization> organizations; map<int, InfoOrganization> organizations;
map<int, InfoCompetitor> competitors; map<int, InfoCompetitor> competitors;
map<int, InfoTeam> teams; map<int, InfoTeam> teams;
vector<pair<string, int>> deleteMap;
void needCommit(InfoBase &obj); void needCommit(InfoBase &obj);
@ -240,10 +241,10 @@ protected:
void includeCourse(bool inc) { withCourse = inc; } void includeCourse(bool inc) { withCourse = inc; }
const vector<int> &getControls(int classId, int legNumber) const; const vector<int> &getControls(int classId, int legNumber) const;
bool synchronize(oEvent &oe, bool onlyCmp, const set<int> &classes, const set<int> &ctrls); bool synchronize(oEvent &oe, bool onlyCmp, const set<int> &classes, const set<int> &ctrls, bool allowDeletion);
bool synchronize(oEvent &oe) { bool synchronize(oEvent &oe) {
set<int> dmy; set<int> dmy;
return synchronize(oe, true, dmy, dmy); return synchronize(oe, true, dmy, dmy, false);
} }
void getCompleteXML(xmlbuffer &xml); void getCompleteXML(xmlbuffer &xml);
void getDiffXML(xmlbuffer &xml); void getDiffXML(xmlbuffer &xml);

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,8 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2015 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -18,10 +17,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu Melin Software HB - software@melin.nu - www.melin.nu
Stigbergsvägen 7, SE-75242 UPPSALA, Sweden Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/ ************************************************************************/
template<class T, class KEY = int> class intkeymap { template<class T, class KEY = int> class intkeymap {
private: private:
const static KEY NoKey = -1013; const static KEY NoKey = -1013;

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2015 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -18,10 +18,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu Melin Software HB - software@melin.nu - www.melin.nu
Stigbergsvägen 7, SE-75242 UPPSALA, Sweden Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/ ************************************************************************/
#include "stdafx.h" #include "stdafx.h"
#include "intkeymap.hpp" #include "intkeymap.hpp"

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -156,7 +156,7 @@ void IOF30Interface::classCourseAssignment(gdioutput &gdi, xmlList &xAssignment,
wstring cname; wstring cname;
xClsAssignment.getObjectString("ClassName", cname); xClsAssignment.getObjectString("ClassName", cname);
if (cname.length() > 0) { if (cname.length() > 0) {
pClass pc = oe.getClassCreate(0, cname); pClass pc = oe.getClassCreate(0, cname, matchedClasses);
if (pc) if (pc)
cls2Stages.insert(make_pair(pc->getId(), vector<int>()) ); cls2Stages.insert(make_pair(pc->getId(), vector<int>()) );
} }
@ -510,7 +510,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
wstring cName; wstring cName;
xCls[j].getObjectString("Name", cName); xCls[j].getObjectString("Name", cName);
int id = xCls[j].getObjectInt("Id"); int id = xCls[j].getObjectInt("Id");
pClass cls = oe.getClassCreate(id, cName); pClass cls = oe.getClassCreate(id, cName, matchedClasses);
if (cls) { if (cls) {
class2Courses[cls->getId()].push_back(pc); class2Courses[cls->getId()].push_back(pc);
@ -2314,7 +2314,8 @@ void IOF30Interface::setupRelayClasses(const map<int, vector<LegInfo> > &teamCla
if (classId > 0) { if (classId > 0) {
pClass pc = oe.getClass(classId); pClass pc = oe.getClass(classId);
if (!pc) { if (!pc) {
pc = oe.getClassCreate(classId, L"tmp" + itow(classId)); set<wstring> dmy;
pc = oe.getClassCreate(classId, L"tmp" + itow(classId), dmy);
} }
setupRelayClass(pc, legs); setupRelayClass(pc, legs);
} }
@ -2732,13 +2733,13 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
xml.endTag(); xml.endTag();
} }
bool doUnroll = unrollLoops && r.getNumShortening() == 0;
pCourse crs = r.getCourse(!unrollLoops); pCourse crs = r.getCourse(!doUnroll);
if (crs) { if (crs) {
if (includeCourse) if (includeCourse)
writeCourse(xml, *crs); writeCourse(xml, *crs);
const vector<SplitData> &sp = r.getSplitTimes(unrollLoops); const vector<SplitData> &sp = r.getSplitTimes(doUnroll);
if (r.getStatus()>0 && r.getStatus() != StatusDNS && if (r.getStatus()>0 && r.getStatus() != StatusDNS &&
r.getStatus() != StatusCANCEL && r.getStatus() != StatusCANCEL &&
r.getStatus() != StatusNotCompetiting) { r.getStatus() != StatusNotCompetiting) {

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -65,6 +65,8 @@ class IOF30Interface {
bool includeStageRaceInfo; bool includeStageRaceInfo;
void operator=(const IOF30Interface &); void operator=(const IOF30Interface &);
set<wstring> matchedClasses;
struct LegInfo { struct LegInfo {
int maxRunners; int maxRunners;
int minRunners; int minRunners;

View File

@ -7,7 +7,7 @@ Third Party Code. Additional copyright notices and license terms applicable to p
All trademarks and registered trademarks mentioned herein are the property of their respective owners. All trademarks and registered trademarks mentioned herein are the property of their respective owners.
------------------------------------ ------------------------------------
Copyright 2007-2017 Melin Software HB. Copyright 2007-2019 Melin Software HB.
------------------------------------ ------------------------------------

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1069,6 +1069,7 @@ void ListEditor::editListProp(gdioutput &gdi, bool newList) {
xp = x1 + margin; xp = x1 + margin;
gdi.setCX(xp); gdi.setCX(xp);
yp += int(1.3 * gdi.getLineHeight()); yp += int(1.3 * gdi.getLineHeight());
gdi.dropLine(1.3);
} }
} }

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/********************i**************************************************** /********************i****************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -91,8 +91,7 @@ void LiveResult::showTimer(gdioutput &gdi, const oListInfo &liIn) {
lastTime = 0; lastTime = 0;
vector<const oFreePunch *> pp; vector<const oFreePunch *> pp;
oe->synchronizeList(oLRunnerId, true, false); oe->synchronizeList({ oListId::oLRunnerId, oListId::oLPunchId });
oe->synchronizeList(oLPunchId, false, true);
oe->getLatestPunches(lastTime, pp); oe->getLatestPunches(lastTime, pp);
processedPunches.clear(); processedPunches.clear();

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -249,7 +249,7 @@ const wstring &LocalizerImpl::translate(const wstring &str, bool &found)
return value[i]; return value[i];
} }
#ifdef _DEBUG #ifdef _DEBUG
if (key.length() > 1) if (key.length() > 1 && _wtoi(key.c_str()) == 0)
unknown[key] = L""; unknown[key] = L"";
#endif #endif

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -154,9 +154,9 @@ void LoadPage(gdioutput &gdi, TabType type) {
// Path to settings file // Path to settings file
static wchar_t settings[260]; static wchar_t settings[260];
// Startup path // Startup path
static wchar_t programPath[MAX_PATH]; wchar_t programPath[MAX_PATH];
// Exe path // Exe path
static wchar_t exePath[MAX_PATH]; wchar_t exePath[MAX_PATH];
void mainMessageLoop(HACCEL hAccelTable, DWORD time) { void mainMessageLoop(HACCEL hAccelTable, DWORD time) {
@ -830,7 +830,7 @@ gdioutput *getExtraWindow(const string &tag, bool toForeGround) {
return 0; return 0;
} }
gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y) { gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x, int max_y, bool fixedSize) {
if (getExtraWindow(tag, false) != 0) if (getExtraWindow(tag, false) != 0)
throw meosException("Window already exists"); throw meosException("Window already exists");
@ -847,21 +847,30 @@ gdioutput *createExtraWindow(const string &tag, const wstring &title, int max_x,
for (size_t k = 0; k<gdi_extra.size(); k++) { for (size_t k = 0; k<gdi_extra.size(); k++) {
if (gdi_extra[k]) { if (gdi_extra[k]) {
HWND hWnd = gdi_extra[k]->getHWNDTarget(); HWND hWnd = gdi_extra[k]->getHWNDTarget();
RECT rc; RECT rcc;
if (GetWindowRect(hWnd, &rc)) { if (GetWindowRect(hWnd, &rcc)) {
xp = max<int>(rc.left + 16, xp); xp = max<int>(rcc.left + 16, xp);
yp = max<int>(rc.top + 32, yp); yp = max<int>(rcc.top + 32, yp);
} }
} }
} }
int xs = gEvent->getPropertyInt("xsize", max(850, min(int(rc.right)-yp, 1124))); if (xp > rc.right - 100)
int ys = gEvent->getPropertyInt("ysize", max(650, min(int(rc.bottom)-yp-40, 800))); xp = rc.right - 100;
if (max_x>0) if (yp > rc.bottom - 100)
yp = rc.bottom - 100;
int xs = max_x, ys = max_y;
if (!fixedSize) {
xs = gEvent->getPropertyInt("xsize", max(850, min(int(rc.right) - yp, 1124)));
ys = gEvent->getPropertyInt("ysize", max(650, min(int(rc.bottom) - yp - 40, 800)));
if (max_x > 0)
xs = min(max_x, xs); xs = min(max_x, xs);
if (max_y>0) if (max_y > 0)
ys = min(max_y, ys); ys = min(max_y, ys);
}
hWnd = CreateWindowEx(0, szWorkSpaceClass, title.c_str(), hWnd = CreateWindowEx(0, szWorkSpaceClass, title.c_str(),
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
@ -944,7 +953,8 @@ void InsertSICard(gdioutput &gdi, SICard &sic);
//static int xPos=0, yPos=0; //static int xPos=0, yPos=0;
void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker, void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
bool skipEconomy, bool skipLists, bool skipRunners, bool skipControls) bool skipEconomy, bool skipLists,
bool skipRunners, bool skipCourses, bool skipControls)
{ {
static bool onlyMainP = false; static bool onlyMainP = false;
static bool skipTeamP = false; static bool skipTeamP = false;
@ -952,11 +962,12 @@ void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
static bool skipEconomyP = false; static bool skipEconomyP = false;
static bool skipListsP = false; static bool skipListsP = false;
static bool skipRunnersP = false; static bool skipRunnersP = false;
static bool skipCoursesP = false;
static bool skipControlsP = false; static bool skipControlsP = false;
if (!force && onlyMain==onlyMainP && skipTeam==skipTeamP && skipSpeaker==skipSpeakerP && if (!force && onlyMain==onlyMainP && skipTeam==skipTeamP && skipSpeaker==skipSpeakerP &&
skipEconomy==skipEconomyP && skipLists==skipListsP && skipEconomy==skipEconomyP && skipLists==skipListsP &&
skipRunners==skipRunnersP && skipControls==skipControlsP) skipRunners==skipRunnersP && skipControls==skipControlsP && skipCourses == skipCoursesP)
return; return;
onlyMainP = onlyMain; onlyMainP = onlyMain;
@ -965,6 +976,7 @@ void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
skipEconomyP = skipEconomy; skipEconomyP = skipEconomy;
skipListsP = skipLists; skipListsP = skipLists;
skipRunnersP = skipRunners; skipRunnersP = skipRunners;
skipCoursesP = skipCourses;
skipControlsP = skipControls; skipControlsP = skipControls;
int oldid=TabCtrl_GetCurSel(hMainTab); int oldid=TabCtrl_GetCurSel(hMainTab);
@ -996,6 +1008,9 @@ void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
if (skipRunners && it->getType() == typeid(TabRunner)) if (skipRunners && it->getType() == typeid(TabRunner))
continue; continue;
if (skipCourses && it->getType() == typeid(TabCourse))
continue;
if (skipControls && it->getType() == typeid(TabControl)) if (skipControls && it->getType() == typeid(TabControl))
continue; continue;
@ -1055,7 +1070,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
ic.dwICC=ICC_TAB_CLASSES ; ic.dwICC=ICC_TAB_CLASSES ;
InitCommonControlsEx(&ic); InitCommonControlsEx(&ic);
hMainTab=CreateWindowEx(0, WC_TABCONTROL, L"tabs", WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, 0, 0, 300, 20, hWnd, 0, hInst, 0); hMainTab=CreateWindowEx(0, WC_TABCONTROL, L"tabs", WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS, 0, 0, 300, 20, hWnd, 0, hInst, 0);
createTabs(true, true, false, false, false, false, false, false); createTabs(true, true, false, false, false, false, false, false, false);
SetTimer(hWnd, 4, 10000, 0); //Connection check SetTimer(hWnd, 4, 10000, 0); //Connection check
break; break;
@ -1278,7 +1293,7 @@ void scrollVertical(gdioutput *gdi, int yInc, HWND hWnd) {
if (si.nPage==0) if (si.nPage==0)
yInc = 0; yInc = 0;
int yPos=gdi->GetOffsetY(); int yPos=gdi->getOffsetY();
int a=si.nMax-signed(si.nPage-1) - yPos; int a=si.nMax-signed(si.nPage-1) - yPos;
if ( (yInc = max( -yPos, min(yInc, a)))!=0 ) { if ( (yInc = max( -yPos, min(yInc, a)))!=0 ) {
@ -1289,9 +1304,9 @@ void scrollVertical(gdioutput *gdi, int yInc, HWND hWnd) {
ScrollArea.top=-gdi->getHeight()-100; ScrollArea.top=-gdi->getHeight()-100;
ScrollArea.bottom+=gdi->getHeight(); ScrollArea.bottom+=gdi->getHeight();
ScrollArea.right=gdi->getWidth()-gdi->GetOffsetX()+15; ScrollArea.right=gdi->getWidth()-gdi->getOffsetX()+15;
ScrollArea.left = -2000; ScrollArea.left = -2000;
gdi->SetOffsetY(yPos); gdi->setOffsetY(yPos);
bool inv = true; //Inv = false works only for lists etc. where there are not controls in the scroll area. bool inv = true; //Inv = false works only for lists etc. where there are not controls in the scroll area.
@ -1331,7 +1346,7 @@ void updateScrollInfo(HWND hWnd, gdioutput &gdi, int nHeight, int nWidth) {
if (maxy>0) { if (maxy>0) {
si.nMax=maxy+nHeight; si.nMax=maxy+nHeight;
si.nPos=gdi.GetOffsetY(); si.nPos=gdi.getOffsetY();
si.nPage=nHeight; si.nPage=nHeight;
} }
else { else {
@ -1344,7 +1359,7 @@ void updateScrollInfo(HWND hWnd, gdioutput &gdi, int nHeight, int nWidth) {
si.nMin=0; si.nMin=0;
if (maxx>0) { if (maxx>0) {
si.nMax=maxx+nWidth; si.nMax=maxx+nWidth;
si.nPos=gdi.GetOffsetX(); si.nPos=gdi.getOffsetX();
si.nPage=nWidth; si.nPage=nWidth;
} }
else { else {
@ -1431,7 +1446,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
//int hwndScrollBar = (HWND) lParam; // handle to scroll bar //int hwndScrollBar = (HWND) lParam; // handle to scroll bar
int yInc; int yInc;
int yPos=gdi->GetOffsetY(); int yPos=gdi->getOffsetY();
RECT rc; RECT rc;
GetClientRect(hWnd, &rc); GetClientRect(hWnd, &rc);
int pagestep = max(50, int(0.9*rc.bottom)); int pagestep = max(50, int(0.9*rc.bottom));
@ -1478,7 +1493,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
} }
scrollVertical(gdi, yInc, hWnd); scrollVertical(gdi, yInc, hWnd);
gdi->storeAutoPos(gdi->GetOffsetY()); gdi->storeAutoPos(gdi->getOffsetY());
break; break;
} }
@ -1488,7 +1503,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
//int hwndScrollBar = (HWND) lParam; // handle to scroll bar //int hwndScrollBar = (HWND) lParam; // handle to scroll bar
int xInc; int xInc;
int xPos=gdi->GetOffsetX(); int xPos=gdi->getOffsetX();
switch(nScrollCode) switch(nScrollCode)
{ {
@ -1552,7 +1567,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
GetClientRect(hWnd, &ScrollArea); GetClientRect(hWnd, &ScrollArea);
ClipArea=ScrollArea; ClipArea=ScrollArea;
gdi->SetOffsetX(xPos); gdi->setOffsetX(xPos);
ScrollWindowEx (hWnd, -xInc, 0, ScrollWindowEx (hWnd, -xInc, 0,
0, &ClipArea, 0, &ClipArea,
@ -1571,7 +1586,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
case WM_MOUSEWHEEL: { case WM_MOUSEWHEEL: {
int dz = GET_WHEEL_DELTA_WPARAM(wParam); int dz = GET_WHEEL_DELTA_WPARAM(wParam);
scrollVertical(gdi, -dz, hWnd); scrollVertical(gdi, -dz, hWnd);
gdi->storeAutoPos(gdi->GetOffsetY()); gdi->storeAutoPos(gdi->getOffsetY());
} }
break; break;

View File

@ -169,7 +169,7 @@ BEGIN
VALUE "FileDescription", "meos" VALUE "FileDescription", "meos"
VALUE "FileVersion", "3.3.0.1" VALUE "FileVersion", "3.3.0.1"
VALUE "InternalName", "meos" VALUE "InternalName", "meos"
VALUE "LegalCopyright", "Copyright © 2007-2018" VALUE "LegalCopyright", "Copyright © 2007-2019"
VALUE "OriginalFilename", "meos.exe" VALUE "OriginalFilename", "meos.exe"
VALUE "ProductName", " meos" VALUE "ProductName", " meos"
VALUE "ProductVersion", "3.4.0.1" VALUE "ProductVersion", "3.4.0.1"

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1825,6 +1825,20 @@ void capitalize(wstring &str) {
} }
} }
bool checkValidDate(const wstring &date) {
SYSTEMTIME st;
if (convertDateYMS(date, st, false) <= 0)
return false;
st.wHour = 12;
SYSTEMTIME utc;
if (!TzSpecificLocalTimeToSystemTime(0, &st, &utc)) {
return false;
}
return true;
}
/** Return bias in seconds. UTC = local time + bias. */ /** Return bias in seconds. UTC = local time + bias. */
int getTimeZoneInfo(const wstring &date) { int getTimeZoneInfo(const wstring &date) {
static wchar_t lastDate[16] = {0}; static wchar_t lastDate[16] = {0};
@ -1839,7 +1853,10 @@ int getTimeZoneInfo(const wstring &date) {
convertDateYMS(date, st, false); convertDateYMS(date, st, false);
st.wHour = 12; st.wHour = 12;
SYSTEMTIME utc; SYSTEMTIME utc;
TzSpecificLocalTimeToSystemTime(0, &st, &utc); if (!TzSpecificLocalTimeToSystemTime(0, &st, &utc)) {
lastValue = 0;
return 0;
}
int datecode = ((st.wYear * 12 + st.wMonth) * 31) + st.wDay; int datecode = ((st.wYear * 12 + st.wMonth) * 31) + st.wDay;
int datecodeUTC = ((utc.wYear * 12 + utc.wMonth) * 31) + utc.wDay; int datecodeUTC = ((utc.wYear * 12 + utc.wMonth) * 31) + utc.wDay;

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -53,17 +53,10 @@ public:
}; };
string convertSystemTimeN(const SYSTEMTIME &st); string convertSystemTimeN(const SYSTEMTIME &st);
/*
string convertSystemTime(const SYSTEMTIME &st);
string convertSystemTimeOnly(const SYSTEMTIME &st);
string convertSystemDate(const SYSTEMTIME &st);
string getLocalTime();
string getLocalDate();
string getLocalTimeOnly();
*/
string getLocalTimeN(); string getLocalTimeN();
bool checkValidDate(const wstring &date);
wstring convertSystemTime(const SYSTEMTIME &st); wstring convertSystemTime(const SYSTEMTIME &st);
wstring convertSystemTimeOnly(const SYSTEMTIME &st); wstring convertSystemTimeOnly(const SYSTEMTIME &st);
wstring convertSystemDate(const SYSTEMTIME &st); wstring convertSystemDate(const SYSTEMTIME &st);
@ -83,7 +76,6 @@ const wstring &getTimeMS(int m);
const wstring &formatTime(int rt); const wstring &formatTime(int rt);
const wstring &formatTimeHMS(int rt); const wstring &formatTimeHMS(int rt);
//const string &formatTimeN(int rt);
wstring formatTimeIOF(int rt, int zeroTime); wstring formatTimeIOF(int rt, int zeroTime);
int convertDateYMS(const string &m, bool checkValid); int convertDateYMS(const string &m, bool checkValid);
@ -92,7 +84,6 @@ int convertDateYMS(const string &m, SYSTEMTIME &st, bool checkValid);
int convertDateYMS(const wstring &m, bool checkValid); int convertDateYMS(const wstring &m, bool checkValid);
int convertDateYMS(const wstring &m, SYSTEMTIME &st, bool checkValid); int convertDateYMS(const wstring &m, SYSTEMTIME &st, bool checkValid);
// Convert a "general" time string to a MeOS compatible time string // Convert a "general" time string to a MeOS compatible time string
void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &meosDate); void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &meosDate);
@ -110,11 +101,6 @@ int convertAbsoluteTimeMS(const wstring &m);
// Parses a time on format HH:MM:SS+01:00Z or HHMMSS+0100Z (but ignores time zone) // Parses a time on format HH:MM:SS+01:00Z or HHMMSS+0100Z (but ignores time zone)
int convertAbsoluteTimeISO(const wstring &m); int convertAbsoluteTimeISO(const wstring &m);
//Returns a time converted from +/-MM:SS or NOTIME, in seconds
//int convertAbsoluteTimeMS(const string &m);
// Parses a time on format HH:MM:SS+01:00Z or HHMMSS+0100Z (but ignores time zone)
//int convertAbsoluteTimeISO(const string &m);
/** Returns a time converted from HH:MM:SS or -1, in seconds /** Returns a time converted from HH:MM:SS or -1, in seconds
@param m time to convert @param m time to convert
@param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time. @param daysZeroTime -1 do not support days syntax, positive interpret days w.r.t the specified zero time.
@ -160,7 +146,7 @@ wstring getMeosFullVersion();
wstring getMajorVersion(); wstring getMajorVersion();
wstring getMeosCompectVersion(); wstring getMeosCompectVersion();
void getSupporters(vector<wstring> &supp, vector<wstring> developSupp); void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp);
int countWords(const wchar_t *p); int countWords(const wchar_t *p);
@ -255,11 +241,6 @@ void capitalize(wstring &str);
/** Initial capital letter for each word. */ /** Initial capital letter for each word. */
void capitalizeWords(wstring &str); void capitalizeWords(wstring &str);
/*
void capitalize(string &str);
void capitalizeWords(string &str);*/
wstring getTimeZoneString(const wstring &date); wstring getTimeZoneString(const wstring &date);
/** Return bias in seconds. UTC = local time + bias. */ /** Return bias in seconds. UTC = local time + bias. */

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -1902,7 +1902,7 @@ OpFailStatus MeosSQL::syncUpdate(oRunner *r, bool forceWriteAll)
mysqlpp::Query queryset = con.query(); mysqlpp::Query queryset = con.query();
queryset << " Name=" << quote << toString(r->sName) << ", " queryset << " Name=" << quote << toString(r->sName) << ", "
<< " CardNo=" << r->CardNo << ", " << " CardNo=" << r->cardNumber << ", "
<< " StartNo=" << r->StartNo << ", " << " StartNo=" << r->StartNo << ", "
<< " StartTime=" << r->startTime << ", " << " StartTime=" << r->startTime << ", "
<< " FinishTime=" << r->FinishTime << ", " << " FinishTime=" << r->FinishTime << ", "
@ -3680,6 +3680,11 @@ bool MeosSQL::skipSynchronize(const oBase &entity) const {
notskipped++; notskipped++;
return false; return false;
} }
namespace {
int encode(oListId id) {
return int(id);
}
}
int MeosSQL::getModifiedMask(oEvent &oe) { int MeosSQL::getModifiedMask(oEvent &oe) {
try { try {
@ -3699,23 +3704,23 @@ int MeosSQL::getModifiedMask(oEvent &oe) {
int e = r["oEvent"]; int e = r["oEvent"];
if (ctrl > oe.sqlCounterControls) if (ctrl > oe.sqlCounterControls)
res |= oLControlId; res |= encode(oListId::oLControlId);
if (crs > oe.sqlCounterCourses) if (crs > oe.sqlCounterCourses)
res |= oLCourseId; res |= encode(oListId::oLCourseId);
if (cls > oe.sqlCounterClasses) if (cls > oe.sqlCounterClasses)
res |= oLClassId; res |= encode(oListId::oLClassId);
if (card > oe.sqlCounterCards) if (card > oe.sqlCounterCards)
res |= oLCardId; res |= encode(oListId::oLCardId);
if (club > oe.sqlCounterClubs) if (club > oe.sqlCounterClubs)
res |= oLClubId; res |= encode(oListId::oLClubId);
if (punch > oe.sqlCounterPunches) if (punch > oe.sqlCounterPunches)
res |= oLPunchId; res |= encode(oListId::oLPunchId);
if (runner > oe.sqlCounterRunners) if (runner > oe.sqlCounterRunners)
res |= oLRunnerId; res |= encode(oListId::oLRunnerId);
if (t > oe.sqlCounterTeams) if (t > oe.sqlCounterTeams)
res |= oLTeamId; res |= encode(oListId::oLTeamId);
if (e > oe.counter) if (e > oe.counter)
res |= oLEventId; res |= encode(oListId::oLEventId);
return res; return res;
} }

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2012 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -20,6 +20,7 @@
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/ ************************************************************************/
#pragma warning( disable : 4251) #pragma warning( disable : 4251)
#include <mysql++.h> #include <mysql++.h>

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -55,7 +55,6 @@ using namespace std;
Localizer lang; Localizer lang;
#endif #endif
extern "C"{
int MEOSDB_API getMeosVersion() int MEOSDB_API getMeosVersion()
{ {
@ -70,27 +69,27 @@ int getListMask(oEvent &oe) {
return msql.getModifiedMask(oe); return msql.getModifiedMask(oe);
} }
bool MEOSDB_API msSynchronizeList(oEvent *oe, int lid) bool MEOSDB_API msSynchronizeList(oEvent *oe, oListId lid)
{ {
nSynchList++; nSynchList++;
if (nSynchList % 100 == 99) if (nSynchList % 100 == 99)
OutputDebugString(L"Synchronized 100 lists\n"); OutputDebugString(L"Synchronized 100 lists\n");
if (lid==oLRunnerId) if (lid == oListId::oLRunnerId)
return msql.syncListRunner(oe); return msql.syncListRunner(oe);
else if (lid==oLClassId) else if (lid == oListId::oLClassId)
return msql.syncListClass(oe); return msql.syncListClass(oe);
else if (lid==oLCourseId) else if (lid == oListId::oLCourseId)
return msql.syncListCourse(oe); return msql.syncListCourse(oe);
else if (lid==oLControlId) else if (lid == oListId::oLControlId)
return msql.syncListControl(oe); return msql.syncListControl(oe);
else if (lid==oLClubId) else if (lid == oListId::oLClubId)
return msql.syncListClub(oe); return msql.syncListClub(oe);
else if (lid==oLCardId) else if (lid == oListId::oLCardId)
return msql.syncListCard(oe); return msql.syncListCard(oe);
else if (lid==oLPunchId) else if (lid == oListId::oLPunchId)
return msql.syncListPunch(oe); return msql.syncListPunch(oe);
else if (lid==oLTeamId) else if (lid == oListId::oLTeamId)
return msql.syncListTeam(oe); return msql.syncListTeam(oe);
return false; return false;
@ -227,7 +226,6 @@ bool MEOSDB_API msReConnect()
} }
} //Extern "C"
bool repairTables(const string &db, vector<string> &output) { bool repairTables(const string &db, vector<string> &output) {
return msql.repairTables(db, output); return msql.repairTables(db, output);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -33,11 +33,10 @@ enum OpFailStatus {
class oEvent; class oEvent;
class oBase; class oBase;
extern "C"{
#define MEOSDB_API #define MEOSDB_API
int MEOSDB_API getMeosVersion(); int MEOSDB_API getMeosVersion();
bool MEOSDB_API msSynchronizeList(oEvent *, int lid); // bool MEOSDB_API msSynchronizeList(oEvent *, oListId lid);
int MEOSDB_API msSynchronizeUpdate(oBase *); int MEOSDB_API msSynchronizeUpdate(oBase *);
int MEOSDB_API msSynchronizeRead(oBase *obj); int MEOSDB_API msSynchronizeRead(oBase *obj);
int MEOSDB_API msRemove(oBase *obj); int MEOSDB_API msRemove(oBase *obj);
@ -52,7 +51,7 @@ extern "C"{
int MEOSDB_API msListCompetitions(oEvent *oe); int MEOSDB_API msListCompetitions(oEvent *oe);
int getListMask(oEvent &oe); int getListMask(oEvent &oe);
}
bool repairTables(const string &db, vector<string> &output); bool repairTables(const string &db, vector<string> &output);

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -2,7 +2,7 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -27,9 +27,10 @@
//V2: ABCDEFGHIHJKMN //V2: ABCDEFGHIHJKMN
//V31: a //V31: a
//V33: abcde //V33: abcde
//V35: abcdefgh //V35: abcdef
//V36: abcdef
int getMeosBuild() { int getMeosBuild() {
string revision("$Rev: 810 $"); string revision("$Rev: 859 $");
return 174 + atoi(revision.substr(5, string::npos).c_str()); return 174 + atoi(revision.substr(5, string::npos).c_str());
} }
@ -41,16 +42,16 @@ int getMeosBuild() {
//V33: abcdefghij //V33: abcdefghij
//V34: abcdfge //V34: abcdfge
wstring getMeosDate() { wstring getMeosDate() {
wstring date(L"$Date: 2019-01-10 22:42:30 +0100 (to, 10 jan 2019) $"); wstring date(L"$Date: 2019-03-19 21:52:12 +0100 (ti, 19 mar 2019) $");
return date.substr(7,10); return date.substr(7,10);
} }
wstring getBuildType() { wstring getBuildType() {
return L"U3"; // No parantheses (...) return L"RC1"; // No parantheses (...)
} }
wstring getMajorVersion() { wstring getMajorVersion() {
return L"3.5"; return L"3.6";
} }
wstring getMeosFullVersion() { wstring getMeosFullVersion() {
@ -70,24 +71,8 @@ wstring getMeosCompectVersion() {
return getMajorVersion() + L"." + itow(getMeosBuild()) + L" (" + getBuildType() + L")"; return getMajorVersion() + L"." + itow(getMeosBuild()) + L" (" + getBuildType() + L")";
} }
void getSupporters(vector<wstring> &supp, vector<wstring> developSupp) void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
{ {
supp.emplace_back(L"Järfälla OK");
supp.emplace_back(L"Anders Larsson, OK Nackhe");
supp.emplace_back(L"Hans Wilhelmsson");
supp.emplace_back(L"Patrice Lavallee, Noyon Course d'Orientation");
supp.emplace_back(L"IFK Linköpings OS");
supp.emplace_back(L"Lars Ove Karlsson, Västerås SOK");
supp.emplace_back(L"OK Djerf");
supp.emplace_back(L"OK Vivill");
supp.emplace_back(L"Sonny Andersson, Huskvarna");
supp.emplace_back(L"Hässleholms OK Skolorientering");
supp.emplace_back(L"IBM-klubben Orientering");
supp.emplace_back(L"OK Øst, Birkerød");
supp.emplace_back(L"OK Klemmingen");
supp.emplace_back(L"Hans Johansson");
supp.emplace_back(L"KOB Kysak");
supp.emplace_back(L"Per Ivarsson, Trollhättans SOK");
supp.emplace_back(L"Sergio Yañez, ABC TRAIL"); supp.emplace_back(L"Sergio Yañez, ABC TRAIL");
supp.emplace_back(L"Western Race Services"); supp.emplace_back(L"Western Race Services");
supp.emplace_back(L"IK Gandvik, Skara"); supp.emplace_back(L"IK Gandvik, Skara");
@ -113,6 +98,7 @@ void getSupporters(vector<wstring> &supp, vector<wstring> developSupp)
supp.emplace_back(L"SOS Jindřichův Hradec"); supp.emplace_back(L"SOS Jindřichův Hradec");
supp.emplace_back(L"Mats Holmberg, OK Gränsen"); supp.emplace_back(L"Mats Holmberg, OK Gränsen");
supp.emplace_back(L"Christoffer Ohlsson, Uddevalla OK"); supp.emplace_back(L"Christoffer Ohlsson, Uddevalla OK");
supp.emplace_back(L"KOB ATU Košice");
supp.emplace_back(L"O-Ringen AB"); supp.emplace_back(L"O-Ringen AB");
supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK"); supp.emplace_back(L"Hans Carlstedt, Sävedalens AIK");
supp.emplace_back(L"IFK Mora OK"); supp.emplace_back(L"IFK Mora OK");
@ -129,6 +115,7 @@ void getSupporters(vector<wstring> &supp, vector<wstring> developSupp)
supp.emplace_back(L"Leksands OK"); supp.emplace_back(L"Leksands OK");
supp.emplace_back(L"O-Travel"); supp.emplace_back(L"O-Travel");
supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice"); supp.emplace_back(L"Kamil Pipek, OK Lokomotiva Pardubice");
developSupp.emplace_back(L"KOB Kysak");
supp.emplace_back(L"Richard HEYRIES"); supp.emplace_back(L"Richard HEYRIES");
supp.emplace_back(L"Ingemar Carlsson"); supp.emplace_back(L"Ingemar Carlsson");
supp.emplace_back(L"Tolereds AIK"); supp.emplace_back(L"Tolereds AIK");
@ -137,8 +124,9 @@ void getSupporters(vector<wstring> &supp, vector<wstring> developSupp)
supp.emplace_back(L"Helsingborgs SOK"); supp.emplace_back(L"Helsingborgs SOK");
supp.emplace_back(L"Sala OK"); supp.emplace_back(L"Sala OK");
supp.emplace_back(L"OK Roskilde"); supp.emplace_back(L"OK Roskilde");
supp.emplace_back(L"Almby IK, Örebro"); developSupp.emplace_back(L"Almby IK, Örebro");
supp.emplace_back(L"Ligue PACA"); supp.emplace_back(L"Ligue PACA");
supp.emplace_back(L"SC vebr-sport");
supp.emplace_back(L"IP Skogen Göteborg");
reverse(supp.begin(), supp.end()); reverse(supp.begin(), supp.end());
} }

View File

@ -1,6 +1,6 @@
/************************************************************************ /************************************************************************
MeOS - Orienteering Software MeOS - Orienteering Software
Copyright (C) 2009-2018 Melin Software HB Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -69,6 +69,10 @@ oListParam::oListParam() {
timePerPage = 8000; timePerPage = 8000;
margin = 5; margin = 5;
screenMode = 0; screenMode = 0;
htmlScale = 1.0;
htmlRows = 60;
htmlTypeTag = "free";
} }
void oListParam::serialize(xmlparser &xml, void oListParam::serialize(xmlparser &xml,
@ -77,10 +81,10 @@ void oListParam::serialize(xmlparser &xml,
xml.startTag("ListParam", "Name", name); xml.startTag("ListParam", "Name", name);
xml.write("ListId", container.getUniqueId(listCode)); xml.write("ListId", container.getUniqueId(listCode));
string sel; string sel;
for (set<int>::const_iterator it = selection.begin(); it != selection.end(); ++it) { for (int s : selection) {
if (!sel.empty()) if (!sel.empty())
sel += ";"; sel += ";";
sel += itos(*it); sel += itos(s);
} }
xml.write("ClassId", sel); xml.write("ClassId", sel);
xml.write("LegNumber", legNumber); xml.write("LegNumber", legNumber);
@ -90,13 +94,15 @@ void oListParam::serialize(xmlparser &xml,
xml.write("Title", title); xml.write("Title", title);
xml.writeBool("Large", useLargeSize); xml.writeBool("Large", useLargeSize);
xml.writeBool("PageBreak", pageBreak); xml.writeBool("PageBreak", pageBreak);
xml.writeBool("HideHeader", !showHeader);
xml.writeBool("ShowNamedSplits", showInterTimes); xml.writeBool("ShowNamedSplits", showInterTimes);
xml.writeBool("ShowInterTitle", showInterTitle); xml.writeBool("ShowInterTitle", showInterTitle);
xml.writeBool("ShowSplits", showSplitTimes); xml.writeBool("ShowSplits", showSplitTimes);
xml.writeBool("ShowAnalysis", splitAnalysis); xml.writeBool("ShowAnalysis", splitAnalysis);
xml.write("InputNumber", inputNumber); xml.write("InputNumber", inputNumber);
if (nextList != 0) { if (nextList != 0) {
map<int, int>::const_iterator res = idToIndex.find(nextList); auto res = idToIndex.find(nextList);
if (res != idToIndex.end()) if (res != idToIndex.end())
xml.write("NextList", res->second); xml.write("NextList", res->second);
} }
@ -111,13 +117,19 @@ void oListParam::serialize(xmlparser &xml,
xml.write("ScreenMode", screenMode); xml.write("ScreenMode", screenMode);
if (nColumns != 0) { if (nColumns != 0 || htmlTypeTag != "free") {
xml.write("NumColumns", itos(nColumns)); xml.write("NumColumns", itos(nColumns));
xml.writeBool("Animate", animate); xml.writeBool("Animate", animate);
xml.write("TimePerPage", timePerPage); xml.write("TimePerPage", timePerPage);
xml.write("Margin", margin); xml.write("Margin", margin);
} }
if (htmlTypeTag != "free") {
xml.write("HTML", htmlTypeTag);
xml.write("PageRows", htmlRows);
xml.write("Scale", to_string(htmlScale));
}
xml.endTag(); xml.endTag();
} }
@ -142,6 +154,8 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
useLargeSize = xml.getObjectBool("Large"); useLargeSize = xml.getObjectBool("Large");
pageBreak = xml.getObjectBool("PageBreak"); pageBreak = xml.getObjectBool("PageBreak");
showHeader = !xml.getObjectBool("HideHeader");
showInterTimes = xml.getObjectBool("ShowNamedSplits"); showInterTimes = xml.getObjectBool("ShowNamedSplits");
showSplitTimes = xml.getObjectBool("ShowSplits"); showSplitTimes = xml.getObjectBool("ShowSplits");
splitAnalysis = xml.getObjectBool("ShowAnalysis"); splitAnalysis = xml.getObjectBool("ShowAnalysis");
@ -163,7 +177,7 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
xml.getObjectString("Image", bgImage); xml.getObjectString("Image", bgImage);
int nColumns = xml.getObjectInt("NumColumns"); nColumns = xml.getObjectInt("NumColumns");
screenMode = xml.getObjectInt("ScreenMode"); screenMode = xml.getObjectInt("ScreenMode");
animate = xml.getObjectBool("Animate"); animate = xml.getObjectBool("Animate");
@ -172,7 +186,22 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
timePerPage = xml.getObjectInt("TimePerPage"); timePerPage = xml.getObjectInt("TimePerPage");
if (xml.got("Margin")) if (xml.got("Margin"))
timePerPage = xml.getObjectInt("Margin"); margin = xml.getObjectInt("Margin");
if (xml.got("HTML"))
xml.getObjectString("HTML", htmlTypeTag);
if (xml.got("Scale")) {
string tmp;
xml.getObjectString("Scale", tmp);
htmlScale = atof(tmp.c_str());
if (!(htmlScale > 0.1 && htmlScale < 1000))
htmlScale = 1.0;
}
if (xml.got("PageRows")) {
htmlRows = xml.getObjectInt("PageRows");
}
saved = true; saved = true;
} }
@ -374,10 +403,18 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
li.calcResults = false; li.calcResults = false;
li.calcTotalResults = false; li.calcTotalResults = false;
li.rogainingResults = false; li.rogainingResults = false;
li.calculateLiveResults = false;
li.calcCourseClassResults = false; li.calcCourseClassResults = false;
if (par.useControlIdResultFrom > 0 || par.useControlIdResultTo > 0) if (par.useControlIdResultFrom > 0 || par.useControlIdResultTo > 0)
li.needPunches = true; li.needPunches = oListInfo::PunchMode::SpecificPunch;
const bool isPunchList = mList.listSubType == oListInfo::EBaseTypePunches; const bool isPunchList = mList.listSubType == oListInfo::EBaseTypeCoursePunches ||
mList.listSubType == oListInfo::EBaseTypeAllPunches;
if (isPunchList) {
if ((!li.filter(EFilterList::EFilterHasResult) && !li.filter(EFilterList::EFilterHasPrelResult))
|| li.sortOrder == SortOrder::ClassLiveResult)
li.needPunches = oListInfo::PunchMode::AnyPunch;
}
map<tuple<int, int, int>, int> indexPosToWidth; map<tuple<int, int, int>, int> indexPosToWidth;
map< pair<int, int>, int> linePostCount; map< pair<int, int>, int> linePostCount;
for (int i = 0; i<4; i++) { for (int i = 0; i<4; i++) {
@ -411,7 +448,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
// Automatically determine what needs to be calculated // Automatically determine what needs to be calculated
if (mp.type == lTeamPlace || mp.type == lRunnerPlace || mp.type == lRunnerGeneralPlace) { if (mp.type == lTeamPlace || mp.type == lRunnerPlace || mp.type == lRunnerGeneralPlace) {
if (!li.calcResults) { if (!li.calcResults) {
oe->calculateResults(oEvent::RTClassResult); oe->calculateResults(set<int>(), oEvent::ResultType::ClassResult);
oe->calculateTeamResults(false); oe->calculateTeamResults(false);
} }
li.calcResults = true; li.calcResults = true;
@ -420,7 +457,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|| mp.type == lTeamTotalPlace || mp.type == lTeamPlaceDiff || mp.type == lTeamTotalPlace || mp.type == lTeamPlaceDiff
|| mp.type == lRunnerGeneralPlace) { || mp.type == lRunnerGeneralPlace) {
if (!li.calcTotalResults) { if (!li.calcTotalResults) {
oe->calculateResults(oEvent::RTTotalResult); oe->calculateResults(set<int>(), oEvent::ResultType::TotalResult);
oe->calculateTeamResults(true); oe->calculateTeamResults(true);
} }
li.calcTotalResults = true; li.calcTotalResults = true;
@ -431,12 +468,13 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
} }
else if (mp.type == lRunnerClassCoursePlace || mp.type == lRunnerClassCourseTimeAfter) { else if (mp.type == lRunnerClassCoursePlace || mp.type == lRunnerClassCourseTimeAfter) {
if (!li.calcCourseClassResults) if (!li.calcCourseClassResults)
oe->calculateResults(oEvent::RTClassCourseResult); oe->calculateResults(set<int>(), oEvent::ResultType::ClassCourseResult);
li.calcCourseClassResults = true; li.calcCourseClassResults = true;
} }
else if (mp.type == lRunnerTempTimeAfter || mp.type == lRunnerTempTimeStatus) { else if (mp.type == lRunnerTempTimeAfter || mp.type == lRunnerTempTimeStatus) {
li.needPunches = true; if (li.needPunches == oListInfo::PunchMode::NoPunch)
li.needPunches = oListInfo::PunchMode::SpecificPunch;
} }
string label = "P" + itos(i*1000 + j*100 + k); string label = "P" + itos(i*1000 + j*100 + k);
@ -515,7 +553,7 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
for (map<pair<int, int>, int>::iterator it = linePostCount.begin(); it != linePostCount.end(); ++it) { for (map<pair<int, int>, int>::iterator it = linePostCount.begin(); it != linePostCount.end(); ++it) {
if (it->second == 1) { if (it->second == 1) {
int base = it->first.first; int base = it->first.first;
if (base == MLSubList && listSubType == oListInfo::EBaseTypePunches) if (base == MLSubList && listSubType == oListInfo::EBaseTypeCoursePunches)
continue; // This type of list requires actual width continue; // This type of list requires actual width
indexPosToWidth[tuple<int,int,int>(base, it->first.second, 0)] = totalWidth; indexPosToWidth[tuple<int,int,int>(base, it->first.second, 0)] = totalWidth;
} }
@ -738,6 +776,9 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
it != filter.end(); ++it) { it != filter.end(); ++it) {
li.setFilter(*it); li.setFilter(*it);
} }
if (li.filter(EFilterList::EFilterAnyResult) || sortOrder == SortOrder::ClassLiveResult)
li.calculateLiveResults = true;
for (set<ESubFilterList>::const_iterator it = subFilter.begin(); for (set<ESubFilterList>::const_iterator it = subFilter.begin();
it != subFilter.end(); ++it) { it != subFilter.end(); ++it) {
li.setSubFilter(*it); li.setSubFilter(*it);
@ -750,7 +791,6 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
hasResults_ = true; hasResults_ = true;
} }
void Position::indent(int ind) { void Position::indent(int ind) {
int end = pos.size() - 1; int end = pos.size() - 1;
if (end < 1) if (end < 1)
@ -1629,15 +1669,17 @@ void MetaList::initSymbols() {
typeToSymbol[lPatrolClubNameNames] = L"PatrolClubNameNames"; typeToSymbol[lPatrolClubNameNames] = L"PatrolClubNameNames";
typeToSymbol[lRunnerFinish] = L"RunnerFinish"; typeToSymbol[lRunnerFinish] = L"RunnerFinish";
typeToSymbol[lRunnerTime] = L"RunnerTime"; typeToSymbol[lRunnerTime] = L"RunnerTime";
typeToSymbol[lRunnerGrossTime] = L"RunnerGrossTime";
typeToSymbol[lRunnerTimeStatus] = L"RunnerTimeStatus"; typeToSymbol[lRunnerTimeStatus] = L"RunnerTimeStatus";
typeToSymbol[lRunnerTempTimeStatus] = L"RunnerTempTimeStatus"; typeToSymbol[lRunnerTempTimeStatus] = L"RunnerTempTimeStatus";
typeToSymbol[lRunnerTempTimeAfter] = L"RunnerTempTimeAfter"; typeToSymbol[lRunnerTempTimeAfter] = L"RunnerTempTimeAfter";
typeToSymbol[lRunnerTimeAfter] = L"RunnerTimeAfter"; typeToSymbol[lRunnerTimeAfter] = L"RunnerTimeAfter";
typeToSymbol[lRunnerClassCourseTimeAfter] = L"RunnerClassCourseTimeAfter"; typeToSymbol[lRunnerClassCourseTimeAfter] = L"RunnerClassCourseTimeAfter";
typeToSymbol[lRunnerMissedTime] = L"RunnerTimeLost"; typeToSymbol[lRunnerLostTime] = L"RunnerTimeLost";
typeToSymbol[lRunnerPlace] = L"RunnerPlace"; typeToSymbol[lRunnerPlace] = L"RunnerPlace";
typeToSymbol[lRunnerClassCoursePlace] = L"RunnerClassCoursePlace"; typeToSymbol[lRunnerClassCoursePlace] = L"RunnerClassCoursePlace";
typeToSymbol[lRunnerStart] = L"RunnerStart"; typeToSymbol[lRunnerStart] = L"RunnerStart";
typeToSymbol[lRunnerCheck] = L"RunnerCheck";
typeToSymbol[lRunnerStartCond] = L"RunnerStartCond"; typeToSymbol[lRunnerStartCond] = L"RunnerStartCond";
typeToSymbol[lRunnerStartZero] = L"RunnerStartZero"; typeToSymbol[lRunnerStartZero] = L"RunnerStartZero";
typeToSymbol[lRunnerClub] = L"RunnerClub"; typeToSymbol[lRunnerClub] = L"RunnerClub";
@ -1674,6 +1716,7 @@ void MetaList::initSymbols() {
typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod"; typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod";
typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate"; typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate";
typeToSymbol[lRunnerEntryTime] = L"RunnerEntryTime"; typeToSymbol[lRunnerEntryTime] = L"RunnerEntryTime";
typeToSymbol[lRunnerId] = L"RunnerId";
typeToSymbol[lTeamName] = L"TeamName"; typeToSymbol[lTeamName] = L"TeamName";
typeToSymbol[lTeamStart] = L"TeamStart"; typeToSymbol[lTeamStart] = L"TeamStart";
@ -1693,13 +1736,18 @@ void MetaList::initSymbols() {
typeToSymbol[lTeamPointAdjustment] = L"TeamPointAdjustment"; typeToSymbol[lTeamPointAdjustment] = L"TeamPointAdjustment";
typeToSymbol[lTeamTime] = L"TeamTime"; typeToSymbol[lTeamTime] = L"TeamTime";
typeToSymbol[lTeamGrossTime] = L"TeamGrossTime";
typeToSymbol[lTeamStatus] = L"TeamStatus"; typeToSymbol[lTeamStatus] = L"TeamStatus";
typeToSymbol[lTeamClub] = L"TeamClub"; typeToSymbol[lTeamClub] = L"TeamClub";
typeToSymbol[lTeamRunner] = L"TeamRunner"; typeToSymbol[lTeamRunner] = L"TeamRunner";
typeToSymbol[lTeamRunnerCard] = L"TeamRunnerCard"; typeToSymbol[lTeamRunnerCard] = L"TeamRunnerCard";
typeToSymbol[lTeamBib] = L"TeamBib"; typeToSymbol[lTeamBib] = L"TeamBib";
typeToSymbol[lTeamStartNo] = L"TeamStartNo"; typeToSymbol[lTeamStartNo] = L"TeamStartNo";
typeToSymbol[lPunchNamedTime] = L"PunchNamedTime"; typeToSymbol[lPunchNamedTime] = L"PunchNamedTime";
typeToSymbol[lPunchName] = L"PunchName";
typeToSymbol[lPunchNamedSplit] = L"PunchNamedSplit";
typeToSymbol[lPunchTime] = L"PunchTime"; typeToSymbol[lPunchTime] = L"PunchTime";
typeToSymbol[lPunchControlNumber] = L"PunchControlNumber"; typeToSymbol[lPunchControlNumber] = L"PunchControlNumber";
typeToSymbol[lPunchControlCode] = L"PunchControlCode"; typeToSymbol[lPunchControlCode] = L"PunchControlCode";
@ -1707,6 +1755,12 @@ void MetaList::initSymbols() {
typeToSymbol[lPunchControlPlace] = L"PunchControlPlace"; typeToSymbol[lPunchControlPlace] = L"PunchControlPlace";
typeToSymbol[lPunchControlPlaceAcc] = L"PunchControlPlaceAcc"; typeToSymbol[lPunchControlPlaceAcc] = L"PunchControlPlaceAcc";
typeToSymbol[lPunchSplitTime] = L"PunchSplitTime";
typeToSymbol[lPunchTotalTime] = L"PunchTotalTime";
typeToSymbol[lPunchAbsTime] = L"PunchAbsTime";
typeToSymbol[lPunchTotalTimeAfter] = L"PunchTotalTimeAfter";
typeToSymbol[lPunchTimeSinceLast] = L"PunchTimeSinceLast";
typeToSymbol[lRogainingPunch] = L"RogainingPunch"; typeToSymbol[lRogainingPunch] = L"RogainingPunch";
typeToSymbol[lTotalCounter] = L"TotalCounter"; typeToSymbol[lTotalCounter] = L"TotalCounter";
typeToSymbol[lSubCounter] = L"SubCounter"; typeToSymbol[lSubCounter] = L"SubCounter";
@ -1746,6 +1800,8 @@ void MetaList::initSymbols() {
typeToSymbol[lControlRunnersLeft] = L"ControlRunnersLeft"; typeToSymbol[lControlRunnersLeft] = L"ControlRunnersLeft";
typeToSymbol[lControlCodes] = L"ControlCodes"; typeToSymbol[lControlCodes] = L"ControlCodes";
typeToSymbol[lLineBreak] = L"LineBreak";
for (map<EPostType, wstring>::iterator it = typeToSymbol.begin(); for (map<EPostType, wstring>::iterator it = typeToSymbol.begin();
it != typeToSymbol.end(); ++it) { it != typeToSymbol.end(); ++it) {
symbolToType[it->second] = it->first; symbolToType[it->second] = it->first;
@ -1760,7 +1816,8 @@ void MetaList::initSymbols() {
baseTypeToSymbol[oListInfo::EBaseTypeRunner] = "Runner"; baseTypeToSymbol[oListInfo::EBaseTypeRunner] = "Runner";
baseTypeToSymbol[oListInfo::EBaseTypeTeam] = "Team"; baseTypeToSymbol[oListInfo::EBaseTypeTeam] = "Team";
baseTypeToSymbol[oListInfo::EBaseTypeClub] = "ClubRunner"; baseTypeToSymbol[oListInfo::EBaseTypeClub] = "ClubRunner";
baseTypeToSymbol[oListInfo::EBaseTypePunches] = "Punches"; baseTypeToSymbol[oListInfo::EBaseTypeCoursePunches] = "CoursePunches";
baseTypeToSymbol[oListInfo::EBaseTypeAllPunches] = "AllPunches";
baseTypeToSymbol[oListInfo::EBaseTypeNone] = "None"; baseTypeToSymbol[oListInfo::EBaseTypeNone] = "None";
baseTypeToSymbol[oListInfo::EBaseTypeRunnerGlobal] = "RunnerGlobal"; baseTypeToSymbol[oListInfo::EBaseTypeRunnerGlobal] = "RunnerGlobal";
baseTypeToSymbol[oListInfo::EBaseTypeRunnerLeg] = "RunnerLeg"; baseTypeToSymbol[oListInfo::EBaseTypeRunnerLeg] = "RunnerLeg";
@ -1778,6 +1835,7 @@ void MetaList::initSymbols() {
if (symbolToBaseType.size() != oListInfo::EBasedTypeLast_) if (symbolToBaseType.size() != oListInfo::EBasedTypeLast_)
throw std::exception("Bad symbol setup"); throw std::exception("Bad symbol setup");
symbolToBaseType["Punches"] = oListInfo::EBaseTypeCoursePunches; // Back comp MeOS --3.5
orderToSymbol[ClassStartTime] = "ClassStartTime"; orderToSymbol[ClassStartTime] = "ClassStartTime";
orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub"; orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub";
@ -1789,6 +1847,7 @@ void MetaList::initSymbols() {
orderToSymbol[SortByFinishTimeReverse] = "FinishTimeReverse"; orderToSymbol[SortByFinishTimeReverse] = "FinishTimeReverse";
orderToSymbol[ClassFinishTime] = "ClassFinishTime"; orderToSymbol[ClassFinishTime] = "ClassFinishTime";
orderToSymbol[SortByStartTime] = "StartTime"; orderToSymbol[SortByStartTime] = "StartTime";
orderToSymbol[SortByStartTimeClass] = "StartTimeClass";
orderToSymbol[SortByEntryTime] = "EntryTime"; orderToSymbol[SortByEntryTime] = "EntryTime";
orderToSymbol[ClassPoints] = "ClassPoints"; orderToSymbol[ClassPoints] = "ClassPoints";
orderToSymbol[ClassTotalResult] = "ClassTotalResult"; orderToSymbol[ClassTotalResult] = "ClassTotalResult";
@ -1796,6 +1855,8 @@ void MetaList::initSymbols() {
orderToSymbol[CourseResult] = "CourseResult"; orderToSymbol[CourseResult] = "CourseResult";
orderToSymbol[CourseStartTime] = "CourseStartTime"; orderToSymbol[CourseStartTime] = "CourseStartTime";
orderToSymbol[ClassTeamLeg] = "ClassTeamLeg"; orderToSymbol[ClassTeamLeg] = "ClassTeamLeg";
orderToSymbol[ClassLiveResult] = "ClassLiveResult";
orderToSymbol[ClassKnockoutTotalResult] = "ClassKnockoutTotalResult";
orderToSymbol[Custom] = "CustomSort"; orderToSymbol[Custom] = "CustomSort";
for (map<SortOrder, string>::iterator it = orderToSymbol.begin(); for (map<SortOrder, string>::iterator it = orderToSymbol.begin();
@ -1818,6 +1879,8 @@ void MetaList::initSymbols() {
filterToSymbol[EFilterVacant] = "FilterNotVacant"; filterToSymbol[EFilterVacant] = "FilterNotVacant";
filterToSymbol[EFilterOnlyVacant] = "FilterOnlyVacant"; filterToSymbol[EFilterOnlyVacant] = "FilterOnlyVacant";
filterToSymbol[EFilterHasNoCard] = "FilterNoCard"; filterToSymbol[EFilterHasNoCard] = "FilterNoCard";
filterToSymbol[EFilterAnyResult] = "FilterAnyResult";
filterToSymbol[EFilterAPIEntry] = "EFilterAPIEntry";
for (map<EFilterList, string>::iterator it = filterToSymbol.begin(); for (map<EFilterList, string>::iterator it = filterToSymbol.begin();
it != filterToSymbol.end(); ++it) { it != filterToSymbol.end(); ++it) {
@ -1836,6 +1899,8 @@ void MetaList::initSymbols() {
subFilterToSymbol[ESubFilterVacant] = "FilterNotVacant"; subFilterToSymbol[ESubFilterVacant] = "FilterNotVacant";
subFilterToSymbol[ESubFilterSameParallel] = "FilterSameParallel"; subFilterToSymbol[ESubFilterSameParallel] = "FilterSameParallel";
subFilterToSymbol[ESubFilterSameParallelNotFirst] = "FilterSameParallelNotFirst"; subFilterToSymbol[ESubFilterSameParallelNotFirst] = "FilterSameParallelNotFirst";
subFilterToSymbol[ESubFilterNotFinish] = "FilterNotFinish";
subFilterToSymbol[ESubFilterNamedControl] = "FilterNamedControl";
for (map<ESubFilterList, string>::iterator it = subFilterToSymbol.begin(); for (map<ESubFilterList, string>::iterator it = subFilterToSymbol.begin();
it != subFilterToSymbol.end(); ++it) { it != subFilterToSymbol.end(); ++it) {
@ -1875,7 +1940,14 @@ void MetaList::initSymbols() {
} }
} }
MetaListContainer::MetaListContainer(oEvent *ownerIn): owner(ownerIn) {} MetaListContainer::MetaListContainer(oEvent *owner): owner(owner) {}
MetaListContainer::MetaListContainer(oEvent *owner, const MetaListContainer &src) {
*this = src;
this->owner = owner;
}
MetaListContainer::~MetaListContainer() {} MetaListContainer::~MetaListContainer() {}
@ -2426,7 +2498,8 @@ void MetaList::getBaseType(vector< pair<wstring, size_t> > &types, int &currentT
types.clear(); types.clear();
for(map<oListInfo::EBaseType, string>::const_iterator it = baseTypeToSymbol.begin(); for(map<oListInfo::EBaseType, string>::const_iterator it = baseTypeToSymbol.begin();
it != baseTypeToSymbol.end(); ++it) { it != baseTypeToSymbol.end(); ++it) {
if (it->first == oListInfo::EBaseTypeNone || it->first == oListInfo::EBaseTypePunches) if (it->first == oListInfo::EBaseTypeNone || it->first == oListInfo::EBaseTypeCoursePunches
|| it->first == oListInfo::EBaseTypeAllPunches)
continue; continue;
types.push_back(make_pair(lang.tl(it->second), it->first)); types.push_back(make_pair(lang.tl(it->second), it->first));
} }
@ -2444,7 +2517,11 @@ void MetaList::getSubType(vector< pair<wstring, size_t> > &types, int &currentTy
tt.insert(t); tt.insert(t);
types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t)); types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t));
t = oListInfo::EBaseTypePunches; t = oListInfo::EBaseTypeCoursePunches;
tt.insert(t);
types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t));
t = oListInfo::EBaseTypeAllPunches;
tt.insert(t); tt.insert(t);
types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t)); types.push_back(make_pair(lang.tl(baseTypeToSymbol[t]), t));
@ -2493,7 +2570,7 @@ void MetaListContainer::removeParam(int index) {
throw meosException("No such parameters exist"); throw meosException("No such parameters exist");
} }
void MetaListContainer::addListParam(oListParam &param) { int MetaListContainer::addListParam(oListParam &param) {
param.saved = true; param.saved = true;
int ix = 0; int ix = 0;
if (!listParam.empty()) if (!listParam.empty())
@ -2502,6 +2579,7 @@ void MetaListContainer::addListParam(oListParam &param) {
listParam[ix] = param; listParam[ix] = param;
if (owner) if (owner)
owner->updateChanged(); owner->updateChanged();
return ix;
} }
const oListParam &MetaListContainer::getParam(int index) const { const oListParam &MetaListContainer::getParam(int index) const {
@ -2606,3 +2684,79 @@ bool MetaList::supportClasses() const {
else else
return true; return true;
} }
EPostType MetaList::getTypeFromSymbol(wstring &symb) noexcept {
auto res = symbolToType.find(symb);
if (res == symbolToType.end())
return EPostType::lNone; // Error code
return res->second;
}
void MetaList::fillSymbols(vector < pair<wstring, size_t>> &symb) {
for (auto s : symbolToType) {
if (s.second == lAlignNext || s.second == lNone || s.second == lLineBreak)
continue;
wstring desc = L"[" + s.first + L"]\t" + lang.tl(s.first);
symb.emplace_back(desc, size_t(s.second));
}
}
void MetaListContainer::synchronizeTo(MetaListContainer &dst) const {
auto &dstData = dst.data;
map<wstring, int> dstLst;
map<string, int> dstLstId;
for (size_t k = 0; k < dstData.size(); k++) {
auto &d = dstData[k];
if (d.first == MetaListType::ExternalList) {
wstring n = d.second.getListName();
dstLst[n] = k;
string id = d.second.getUniqueId();
dstLstId[id] = k;
}
}
for (auto &d : data) {
if (d.first == MetaListType::ExternalList) {
wstring n = d.second.getListName();
string id = d.second.getUniqueId();
if (dstLst.count(n))
dstData[dstLst[n]].second = d.second;
else if (!dstLstId.count(id)) {
dstData.push_back(d);
}
}
else if (d.first != MetaListType::RemovedList) {
dstData.push_back(d); // All internal lists
}
}
dst.setupIndex(EFirstLoadedList);
map<wstring, int> dstLstParam;
for (auto &lp : dst.listParam) {
const wstring &n = lp.second.getName();
dstLstParam[n] = lp.first;
}
for (auto &lp : listParam) {
EStdListType dstCode = dst.getCodeFromUnqiueId(getUniqueId(lp.second.listCode));
const wstring &n = lp.second.getName();
if (dstLstParam.count(n)) {
dst.listParam[dstLstParam[n]] = lp.second;
dst.listParam[dstLstParam[n]].listCode = dstCode;
}
else {
int ix = 0;
if (!listParam.empty())
ix = listParam.rbegin()->first + 1;
dst.listParam[ix] = lp.second;
dst.listParam[ix].listCode = dstCode;
}
}
}

Some files were not shown because too many files have changed in this diff Show More