MeOS version 3.6-1033 RC1
This commit is contained in:
parent
8ba2208e65
commit
e8e5e499f2
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -30,26 +30,36 @@
|
||||
#include "meos_util.h"
|
||||
#include "Localizer.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);
|
||||
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) {
|
||||
fout << "<style type=\"text/css\">\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 << "h2 {font-family:arial,sans-serif;font-size:20px;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 << "p {font-family:arial,sans-serif;font-size:12px;font-weight:normal}\n";
|
||||
fout << "div {font-family:arial,sans-serif;font-size:12px;font-weight:normal}\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:" << fixed << std::setprecision(2) << 20 * scale << "px;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:" << fixed << std::setprecision(2) << 12 * scale << "px;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) {
|
||||
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.e1 {background-color: rgb(245,245,255)}\n";
|
||||
fout << "td.header {line-height:1.8;height:40px}\n";
|
||||
fout << "td.freeheader {line-height:1.2}\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:" << fixed << std::setprecision(2) << 1.2 * scale << "}\n";
|
||||
}
|
||||
list<TextInfo>::const_iterator it=TL.begin();
|
||||
int styleList = 1;
|
||||
@ -93,16 +103,16 @@ static void generateStyles(const gdioutput &gdi, ostream &fout, bool withTbl, co
|
||||
}
|
||||
|
||||
wstring faceName;
|
||||
double scale = 1.0;
|
||||
double iscale = 1.0;
|
||||
if (it->font.empty()) {
|
||||
faceName = L"arial,sans-serif";
|
||||
}
|
||||
else
|
||||
scale = getLocalScale(it->font, faceName);
|
||||
iscale = getLocalScale(it->font, faceName);
|
||||
|
||||
fout << element << "." << style
|
||||
<< "{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";
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
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,
|
||||
gdiFonts font, const string &face, const string &extraStyle, string &starttag, string &endtag) {
|
||||
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);
|
||||
ofstream fout(file.c_str());
|
||||
|
||||
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" <<
|
||||
" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n";
|
||||
void HTMLWriter::writeHTML(gdioutput &gdi, ostream &fout, const wstring &title, int refreshTimeOut, double scale) {
|
||||
if (scale <= 0)
|
||||
scale = 1.0;
|
||||
|
||||
fout << "<!DOCTYPE html>" << endl;
|
||||
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)
|
||||
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;
|
||||
generateStyles(*this, fout, false, TL, styles);
|
||||
generateStyles(gdi, fout, scale, false, gdi.getTL(), styles);
|
||||
|
||||
fout << "</head>\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();
|
||||
|
||||
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\">";
|
||||
fout << "<p style=\"position:absolute;left:10px;top:" << int(yscale*(gdi.getPageY()-45)) + offsetY << "px\">";
|
||||
|
||||
char bf1[256];
|
||||
char bf2[256];
|
||||
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
||||
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
||||
//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 << "</body>\n";
|
||||
fout << "</html>\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
const wstring &title, int refreshTimeOut) const
|
||||
{
|
||||
void HTMLWriter::writeTableHTML(gdioutput &gdi,
|
||||
const wstring &file,
|
||||
const wstring &title,
|
||||
int refreshTimeOut,
|
||||
double scale) {
|
||||
checkWriteAccess(file);
|
||||
ofstream fout(file.c_str());
|
||||
|
||||
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,
|
||||
bool simpleFormat,
|
||||
int refreshTimeOut) const {
|
||||
|
||||
fout << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n" <<
|
||||
" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n";
|
||||
int refreshTimeOut,
|
||||
double scale) {
|
||||
if (scale <= 0)
|
||||
scale = 1.0;
|
||||
|
||||
fout << "<!DOCTYPE html>" << endl;
|
||||
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)
|
||||
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;
|
||||
generateStyles(*this, fout, true, TL, styles);
|
||||
generateStyles(gdi, fout, scale, true, gdi.getTL(), styles);
|
||||
|
||||
fout << "</head>\n";
|
||||
|
||||
fout << "<body>\n";
|
||||
|
||||
list<TextInfo>::const_iterator it = TL.begin();
|
||||
auto &TL = gdi.getTL();
|
||||
auto it = TL.begin();
|
||||
int MaxX = gdi.getPageX() - 100;
|
||||
map<int,int> tableCoordinates;
|
||||
|
||||
//Get x-coordinates
|
||||
@ -493,9 +536,9 @@ bool gdioutput::writeTableHTML(ostream &fout,
|
||||
|
||||
gdiFonts font = row[k]->getGdiFont();
|
||||
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";
|
||||
@ -512,12 +555,423 @@ bool gdioutput::writeTableHTML(ostream &fout,
|
||||
GetTimeFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf2, 256);
|
||||
GetDateFormatA(LOCALE_USER_DEFAULT, 0, NULL, NULL, bf1, 256);
|
||||
wstring meos = getMeosCompectVersion();
|
||||
fout << toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS "
|
||||
<< toUTF8(meos) << "</i></a>: " << bf1 << " "<< bf2 << "\n";
|
||||
fout << gdioutput::toUTF8(lang.tl("Skapad av ")) + "<a href=\"http://www.melin.nu/meos\" target=\"_blank\"><i>MeOS "
|
||||
<< gdioutput::toUTF8(meos) << "</i></a>: " << bf1 << " " << bf2 << "\n";
|
||||
fout << "</p><br>\n";
|
||||
}
|
||||
fout << "</body>\n";
|
||||
fout << "</html>\n";
|
||||
|
||||
return true;
|
||||
fout << "</body>" << endl;
|
||||
fout << "</html>" << endl;
|
||||
}
|
||||
|
||||
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 ¶m, 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
114
code/HTMLWriter.h
Normal 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 ¶m, 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);
|
||||
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -55,6 +55,9 @@ MeOSFeatures::MeOSFeatures(void)
|
||||
addHead("Rogaining");
|
||||
add(Rogaining, L"RO", "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) {
|
||||
@ -239,6 +242,8 @@ void MeOSFeatures::loadDefaults(oEvent &oe) {
|
||||
|
||||
void MeOSFeatures::useAll(oEvent &oe) {
|
||||
for (size_t k = 0; k < desc.size(); k++) {
|
||||
if (desc[k].feat == NoCourses)
|
||||
continue;
|
||||
if (desc[k].feat != _Head)
|
||||
features.insert(desc[k].feat);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -50,6 +50,7 @@ public:
|
||||
DrawStartList,
|
||||
Bib,
|
||||
RunnerDb,
|
||||
NoCourses,
|
||||
};
|
||||
|
||||
private:
|
||||
@ -97,6 +98,9 @@ public:
|
||||
const string &getDescription(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;
|
||||
void deserialize(const wstring &input, oEvent &oe);
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
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,
|
||||
const list<RectangleInfo> &rects,
|
||||
bool invertHeightY,
|
||||
bool respectPageBreak,
|
||||
vector<RenderedPage> &pages);
|
||||
|
||||
wstring pageInfo(const RenderedPage &page) const;
|
||||
@ -68,6 +69,7 @@ struct PageInfo {
|
||||
struct RenderedPage {
|
||||
int nPage; // This page number
|
||||
wstring info;
|
||||
bool startChapter = false;
|
||||
vector<PrintTextInfo> text;
|
||||
vector<RectangleInfo> rectangles;
|
||||
__int64 checkSum;
|
||||
|
||||
@ -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 "meos_util.h"
|
||||
#include "restserver.h"
|
||||
@ -8,7 +30,7 @@
|
||||
|
||||
int AutomaticCB(gdioutput *gdi, int type, void *data);
|
||||
|
||||
RestService::RestService() : AutoMachine("Informationsserver"), port(-1) {
|
||||
RestService::RestService() : AutoMachine("Informationsserver", Machines::mInfoService), port(-1) {
|
||||
}
|
||||
|
||||
RestService::~RestService() {
|
||||
@ -30,19 +52,62 @@ void RestService::save(oEvent &oe, gdioutput &gdi) {
|
||||
else
|
||||
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) {
|
||||
if (port == -1)
|
||||
port = oe.getPropertyInt("ServicePort", 2009);
|
||||
|
||||
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"");
|
||||
|
||||
if (!server)
|
||||
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));
|
||||
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.addString("", 10, "help:rest");
|
||||
@ -65,7 +130,31 @@ void RestService::status(gdioutput &gdi) {
|
||||
gdi.addButton("Update", "Uppdatera").setHandler(this);
|
||||
gdi.dropLine(0.6);
|
||||
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);
|
||||
@ -87,9 +176,13 @@ void RestService::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
||||
if (bi.id == "Update") {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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) {
|
||||
RunnerWDBEntry *dbe = getRunnerById(int(r.getExtIdentifier()));
|
||||
if (dbe) {
|
||||
dbe->dbe().cardNo = r.CardNo;
|
||||
dbe->dbe().cardNo = r.getCardNo();
|
||||
return; // Do not change too much in runner from national database
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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);
|
||||
wcsncpy(card.lastName, lastName.c_str(), 20);
|
||||
wcsncpy_s(card.lastName, lastName.c_str(), 20);
|
||||
|
||||
memcpy(firstNameByte, data+32+20, 20);
|
||||
firstNameByte[20] = 0;
|
||||
@ -1698,7 +1698,7 @@ bool SportIdent::getCard6Data(BYTE *data, SICard &card)
|
||||
}
|
||||
|
||||
string2Wide(firstNameByte, firstName);
|
||||
wcsncpy(card.firstName, firstName.c_str(), 20);
|
||||
wcsncpy_s(card.firstName, firstName.c_str(), 20);
|
||||
|
||||
data+=128-16;
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -36,7 +36,7 @@ bool getDesktopFile(wchar_t *fileNamePath, const wchar_t *fileName, const wchar_
|
||||
bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName);
|
||||
|
||||
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);
|
||||
string uniqueTag(const char *base);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -44,6 +44,7 @@
|
||||
|
||||
#include "gdiconstants.h"
|
||||
#include "meosexception.h"
|
||||
#include "HTMLWriter.h"
|
||||
|
||||
static TabAuto *tabAuto = 0;
|
||||
int AutoMachine::uniqueId = 1;
|
||||
@ -212,7 +213,7 @@ void TabAuto::timerCallback(gdioutput &gdi)
|
||||
|
||||
DWORD d=0;
|
||||
if (reload && !editMode && gdi.getData("AutoPage", d) && d)
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
|
||||
void TabAuto::setTimer(AutoMachine *am)
|
||||
@ -259,7 +260,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
if (sm)
|
||||
sm->saveSettings(gdi);
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="Result") {
|
||||
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"));
|
||||
|
||||
wstring file = gdi.browseForSave(ext, L"html", index);
|
||||
if (!file.empty())
|
||||
if (!file.empty()) {
|
||||
gdi.setText("ExportFile", file);
|
||||
oe->setProperty("LastExportTarget", file);
|
||||
}
|
||||
}
|
||||
else if (bu.id == "BrowseScript") {
|
||||
vector< pair<wstring, wstring> > ext;
|
||||
@ -288,9 +291,11 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
gdi.setInputStatus("ExportScript", stat);
|
||||
gdi.setInputStatus("BrowseFile", stat);
|
||||
gdi.setInputStatus("BrowseScript", stat);
|
||||
if (gdi.hasField("HTMLRefresh")) {
|
||||
gdi.setInputStatus("HTMLRefresh", stat);
|
||||
gdi.setInputStatus("StructuredExport", stat);
|
||||
}
|
||||
}
|
||||
else if (bu.id == "DoPrint") {
|
||||
bool stat = gdi.isChecked(bu.id);
|
||||
gdi.setInputStatus("PrinterSetup", stat);
|
||||
@ -339,9 +344,11 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
prm->doPrint = gdi.isChecked("DoPrint");
|
||||
prm->exportFile = gdi.getText("ExportFile");
|
||||
prm->exportScript = gdi.getText("ExportScript");
|
||||
|
||||
if (!prm->readOnly) {
|
||||
prm->structuredExport = gdi.isChecked("StructuredExport");
|
||||
prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
|
||||
if (!prm->readOnly) {
|
||||
|
||||
gdi.getSelection("Classes", prm->classesToPrint);
|
||||
|
||||
ListBoxInfo lbi;
|
||||
@ -350,6 +357,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
par.selection=prm->classesToPrint;
|
||||
par.listCode = EStdListType(lbi.data);
|
||||
par.pageBreak = gdi.isChecked("PageBreak");
|
||||
par.showHeader = gdi.isChecked("ShowHeader");
|
||||
par.showInterTimes = gdi.isChecked("ShowInterResults");
|
||||
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
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->pageBreak = gdi.isChecked("PageBreak");
|
||||
prm->showHeader = gdi.isChecked("ShowHeader");
|
||||
|
||||
prm->showInterResult = gdi.isChecked("ShowInterResults");
|
||||
prm->splitAnalysis = gdi.isChecked("SplitAnalysis");
|
||||
prm->synchronize=true; //To force continuos data sync.
|
||||
setTimer(prm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -401,7 +411,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
setTimer(sm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="Save") { // General save
|
||||
AutoMachine *sm=getMachine(bu.getExtraInt());
|
||||
@ -410,7 +420,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
setTimer(sm);
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="StartPrewarning") {
|
||||
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");
|
||||
gdi.getSelection("Controls", pwm->controls);
|
||||
|
||||
oe->synchronizeList(oLPunchId);
|
||||
oe->synchronizeList(oListId::oLPunchId);
|
||||
oe->clearPrewarningSounds();
|
||||
|
||||
pwm->synchronizePunches=true;
|
||||
@ -432,7 +442,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
}
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id=="StartPunch") {
|
||||
|
||||
@ -452,17 +462,17 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
}
|
||||
}
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "Cancel") {
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "Stop") {
|
||||
if (bu.getExtraInt())
|
||||
stopMachine(getMachine(bu.getExtraInt()));
|
||||
|
||||
updateSyncInfo();
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
else if (bu.id == "PrinterSetup") {
|
||||
PrintResultMachine *prm =
|
||||
@ -479,7 +489,7 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
||||
if (prm) {
|
||||
prm->process(gdi, oe, SyncNone);
|
||||
setTimer(prm);
|
||||
loadPage(gdi);
|
||||
loadPage(gdi, false);
|
||||
}
|
||||
}
|
||||
else if (bu.id == "SelectAll") {
|
||||
@ -540,8 +550,11 @@ bool TabAuto::stopMachine(AutoMachine *am)
|
||||
|
||||
void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) {
|
||||
editMode=true;
|
||||
bool createNew = (sm==0);
|
||||
if (!sm) {
|
||||
bool createNew = (sm==0) || (ms == Machines::Unknown);
|
||||
if (sm) {
|
||||
ms = sm->getType();
|
||||
}
|
||||
else {
|
||||
sm = AutoMachine::construct(ms);
|
||||
machines.push_back(sm);
|
||||
}
|
||||
@ -576,7 +589,7 @@ void TabAuto::killMachines()
|
||||
AutoMachine::resetGlobalId();
|
||||
}
|
||||
|
||||
bool TabAuto::loadPage(gdioutput &gdi)
|
||||
bool TabAuto::loadPage(gdioutput &gdi, bool showSettingsLast)
|
||||
{
|
||||
oe->checkDB();
|
||||
tabAuto=this;
|
||||
@ -587,8 +600,8 @@ bool TabAuto::loadPage(gdioutput &gdi)
|
||||
int storedOY = 0;
|
||||
int storedOX = 0;
|
||||
if (isAP) {
|
||||
storedOY = gdi.GetOffsetY();
|
||||
storedOX = gdi.GetOffsetX();
|
||||
storedOY = gdi.getOffsetY();
|
||||
storedOX = gdi.getOffsetX();
|
||||
}
|
||||
|
||||
gdi.clearPage(false);
|
||||
@ -652,7 +665,8 @@ bool TabAuto::loadPage(gdioutput &gdi)
|
||||
if (isAP) {
|
||||
gdi.setOffset(storedOY, storedOY, true);
|
||||
}
|
||||
|
||||
if (showSettingsLast && !machines.empty())
|
||||
settings(gdi, *machines.rbegin(), Machines::Unknown);
|
||||
gdi.refresh();
|
||||
return true;
|
||||
}
|
||||
@ -693,7 +707,7 @@ void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool c
|
||||
|
||||
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
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);
|
||||
|
||||
if (created) {
|
||||
@ -716,9 +730,15 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.addButton("BrowseFile", "Bläddra...", AutomaticCB);
|
||||
gdi.setCX(cx);
|
||||
gdi.dropLine(2.3);
|
||||
if (!readOnly) {
|
||||
gdi.addCheckbox("StructuredExport", "Strukturerat exportformat", 0, structuredExport);
|
||||
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.addInput("ExportScript", exportScript, 32, 0, L"Skript att köra efter export:");
|
||||
gdi.dropLine(0.7);
|
||||
@ -730,13 +750,14 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.setInputStatus("ExportScript", doExport);
|
||||
gdi.setInputStatus("BrowseFile", doExport);
|
||||
gdi.setInputStatus("BrowseScript", doExport);
|
||||
gdi.setInputStatus("StructuredExport", doExport);
|
||||
gdi.setInputStatus("HTMLRefresh", doExport);
|
||||
gdi.setInputStatus("PrinterSetup", doPrint);
|
||||
|
||||
if (!readOnly) {
|
||||
gdi.setInputStatus("StructuredExport", doExport);
|
||||
gdi.setInputStatus("HTMLRefresh", doExport);
|
||||
|
||||
gdi.fillDown();
|
||||
gdi.addString("", 1, "Listval");
|
||||
gdi.addString("", fontMediumPlus, "Listval");
|
||||
gdi.dropLine();
|
||||
gdi.fillRight();
|
||||
gdi.addListBox("Classes", 150, 300, 0, L"", L"", true);
|
||||
@ -771,6 +792,8 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
gdi.selectItemByData("LegNumber", listInfo.getLegNumberCoded());
|
||||
|
||||
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, pageBreak);
|
||||
gdi.addCheckbox("ShowHeader", "Visa rubrik", 0, showHeader);
|
||||
|
||||
gdi.addCheckbox("ShowInterResults", "Visa mellantider", 0, showInterResult,
|
||||
"Mellantider visas för namngivna kontroller.");
|
||||
gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, splitAnalysis);
|
||||
@ -784,7 +807,8 @@ void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -804,7 +828,7 @@ void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
if (doPrint) {
|
||||
gdiPrint.refresh();
|
||||
try {
|
||||
gdiPrint.print(po, oe);
|
||||
gdiPrint.print(po, oe, true, false, listInfo.getParam().pageBreak);
|
||||
}
|
||||
catch (const meosException &ex) {
|
||||
printError = ex.wwhat();
|
||||
@ -814,10 +838,19 @@ void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
||||
}
|
||||
if (doExport) {
|
||||
if (!exportFile.empty()) {
|
||||
checkWriteAccess(exportFile);
|
||||
wstring tExport = exportFile + L"~";
|
||||
if (!readOnly) {
|
||||
if (structuredExport)
|
||||
gdiPrint.writeTableHTML(exportFile, oe->getName(), htmlRefresh);
|
||||
HTMLWriter::writeTableHTML(gdiPrint, tExport, oe->getName(), htmlRefresh, 1.0);
|
||||
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()) {
|
||||
ShellExecute(NULL, NULL, exportScript.c_str(), exportFile.c_str(), NULL, SW_HIDE);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -44,6 +44,9 @@ enum Machines {
|
||||
mOnlineInput,
|
||||
mSaveBackup,
|
||||
mInfoService,
|
||||
|
||||
mMySQLReconnect,
|
||||
Unknown = -1,
|
||||
};
|
||||
|
||||
class AutoMachine
|
||||
@ -51,6 +54,8 @@ class AutoMachine
|
||||
private:
|
||||
int myid;
|
||||
static int uniqueId;
|
||||
const Machines type;
|
||||
|
||||
protected:
|
||||
bool editMode;
|
||||
|
||||
@ -76,7 +81,12 @@ public:
|
||||
virtual void status(gdioutput &gdi) = 0;
|
||||
virtual bool stop() {return true;}
|
||||
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) {}
|
||||
virtual ~AutoMachine() = 0 {}
|
||||
};
|
||||
@ -93,6 +103,7 @@ protected:
|
||||
PrinterObject po;
|
||||
set<int> classesToPrint;
|
||||
bool pageBreak;
|
||||
bool showHeader;
|
||||
bool showInterResult;
|
||||
bool splitAnalysis;
|
||||
bool notShown;
|
||||
@ -112,9 +123,18 @@ public:
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
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;
|
||||
pageBreak = true;
|
||||
showHeader = false;
|
||||
showInterResult = true;
|
||||
notShown = true;
|
||||
splitAnalysis = true;
|
||||
@ -126,9 +146,10 @@ public:
|
||||
structuredExport = true;
|
||||
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;
|
||||
pageBreak = true;
|
||||
showHeader = false;
|
||||
showInterResult = true;
|
||||
notShown = true;
|
||||
splitAnalysis = true;
|
||||
@ -160,7 +181,7 @@ public:
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
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);}
|
||||
void status(gdioutput &gdi);
|
||||
void process(gdioutput &gdi, oEvent *oe, AutoSyncType ast);
|
||||
PrewarningMachine():AutoMachine("Förvarningsröst") {}
|
||||
PrewarningMachine():AutoMachine("Förvarningsröst", Machines::mPrewarningMachine) {}
|
||||
friend class TabAuto;
|
||||
};
|
||||
|
||||
@ -212,7 +233,7 @@ public:
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void status(gdioutput &gdi);
|
||||
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;
|
||||
};
|
||||
|
||||
@ -228,7 +249,7 @@ public:
|
||||
void settings(gdioutput &gdi, oEvent &oe, bool created);
|
||||
void status(gdioutput &gdi);
|
||||
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;
|
||||
};
|
||||
|
||||
@ -271,7 +292,10 @@ public:
|
||||
int processButton(gdioutput &gdi, const ButtonInfo &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";}
|
||||
TabType getType() const {return TAutoTab;}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -42,6 +42,7 @@
|
||||
#include "gdifonts.h"
|
||||
#include "oEventDraw.h"
|
||||
#include "MeOSFeatures.h"
|
||||
#include "qualification_final.h"
|
||||
|
||||
extern pEvent gEvent;
|
||||
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)
|
||||
{
|
||||
return ci1.firstStart>ci2.firstStart;
|
||||
@ -237,6 +255,8 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id == "AssignCourses") {
|
||||
set<int> selectedCourses, selectedLegs;
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
|
||||
gdi.getSelection("AllCourses", selectedCourses);
|
||||
gdi.getSelection("AllStages", selectedLegs);
|
||||
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;
|
||||
for (size_t k = 0; k < forkingSetup.size(); k++) {
|
||||
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 {
|
||||
empty = false;
|
||||
@ -262,7 +282,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
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);
|
||||
@ -374,8 +394,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
pc->setNumStages(0);
|
||||
pc->synchronize();
|
||||
gdi.restore();
|
||||
gdi.enableInput("MultiCourse", true);
|
||||
gdi.enableInput("Courses");
|
||||
selectClass(gdi, ClassId);
|
||||
}
|
||||
else if (bi.id=="SetNStage") {
|
||||
if (!checkClassSelected(gdi))
|
||||
@ -441,8 +460,10 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
save(gdi, false); //Clears and reloads
|
||||
|
||||
if (gdi.hasField("Courses")) {
|
||||
gdi.selectItemByData("Courses", -2);
|
||||
gdi.disableInput("Courses");
|
||||
}
|
||||
oe->setupRelay(*pc, newType, nstages, st);
|
||||
|
||||
if (gdi.hasField("MAdd")) {
|
||||
@ -458,6 +479,7 @@ int TabClass::multiCB(gdioutput &gdi, int type, void *data)
|
||||
pc->synchronize();
|
||||
gdi.restore();
|
||||
gdi.enableInput("MultiCourse", true);
|
||||
if (gdi.hasField("Courses"))
|
||||
gdi.enableInput("Courses");
|
||||
oe->adjustTeamMultiRunners(pc);
|
||||
}
|
||||
@ -837,6 +859,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
|
||||
if (classes.empty()) {
|
||||
gdi.dropLine();
|
||||
gdi.addButton("DrawMode", L"Återgå", ClassesCB);
|
||||
gdi.scrollToBottom();
|
||||
throw meosException("Ingen klass vald.");
|
||||
}
|
||||
|
||||
@ -855,8 +880,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id=="DoDrawAll") {
|
||||
readClassSettings(gdi);
|
||||
int method = gdi.getSelectedItem("Method").first;
|
||||
bool soft = method == DMSOFT;
|
||||
oEvent::DrawMethod method = (oEvent::DrawMethod)gdi.getSelectedItem("Method").first;
|
||||
int pairSize = gdi.getSelectedItem("PairSize").first;
|
||||
|
||||
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();
|
||||
it != specs.end(); ++it) {
|
||||
oe->drawList(it->second, soft, pairSize, oEvent::drawAll);
|
||||
oe->drawList(it->second, method, pairSize, oEvent::DrawType::DrawAll);
|
||||
}
|
||||
|
||||
oe->addAutoBib();
|
||||
@ -944,6 +968,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
prepareForDrawing(gdi);
|
||||
}
|
||||
else if (bi.id == "DrawMode") {
|
||||
if (gdi.hasField("Name"))
|
||||
save(gdi, false);
|
||||
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.popX();
|
||||
|
||||
gdi.addSelection("Method", 200, 200, 0, L"Metod:");
|
||||
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
|
||||
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
|
||||
gdi.selectItemByData("Method", getDefaultMethod({ DMRandom, DMSOFT }));
|
||||
createDrawMethod(gdi);
|
||||
|
||||
gdi.fillDown();
|
||||
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;
|
||||
}
|
||||
|
||||
int method = gdi.getSelectedItem("Method").first;
|
||||
bool useSoft = method == DMSOFT;
|
||||
oEvent::DrawMethod method = (oEvent::DrawMethod)gdi.getSelectedItem("Method").first;
|
||||
|
||||
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);
|
||||
oe->automaticDrawAll(gdi, firstStart, minInterval, vacances,
|
||||
lateBefore, useSoft, pairSize);
|
||||
lateBefore, method, pairSize);
|
||||
oe->addAutoBib();
|
||||
gdi.scrollToBottom();
|
||||
gdi.addButton("Cancel", "Återgå", ClassesCB);
|
||||
@ -1262,6 +1294,9 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
readDrawInfo(gdi, drawInfo);
|
||||
if (drawInfo.baseInterval <= 0 || drawInfo.baseInterval == NOTIME)
|
||||
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)
|
||||
throw meosException("Ogiltigt minimalt intervall.");
|
||||
if (drawInfo.minClassInterval > drawInfo.maxClassInterval || drawInfo.maxClassInterval == NOTIME)
|
||||
@ -1277,12 +1312,6 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
|
||||
gdi.enableEditControls(false);
|
||||
|
||||
if (drawInfo.firstStart<=0) {
|
||||
drawInfo.baseInterval = 0;
|
||||
gdi.addString("", 0, "Raderar starttider...");
|
||||
}
|
||||
|
||||
oe->optimizeStartOrder(gdi, drawInfo, cInfo);
|
||||
|
||||
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) {
|
||||
vector<ClassDrawSpecification> spec;
|
||||
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)
|
||||
@ -1363,7 +1392,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
return classCB(gdi, type, &bi);
|
||||
}
|
||||
else if (bi.id == "DrawAllBefore" || bi.id == "DrawAllAfter") {
|
||||
oe->drawRemaining(true, bi.id == "DrawAllAfter");
|
||||
oe->drawRemaining(oEvent::DrawMethod::MeOS, bi.id == "DrawAllAfter");
|
||||
oe->addAutoBib();
|
||||
loadPage(gdi);
|
||||
}
|
||||
@ -1373,7 +1402,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
DWORD cid=ClassId;
|
||||
pClass pc = oe->getClass(cid);
|
||||
DrawMethod method = DrawMethod(gdi.getSelectedItem("Method").first);
|
||||
oEvent::DrawMethod method = oEvent::DrawMethod(gdi.getSelectedItem("Method").first);
|
||||
|
||||
int interval = 0;
|
||||
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.");
|
||||
|
||||
|
||||
oEvent::DrawType dtype(oEvent::drawAll);
|
||||
oEvent::DrawType dtype(oEvent::DrawType::DrawAll);
|
||||
if (bi.id=="DoDrawAfter")
|
||||
dtype = oEvent::remainingAfter;
|
||||
dtype = oEvent::DrawType::RemainingAfter;
|
||||
else if (bi.id=="DoDrawBefore")
|
||||
dtype = oEvent::remainingBefore;
|
||||
dtype = oEvent::DrawType::RemainingBefore;
|
||||
else {
|
||||
if (warnDrawStartTime(gdi, t, false))
|
||||
return 0;
|
||||
@ -1435,24 +1464,24 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
if (gdi.hasField("ScaleFactor"))
|
||||
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;
|
||||
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);
|
||||
else if (method == DMPursuit || method == DMReversePursuit) {
|
||||
else if (method == oEvent::DrawMethod::Pursuit || method == oEvent::DrawMethod::ReversePursuit) {
|
||||
oe->drawPersuitList(cid, t, restartTime, maxTime,
|
||||
interval, pairSize,
|
||||
method == DMReversePursuit,
|
||||
method == oEvent::DrawMethod::ReversePursuit,
|
||||
scaleFactor);
|
||||
}
|
||||
else if (method == DMSimultaneous) {
|
||||
else if (method == oEvent::DrawMethod::Simultaneous) {
|
||||
simultaneous(cid, time);
|
||||
}
|
||||
else if (method == DMSeeded) {
|
||||
else if (method == oEvent::DrawMethod::Seeded) {
|
||||
ListBoxInfo seedMethod;
|
||||
gdi.getSelectedItem("SeedMethod", seedMethod);
|
||||
wstring seedGroups = gdi.getText("SeedGroups");
|
||||
@ -1525,7 +1554,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
vector<ClassDrawSpecification> spec;
|
||||
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);
|
||||
}
|
||||
else if (bi.id=="Draw") {
|
||||
@ -1567,7 +1596,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
gdi.setRestorePoint("MultiDayDraw");
|
||||
|
||||
lastDrawMethod = NOMethod;
|
||||
lastDrawMethod = oEvent::DrawMethod::NOMethod;
|
||||
drawDialog(gdi, getDefaultMethod(getSupportedDrawMethods(multiDay)), *pc);
|
||||
}
|
||||
else if (bi.id == "HandleMultiDay") {
|
||||
@ -1578,15 +1607,15 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
if (!pc)
|
||||
throw std::exception("Class not found");
|
||||
|
||||
if (!gdi.isChecked(bi.id) && (lastDrawMethod == DMReversePursuit ||
|
||||
lastDrawMethod == DMPursuit)) {
|
||||
drawDialog(gdi, DMSOFT, *pc);
|
||||
if (!gdi.isChecked(bi.id) && (lastDrawMethod == oEvent::DrawMethod::ReversePursuit ||
|
||||
lastDrawMethod == oEvent::DrawMethod::Pursuit)) {
|
||||
drawDialog(gdi, oEvent::DrawMethod::MeOS, *pc);
|
||||
}
|
||||
else
|
||||
setMultiDayClass(gdi, gdi.isChecked(bi.id), lastDrawMethod);
|
||||
|
||||
}
|
||||
else if (bi.id == "QualificationFinal") {
|
||||
else if (bi.id == "QualificationFinal" || bi.id == "UpdateQF") {
|
||||
save(gdi, true);
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
if (!pc)
|
||||
@ -1599,6 +1628,32 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
pc->updateFinalClasses(0, true);
|
||||
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") {
|
||||
save(gdi, true);
|
||||
if (!checkClassSelected(gdi))
|
||||
@ -1722,6 +1777,28 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
pClass pc=oe->getClass(ClassId);
|
||||
if (!pc)
|
||||
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);
|
||||
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);
|
||||
gdi.addItem("Type", mt);
|
||||
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);
|
||||
vector< pair<wstring, size_t> > sp;
|
||||
for (int k = 2; k < 10; k++)
|
||||
sp.push_back(make_pair(itow(k), k));
|
||||
gdi.addItem("SplitInput", sp);
|
||||
gdi.selectFirstItem("SplitInput");
|
||||
|
||||
gdi.dropLine(3);
|
||||
gdi.popX();
|
||||
|
||||
updateSplitDistribution(gdi, 2, tot);
|
||||
}
|
||||
|
||||
updateSplitDistribution(gdi, numSplitDef, tot);
|
||||
}
|
||||
else if (bi.id=="DoSplit") {
|
||||
if (!checkClassSelected(gdi))
|
||||
@ -1761,9 +1859,17 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
ListBoxInfo lbi;
|
||||
gdi.getSelectedItem("Type", lbi);
|
||||
|
||||
int number = gdi.getSelectedItem("SplitInput").first;
|
||||
int number;
|
||||
if (gdi.hasData("NumCls")) {
|
||||
DWORD dn;
|
||||
number = gdi.getData("NumCls", dn);
|
||||
number = dn;
|
||||
}
|
||||
else {
|
||||
number = gdi.getSelectedItem("SplitInput").first;
|
||||
}
|
||||
vector<int> parts(number);
|
||||
|
||||
for (int k = 0; k < number; k++) {
|
||||
string id = "CLS" + itos(k);
|
||||
parts[k] = gdi.getTextNo(id, false);
|
||||
@ -1983,7 +2089,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
if (!pc)
|
||||
throw std::exception("Nullpointer exception");
|
||||
|
||||
drawDialog(gdi, DrawMethod(bi.data), *pc);
|
||||
drawDialog(gdi, oEvent::DrawMethod(bi.data), *pc);
|
||||
}
|
||||
}
|
||||
else if (type==GUI_INPUTCHANGE) {
|
||||
@ -2251,11 +2357,7 @@ void TabClass::showClassSettings(gdioutput &gdi)
|
||||
gdi.setCX(rc.left + gdi.scaleLength(10));
|
||||
gdi.setCY(rc.top + gdi.scaleLength(10));
|
||||
|
||||
gdi.addSelection("Method", 200, 200, 0, L"Metod:");
|
||||
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
|
||||
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
|
||||
|
||||
gdi.selectItemByData("Method", getDefaultMethod({DMRandom, DMSOFT}));
|
||||
createDrawMethod(gdi);
|
||||
|
||||
gdi.addSelection("PairSize", 150, 200, 0, L"Tillämpa parstart:");
|
||||
gdi.addItem("PairSize", getPairOptions());
|
||||
@ -2292,11 +2394,13 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
if (cid==0) {
|
||||
gdi.restore("", true);
|
||||
gdi.disableInput("MultiCourse", true);
|
||||
if (gdi.hasField("Courses"))
|
||||
gdi.enableInput("Courses");
|
||||
gdi.enableEditControls(false);
|
||||
gdi.setText("Name", L"");
|
||||
gdi.selectItemByData("Courses", -2);
|
||||
gdi.check("AllowQuickEntry", true);
|
||||
gdi.setText("NumberMaps", L"");
|
||||
|
||||
if (gdi.hasField("FreeStart"))
|
||||
gdi.check("FreeStart", false);
|
||||
@ -2333,6 +2437,7 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
|
||||
pc->synchronize();
|
||||
gdi.setText("Name", pc->getName());
|
||||
gdi.setTextZeroBlank("NumberMaps", pc->getNumberMaps(true));
|
||||
|
||||
gdi.setText("ClassType", pc->getType());
|
||||
gdi.setText("StartName", pc->getStart());
|
||||
@ -2368,16 +2473,46 @@ void TabClass::selectClass(gdioutput &gdi, int 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);
|
||||
|
||||
multiCourse(gdi, pc->getNumStages());
|
||||
gdi.refresh();
|
||||
|
||||
if (gdi.hasField("Courses")) {
|
||||
gdi.addItem("Courses", lang.tl("Flera banor"), -3);
|
||||
gdi.selectItemByData("Courses", -3);
|
||||
gdi.disableInput("Courses");
|
||||
gdi.check("CoursePool", pc->hasCoursePool());
|
||||
}
|
||||
|
||||
if (gdi.hasField("Unordered"))
|
||||
gdi.check("Unordered", pc->hasUnorderedLegs());
|
||||
@ -2432,10 +2567,12 @@ void TabClass::selectClass(gdioutput &gdi, int cid)
|
||||
else {
|
||||
gdi.restore("", true);
|
||||
gdi.enableInput("MultiCourse", true);
|
||||
if (gdi.hasField("Courses")) {
|
||||
gdi.enableInput("Courses");
|
||||
pCourse pcourse = pc->getCourse();
|
||||
gdi.selectItemByData("Courses", pcourse ? pcourse->getId() : -2);
|
||||
}
|
||||
}
|
||||
if (gdi.hasField("QualificationFinal"))
|
||||
gdi.setInputStatus("QualificationFinal", pc->getParentClass() == 0);
|
||||
|
||||
@ -2490,14 +2627,14 @@ void TabClass::legSetup(gdioutput &gdi)
|
||||
|
||||
void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
currentStage=-1;
|
||||
|
||||
bool simpleView = nLeg==1;
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
bool isQF = (pc && pc->isQualificationFinalClass());
|
||||
bool simpleView = nLeg==1 || isQF;
|
||||
|
||||
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) {
|
||||
pClass pc = oe->getClass(ClassId);
|
||||
if (pc) {
|
||||
pc->setNumStages(1);
|
||||
pc->setStartType(0, STDrawn, false);
|
||||
@ -2512,7 +2649,6 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
gdi.fillDown();
|
||||
gdi.newColumn();
|
||||
|
||||
|
||||
int cx=gdi.getCX(), cy=gdi.getCY();
|
||||
gdi.setCX(cx+10);
|
||||
gdi.setCY(cy+10);
|
||||
@ -2551,6 +2687,9 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false,
|
||||
"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.setRestorePoint("Courses");
|
||||
selectCourses(gdi, 0);
|
||||
@ -2627,6 +2766,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
}
|
||||
|
||||
gdi.dropLine(-0.1);
|
||||
if (oe->getMeOSFeatures().withCourses(oe))
|
||||
gdi.addButton(string("@Course")+legno, "Banor...", MultiCB);
|
||||
|
||||
gdi.fillDown();
|
||||
@ -2648,6 +2788,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
}
|
||||
|
||||
gdi.pushX();
|
||||
if (oe->getMeOSFeatures().withCourses(oe)) {
|
||||
gdi.fillRight();
|
||||
gdi.addCheckbox("CoursePool", "Använd banpool", MultiCB, false,
|
||||
"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.popX();
|
||||
}
|
||||
RECT rc;
|
||||
rc.left = cx;
|
||||
rc.right = gdi.getWidth()+10;
|
||||
@ -2676,7 +2818,7 @@ void TabClass::multiCourse(gdioutput &gdi, int nLeg) {
|
||||
|
||||
gdi.setRestorePoint("Courses");
|
||||
|
||||
if (nLeg==1)
|
||||
if (nLeg==1 && oe->getMeOSFeatures().withCourses(oe))
|
||||
gdi.sendCtrlMessage("@Course0");
|
||||
|
||||
}
|
||||
@ -2721,6 +2863,10 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
||||
ClassId=pc->getId();
|
||||
|
||||
pc->setName(name);
|
||||
if (gdi.hasField("NumberMaps")) {
|
||||
pc->setNumberMaps(gdi.getTextNo("NumberMaps"));
|
||||
}
|
||||
|
||||
if (gdi.hasField("StartName"))
|
||||
pc->setStart(gdi.getText("StartName"));
|
||||
|
||||
@ -2771,6 +2917,7 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
||||
pc->lockedClassAssignment(locked);
|
||||
}
|
||||
|
||||
if (gdi.hasField("Courses")) {
|
||||
int crs = gdi.getSelectedItem("Courses").first;
|
||||
|
||||
if (crs == 0) {
|
||||
@ -2784,6 +2931,7 @@ void TabClass::save(gdioutput &gdi, bool skipReload)
|
||||
pc->setCourse(0);
|
||||
else if (crs > 0)
|
||||
pc->setCourse(oe->getCourse(crs));
|
||||
}
|
||||
|
||||
if (pc->hasMultiCourse()) {
|
||||
|
||||
@ -2933,23 +3081,28 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
gdi.addInput("Name", L"", 14, ClassesCB, L"Klassnamn:");
|
||||
bool sameLineNameCourse = true;
|
||||
if (showAdvanced) {
|
||||
gdi.addCombo("ClassType", 100, 300, 0, L"Typ:");
|
||||
gdi.addCombo("ClassType", 80, 300, 0, L"Typ:");
|
||||
oe->fillClassTypes(gdi, "ClassType");
|
||||
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.popX();
|
||||
}
|
||||
|
||||
if (useCourse) {
|
||||
gdi.addSelection("Courses", 120, 400, ClassesCB, L"Bana:");
|
||||
oe->fillCourses(gdi, "Courses", true);
|
||||
gdi.addItem("Courses", lang.tl("Ingen bana"), -2);
|
||||
|
||||
}
|
||||
if (showMulti(false)) {
|
||||
gdi.dropLine(0.9);
|
||||
if (showMulti(true)) {
|
||||
if (showMulti(true) || !useCourse) {
|
||||
gdi.addButton("MultiCourse", "Flera banor/stafett...", ClassesCB);
|
||||
}
|
||||
else {
|
||||
@ -2957,6 +3110,9 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
}
|
||||
gdi.disableInput("MultiCourse");
|
||||
}
|
||||
else if (useCourse) {
|
||||
gdi.addInput("NumberMaps", L"", 6, ClassesCB, L"Antal kartor:");
|
||||
}
|
||||
|
||||
gdi.popX();
|
||||
if (showAdvanced) {
|
||||
@ -3077,7 +3233,7 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
func.push_back(ButtonData("QuickSettings", "Snabbinställningar", true));
|
||||
|
||||
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;
|
||||
funRect.right = gdi.getCX() - 7;
|
||||
@ -3107,7 +3263,7 @@ bool TabClass::loadPage(gdioutput &gdi)
|
||||
gdi.dropLine(2.5);
|
||||
|
||||
funRect.bottom = gdi.getCY();
|
||||
gdi.addRectangle(funRect, colorLightGreen);
|
||||
gdi.addRectangle(funRect, colorLightBlue);
|
||||
|
||||
gdi.popX();
|
||||
gdi.dropLine(0.5);
|
||||
@ -3246,22 +3402,25 @@ void TabClass::prepareForDrawing(gdioutput &gdi) {
|
||||
gdi.refresh();
|
||||
}
|
||||
|
||||
void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
oe->setProperty("DefaultDrawMethod", method);
|
||||
bool isInSameClass(oEvent::DrawMethod m1, oEvent::DrawMethod m2, const set<oEvent::DrawMethod> &cls) {
|
||||
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)
|
||||
return;
|
||||
|
||||
bool noUpdate = false;
|
||||
|
||||
if (lastDrawMethod == DMPursuit && method == DMReversePursuit)
|
||||
noUpdate = true;
|
||||
if (lastDrawMethod == DMReversePursuit && method == DMPursuit)
|
||||
if (isInSameClass(lastDrawMethod, method, { oEvent::DrawMethod::Pursuit,
|
||||
oEvent::DrawMethod::ReversePursuit }))
|
||||
noUpdate = true;
|
||||
|
||||
if (lastDrawMethod == DMRandom && method == DMSOFT)
|
||||
noUpdate = true;
|
||||
if (lastDrawMethod == DMSOFT && method == DMRandom)
|
||||
if (isInSameClass(lastDrawMethod, method, { oEvent::DrawMethod::Random,
|
||||
oEvent::DrawMethod::SOFT,
|
||||
oEvent::DrawMethod::MeOS }))
|
||||
noUpdate = true;
|
||||
|
||||
if (noUpdate) {
|
||||
@ -3292,7 +3451,7 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
|
||||
const bool multiDay = oe->hasPrevStage() && gdi.isChecked("HandleMultiDay");
|
||||
|
||||
if (method == DMSeeded) {
|
||||
if (method == oEvent::DrawMethod::Seeded) {
|
||||
gdi.addString("", 10, "help:seeding_info");
|
||||
gdi.dropLine(1);
|
||||
gdi.pushX();
|
||||
@ -3323,8 +3482,8 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
gdi.dropLine(1);
|
||||
}
|
||||
|
||||
if (method == DMRandom || method == DMSOFT || method == DMPursuit
|
||||
|| method == DMReversePursuit || method == DMSeeded) {
|
||||
if (method == oEvent::DrawMethod::Random || method == oEvent::DrawMethod::SOFT || method == oEvent::DrawMethod::Pursuit
|
||||
|| 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.addItem("PairSize", getPairOptions());
|
||||
gdi.selectItemByData("PairSize", pairSize);
|
||||
@ -3333,19 +3492,19 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
|
||||
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("TimeRestart", oe->getAbsTime(firstStart + 3600), 8, 0, L"Första omstartstid:");
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
for (unsigned k = 0; k < pc.getNumStages(); k++)
|
||||
gdi.addItem("Leg", lang.tl("Sträcka X#" + itos(k + 1)), k);
|
||||
@ -3373,12 +3532,12 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
|
||||
gdi.fillRight();
|
||||
|
||||
if (method != DMSimultaneous)
|
||||
if (method != oEvent::DrawMethod::Simultaneous)
|
||||
gdi.addButton("DoDraw", "Lotta klassen", ClassesCB, "Lotta om hela klassen");
|
||||
else
|
||||
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("DoDrawAfter", "Ej lottade, efter", ClassesCB, "Lotta löpare som saknar starttid");
|
||||
}
|
||||
@ -3399,33 +3558,35 @@ void TabClass::drawDialog(gdioutput &gdi, DrawMethod method, const oClass &pc) {
|
||||
lastDrawMethod = method;
|
||||
}
|
||||
|
||||
set<DrawMethod> TabClass::getSupportedDrawMethods(bool hasMulti) const {
|
||||
set<DrawMethod> base = { DMRandom, DMSOFT, DMClumped, DMSimultaneous, DMSeeded };
|
||||
set<oEvent::DrawMethod> TabClass::getSupportedDrawMethods(bool hasMulti) const {
|
||||
set<oEvent::DrawMethod> base = { oEvent::DrawMethod::Random, oEvent::DrawMethod::SOFT, oEvent::DrawMethod::Clumped,
|
||||
oEvent::DrawMethod::MeOS, oEvent::DrawMethod::Simultaneous, oEvent::DrawMethod::Seeded };
|
||||
if (hasMulti) {
|
||||
base.insert(DMPursuit);
|
||||
base.insert(DMReversePursuit);
|
||||
base.insert(oEvent::DrawMethod::Pursuit);
|
||||
base.insert(oEvent::DrawMethod::ReversePursuit);
|
||||
}
|
||||
|
||||
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.addItem("Method", lang.tl("Lottning"), DMRandom);
|
||||
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
|
||||
gdi.addItem("Method", lang.tl("Klungstart"), DMClumped);
|
||||
gdi.addItem("Method", lang.tl("Gemensam start"), DMSimultaneous);
|
||||
gdi.addItem("Method", lang.tl("Seedad lottning"), DMSeeded);
|
||||
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.addItem("Method", lang.tl("Klungstart"), int(oEvent::DrawMethod::Clumped));
|
||||
gdi.addItem("Method", lang.tl("Gemensam start"), int(oEvent::DrawMethod::Simultaneous));
|
||||
gdi.addItem("Method", lang.tl("Seedad lottning"), int(oEvent::DrawMethod::Seeded));
|
||||
|
||||
if (hasMulti) {
|
||||
gdi.addItem("Method", lang.tl("Jaktstart"), DMPursuit);
|
||||
gdi.addItem("Method", lang.tl("Omvänd jaktstart"), DMReversePursuit);
|
||||
gdi.addItem("Method", lang.tl("Jaktstart"), int(oEvent::DrawMethod::Pursuit));
|
||||
gdi.addItem("Method", lang.tl("Omvänd jaktstart"), int(oEvent::DrawMethod::ReversePursuit));
|
||||
}
|
||||
else if (defaultMethod > 10)
|
||||
defaultMethod = DMSOFT;
|
||||
else if (int(defaultMethod) > 10)
|
||||
defaultMethod = oEvent::DrawMethod::MeOS;
|
||||
|
||||
gdi.selectItemByData("Method", defaultMethod);
|
||||
gdi.selectItemByData("Method", int(defaultMethod));
|
||||
|
||||
if (gdi.hasField("Vacanses")) {
|
||||
gdi.setInputStatus("Vacanses", !hasMulti);
|
||||
@ -3706,6 +3867,8 @@ void TabClass::selectCourses(gdioutput &gdi, int legNo) {
|
||||
}
|
||||
|
||||
void TabClass::updateFairForking(gdioutput &gdi, pClass pc) const {
|
||||
if (!gdi.hasField("FairForking"))
|
||||
return;
|
||||
vector< vector<int> > forks;
|
||||
vector< vector<int> > forksC;
|
||||
set< pair<int, int> > unfairLegs;
|
||||
@ -3762,9 +3925,15 @@ void TabClass::defineForking(gdioutput &gdi, bool clearSettings) {
|
||||
gdi.dropLine(0.5);
|
||||
for (int k = 0; k < ns; k++) {
|
||||
LegTypes lt = pc->getLegType(k);
|
||||
if (lt != LTIgnore) {
|
||||
gdi.addString("leg"+ itos(k), 0, "Leg X: Do not modify.#" + itos(k+1));
|
||||
gdi.addItem("AllStages", lang.tl("Leg X#" + itos(k+1)), k);
|
||||
if (lt != LTIgnore && lt != LTExtra) {
|
||||
wstring lnum = pc->getLegNumber(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();
|
||||
}
|
||||
|
||||
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> > res;
|
||||
@ -4179,6 +4342,12 @@ void TabClass::setLockForkingState(gdioutput &gdi, bool poolState, bool lockStat
|
||||
while (gdi.hasField("@Course" + itos(legno))) {
|
||||
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) {
|
||||
@ -4275,6 +4444,7 @@ vector<DrawSettingsCSV> DrawSettingsCSV::read(gdioutput &gdi, const oEvent &oe,
|
||||
set<int> usedId;
|
||||
// Save settings with class
|
||||
int lineNo = 0;
|
||||
bool anyError = false;
|
||||
for (auto &row : data) {
|
||||
lineNo++;
|
||||
if (row.empty())
|
||||
@ -4285,8 +4455,8 @@ vector<DrawSettingsCSV> DrawSettingsCSV::read(gdioutput &gdi, const oEvent &oe,
|
||||
continue;
|
||||
|
||||
DrawSettingsCSV dl;
|
||||
try {
|
||||
|
||||
try {
|
||||
if (row.size() <= 7)
|
||||
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) {
|
||||
gdi.addString("", 0, exmsg).setColor(colorRed);
|
||||
anyError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyError && !output.empty()) {
|
||||
gdi.dropLine();
|
||||
gdi.refresh();
|
||||
Sleep(3000);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -75,10 +75,10 @@ class TabClass :
|
||||
map<int, ClassInfo> cInfoCache;
|
||||
|
||||
DrawInfo drawInfo;
|
||||
void setMultiDayClass(gdioutput &gdi, bool hasMulti, DrawMethod defaultMethod);
|
||||
set<DrawMethod> getSupportedDrawMethods(bool multiDay) const;
|
||||
void setMultiDayClass(gdioutput &gdi, bool hasMulti, oEvent::DrawMethod defaultMethod);
|
||||
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);
|
||||
|
||||
@ -90,7 +90,7 @@ class TabClass :
|
||||
bool hasWarnedStartTime;
|
||||
bool hasWarnedDirect;
|
||||
bool tableMode;
|
||||
DrawMethod lastDrawMethod;
|
||||
oEvent::DrawMethod lastDrawMethod;
|
||||
int lastSeedMethod;
|
||||
bool lastSeedPreventClubNb;
|
||||
bool lastSeedReverse;
|
||||
@ -138,7 +138,9 @@ class TabClass :
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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);
|
||||
oe->calculateTeamResults(false);
|
||||
oe->sortTeams(ClassStartTime, 0, true);
|
||||
oe->calculateResults(oEvent::RTClassResult);
|
||||
oe->calculateResults({}, oEvent::ResultType::ClassResult);
|
||||
oe->sortRunners(ClassStartTime);
|
||||
int pay, paid;
|
||||
{
|
||||
@ -561,7 +561,7 @@ int TabClub::clubCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
if (!file.empty()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -52,6 +52,8 @@
|
||||
#include "recorder.h"
|
||||
#include "testmeos.h"
|
||||
#include "importformats.h"
|
||||
#include "HTMLWriter.h"
|
||||
#include "metalist.h"
|
||||
|
||||
#include <Shellapi.h>
|
||||
#include <algorithm>
|
||||
@ -99,6 +101,9 @@ bool TabCompetition::save(gdioutput &gdi, bool write)
|
||||
bool longTimes = gdi.isChecked("LongTimes");
|
||||
wstring date = gdi.getText("Date");
|
||||
|
||||
if (!checkValidDate(date))
|
||||
throw meosException(L"Felaktigt datum 'X' (Använd YYYY-MM-DD)#" + date);
|
||||
|
||||
if (longTimes)
|
||||
zt = L"00:00:00";
|
||||
|
||||
@ -674,9 +679,8 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
if (club == cmp)
|
||||
club = L"";
|
||||
|
||||
csvparser csv;
|
||||
bool clubCsv = !club.empty() && csv.iscsv(club.c_str()) != 0;
|
||||
bool cmpCsv = !cmp.empty() && csv.iscsv(cmp.c_str()) != 0;
|
||||
bool clubCsv = !club.empty() && csvparser::iscsv(club) != csvparser::CSV::NoCSV;
|
||||
bool cmpCsv = !cmp.empty() && csvparser::iscsv(cmp) != csvparser::CSV::NoCSV;
|
||||
|
||||
if (cmpCsv) {
|
||||
if (!club.empty())
|
||||
@ -964,8 +968,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
vector<pTeam> newEntriesT, notTransferedT, failedTargetT;
|
||||
oe->transferResult(nextStage, method, newEntriesT, notTransferedT, failedTargetT);
|
||||
|
||||
nextStage.save();
|
||||
nextStage.transferListsAndSave(*oe);
|
||||
oe->updateTabs(true);
|
||||
gdi.dropLine();
|
||||
|
||||
@ -1549,7 +1552,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
switch (startType) {
|
||||
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;
|
||||
break;
|
||||
|
||||
@ -1569,12 +1572,12 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
cls += cnf.classWithoutCourse[k];
|
||||
}
|
||||
if (!gdi.ask(L"ask:missingcourse#" + cls)) {
|
||||
gdi.addString("", 0, "Skipper lottning");
|
||||
gdi.addString("", 0, "Skippar lottning");
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -1773,7 +1776,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), li);
|
||||
gdioutput tGdi("temp", gdi.getScale());
|
||||
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());
|
||||
}
|
||||
loadPage(gdi);
|
||||
@ -1858,7 +1861,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
oe->generateListInfo(par, gdi.getLineHeight(), li);
|
||||
gdioutput tGdi("temp", gdi.getScale());
|
||||
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());
|
||||
}
|
||||
|
||||
@ -2337,7 +2340,7 @@ int TabCompetition::restoreCB(gdioutput &gdi, int type, void *data) {
|
||||
void TabCompetition::listBackups(gdioutput &gdi) {
|
||||
wchar_t bf[260];
|
||||
getUserFile(bf, L"");
|
||||
int yo = gdi.GetOffsetY();
|
||||
int yo = gdi.getOffsetY();
|
||||
gdi.clearPage(false);
|
||||
oe->enumerateBackups(bf);
|
||||
|
||||
@ -2393,10 +2396,17 @@ void TabCompetition::loadAboutPage(gdioutput &gdi) const
|
||||
gdi.addString("", 0, "se license.txt som levereras med programmet.");
|
||||
|
||||
gdi.dropLine();
|
||||
gdi.addString("", 1, "Vi stöder MeOS");
|
||||
vector<wstring> supp;
|
||||
vector<wstring> 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++)
|
||||
gdi.addStringUT(0, supp[k]);
|
||||
|
||||
@ -2492,7 +2502,7 @@ bool TabCompetition::loadPage(gdioutput &gdi)
|
||||
|
||||
copyrightLine(gdi);
|
||||
|
||||
gdi.addButton(gdi.GetPageX()-gdi.scaleLength(180),
|
||||
gdi.addButton(gdi.getPageX()-gdi.scaleLength(180),
|
||||
gdi.getCY()-gdi.getButtonHeight(),
|
||||
"Exit", "Avsluta", CompetitionCB);
|
||||
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, behåll resultat från annan klass"), oEvent::TransferAnyway);
|
||||
gdi.selectItemByData("ChangeClassType", lastChangeClassType);
|
||||
gdi.autoGrow("ChangeClassType");
|
||||
|
||||
if (expand) {
|
||||
gdi.fillDown();
|
||||
@ -3429,7 +3440,7 @@ void TabCompetition::entryForm(gdioutput &gdi, bool isGuide) {
|
||||
gdi.popX();
|
||||
|
||||
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.addButton("BrowseEntries", "Bläddra...", CompetitionCB).setExtra(L"FileNameRank");
|
||||
gdi.popX();
|
||||
@ -3445,7 +3456,7 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
|
||||
filename[3] = gdi.getText("FileName");
|
||||
filename[4] = gdi.getText("FileNameRank");
|
||||
|
||||
csvparser csv;
|
||||
//csvparser csv;
|
||||
|
||||
for (int i = 0; i<5; i++) {
|
||||
if (filename[i].empty())
|
||||
@ -3453,12 +3464,32 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
|
||||
|
||||
gdi.addString("", 0, L"Behandlar: X#" + filename[i]);
|
||||
|
||||
int type=csv.iscsv(filename[i]);
|
||||
|
||||
if (type) {
|
||||
csvparser::CSV type = csvparser::iscsv(filename[i]);
|
||||
if (i == 4 && (type == csvparser::CSV::OE || type == csvparser::CSV::Unknown)) {
|
||||
// Ranking
|
||||
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.refresh();
|
||||
gdi.setWaitCursor(true);
|
||||
@ -3467,7 +3498,7 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
|
||||
}
|
||||
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.refresh();
|
||||
gdi.setWaitCursor(true);
|
||||
@ -3476,14 +3507,16 @@ TabCompetition::FlowOperation TabCompetition::saveEntries(gdioutput &gdi, bool r
|
||||
}
|
||||
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.setWaitCursor(true);
|
||||
if (csv.importRAID(*oe, File)) {
|
||||
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 {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
fillOtherCourses(gdi, *pc);
|
||||
pCourse sh = pc->getShorterVersion();
|
||||
gdi.check("Shorten", sh != 0);
|
||||
gdi.setInputStatus("ShortCourse", sh != 0);
|
||||
if (sh) {
|
||||
gdi.selectItemByData("ShortCourse", sh->getId());
|
||||
}
|
||||
fillOtherCourses(gdi, *pc, cc != 0);
|
||||
auto sh = pc->getShorterVersion();
|
||||
gdi.check("Shorten", sh.first);
|
||||
gdi.setInputStatus("ShortCourse", sh.first);
|
||||
gdi.selectItemByData("ShortCourse", sh.second ? sh.second->getId() : 0);
|
||||
}
|
||||
else {
|
||||
gdi.setText("Name", L"");
|
||||
@ -283,13 +281,16 @@ void TabCourse::save(gdioutput &gdi, int canSwitchViewMode)
|
||||
if (gdi.isChecked("Shorten")) {
|
||||
ListBoxInfo ci;
|
||||
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
|
||||
throw meosException("Ange en avkortad banvariant");
|
||||
}
|
||||
else
|
||||
pc->setShorterVersion(0);
|
||||
pc->setShorterVersion(false, 0);
|
||||
|
||||
if (gdi.hasField("Rogaining")) {
|
||||
string t;
|
||||
@ -411,7 +412,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
if (!file.empty()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -420,6 +421,21 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.setInputStatus("CommonControl", w);
|
||||
if (w && gdi.getTextNo("CommonControl") == 0)
|
||||
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") {
|
||||
bool w = gdi.isChecked(bi.id);
|
||||
@ -512,10 +528,11 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.popX();
|
||||
gdi.dropLine(3);
|
||||
gdi.addSelection("Method", 200, 200, 0, L"Metod:");
|
||||
gdi.addItem("Method", lang.tl("Lottning"), DMRandom);
|
||||
gdi.addItem("Method", lang.tl("SOFT-lottning"), DMSOFT);
|
||||
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", getDefaultMethod());
|
||||
gdi.selectItemByData("Method", (int)getDefaultMethod());
|
||||
gdi.dropLine(0.9);
|
||||
gdi.fillRight();
|
||||
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 fs = oe->getRelativeTime(firstStart);
|
||||
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].vacances = vacances;
|
||||
courseDrawClasses[0].interval = iv;
|
||||
@ -549,7 +566,7 @@ int TabCourse::courseCB(gdioutput &gdi, int type, void *data)
|
||||
courseDrawClasses[k].interval = iv;
|
||||
}
|
||||
|
||||
oe->drawList(courseDrawClasses, method == DMSOFT, 1, oEvent::drawAll);
|
||||
oe->drawList(courseDrawClasses, method, 1, oEvent::DrawType::DrawAll);
|
||||
|
||||
oe->addAutoBib();
|
||||
|
||||
@ -852,13 +869,12 @@ bool TabCourse::loadPage(gdioutput &gdi) {
|
||||
|
||||
void TabCourse::runCourseImport(gdioutput& gdi, const wstring &filename,
|
||||
oEvent *oe, bool addClasses) {
|
||||
csvparser csv;
|
||||
if (csv.iscsv(filename)) {
|
||||
if (csvparser::iscsv(filename) != csvparser::CSV::NoCSV) {
|
||||
gdi.fillRight();
|
||||
gdi.pushX();
|
||||
gdi.addString("", 0, "Importerar OCAD csv-fil...");
|
||||
gdi.refreshFast();
|
||||
|
||||
csvparser csv;
|
||||
if (csv.importOCAD_CSV(*oe, filename, addClasses)) {
|
||||
gdi.addString("", 1, "Klart.").setColor(colorGreen);
|
||||
}
|
||||
@ -1044,7 +1060,7 @@ void TabCourse::fillCourseControls(gdioutput &gdi, const wstring &ctrl) {
|
||||
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;
|
||||
oe->fillCourses(ac, true);
|
||||
set<int> skipped;
|
||||
@ -1057,6 +1073,9 @@ void TabCourse::fillOtherCourses(gdioutput &gdi, oCourse &crs) {
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (!skipped.count(ac[k].second))
|
||||
out.push_back(ac[k]);
|
||||
@ -1093,12 +1112,14 @@ void TabCourse::saveLegLengths(gdioutput &gdi) {
|
||||
pc->synchronize(true);
|
||||
}
|
||||
|
||||
DrawMethod TabCourse::getDefaultMethod() const {
|
||||
int dm = oe->getPropertyInt("DefaultDrawMethod", DMSOFT);
|
||||
if (dm == DMRandom)
|
||||
return DMRandom;
|
||||
oEvent::DrawMethod TabCourse::getDefaultMethod() const {
|
||||
int dm = oe->getPropertyInt("DefaultDrawMethod", int(oEvent::DrawMethod::MeOS));
|
||||
if (dm == (int)oEvent::DrawMethod::Random)
|
||||
return oEvent::DrawMethod::Random;
|
||||
if (dm == (int)oEvent::DrawMethod::MeOS)
|
||||
return oEvent::DrawMethod::MeOS;
|
||||
else
|
||||
return DMSOFT;
|
||||
return oEvent::DrawMethod::SOFT;
|
||||
}
|
||||
|
||||
void TabCourse::clearCompetitionData() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -24,7 +24,6 @@
|
||||
#include "tabbase.h"
|
||||
|
||||
struct ClassDrawSpecification;
|
||||
enum DrawMethod;
|
||||
|
||||
class TabCourse :
|
||||
public TabBase
|
||||
@ -40,13 +39,13 @@ class TabCourse :
|
||||
wstring point_reduction;
|
||||
|
||||
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);
|
||||
|
||||
vector<ClassDrawSpecification> courseDrawClasses;
|
||||
|
||||
DrawMethod getDefaultMethod() const;
|
||||
oEvent::DrawMethod getDefaultMethod() const;
|
||||
|
||||
wstring encodeCourse(const wstring &in, bool firstStart, bool lastFinish);
|
||||
void refreshCourse(const wstring &text, gdioutput &gdi);
|
||||
|
||||
879
code/TabList.cpp
879
code/TabList.cpp
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -40,6 +40,7 @@ protected:
|
||||
bool lastSplitState;
|
||||
bool lastLargeSize;
|
||||
|
||||
wstring lastHtmlTarget;
|
||||
|
||||
EStdListType getTypeFromResultIndex(int ix) const;
|
||||
|
||||
@ -78,6 +79,9 @@ private:
|
||||
TabList(const TabList &);
|
||||
const TabList &operator = (const TabList &);
|
||||
|
||||
map<string, int> htmlTemplateTag2Id;
|
||||
map<int, wstring> html2IdToInfo;
|
||||
|
||||
string settingsTarget;
|
||||
oListParam tmpSettingsParam;
|
||||
void changeListSettingsTarget(gdioutput &oldWindow, gdioutput &newWindow);
|
||||
@ -93,8 +97,8 @@ private:
|
||||
static void getResultIndividual(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultClub(oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
static void getStartPatrol(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultPatrol(oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getStartPatrol(oEvent &oe, oListParam &par, ClassConfigInfo &cnf);
|
||||
static void getResultPatrol(oEvent &oe, oListParam &par, ClassConfigInfo &cnf);
|
||||
|
||||
static void getStartTeam(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 readSettings(gdioutput &gdi, oListParam &par, bool forResult);
|
||||
|
||||
public:
|
||||
/** Returns a collection of public lists. */
|
||||
void static getPublicLists(oEvent &oe, vector<oListParam> &lists);
|
||||
@ -121,8 +127,18 @@ public:
|
||||
void rebuildList(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 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 {
|
||||
Splits = 0,
|
||||
StartInfo = 1,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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) {
|
||||
oe->synchronizeList(oLCardId, true, true);
|
||||
oe->synchronizeList(oListId::oLCardId);
|
||||
TabSI &tsi = dynamic_cast<TabSI &>(*gdi.getTabs().get(TSITab));
|
||||
tsi.storedInfo.clear();
|
||||
|
||||
@ -545,11 +545,8 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
RunnerStatus originalStatus = r->getStatus();
|
||||
r->setName(name, true);
|
||||
|
||||
if (gdi.hasField("Bib")) {
|
||||
const wstring &bib = gdi.getText("Bib");
|
||||
wchar_t pat[32];
|
||||
int num = oClass::extractBibPattern(bib, pat);
|
||||
r->setBib(bib, num, num>0, false);
|
||||
if (dynamic_cast<InputInfo &>(gdi.getBaseInfo("PTime")).changed()) {
|
||||
savePunchTime(r, gdi);
|
||||
}
|
||||
|
||||
bool noSetStatus = false;
|
||||
@ -578,7 +575,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
const bool hireChecked = gdi.isChecked("RentCard");
|
||||
const bool hireState = r->isHiredCard();
|
||||
if (hireChecked && !hireState) {
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||
}
|
||||
else if (!hireChecked && hireState) {
|
||||
r->getDI().setInt("CardFee", 0);
|
||||
@ -638,6 +635,15 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
|
||||
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);
|
||||
|
||||
RunnerStatus sIn = (RunnerStatus)gdi.getSelectedItem("Status").first;
|
||||
@ -649,7 +655,7 @@ pRunner TabRunner::save(gdioutput &gdi, int runnerId, bool willExit) {
|
||||
vector<int> mp;
|
||||
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.");
|
||||
}
|
||||
|
||||
@ -963,7 +969,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
return 0;
|
||||
pRunner r = oe->getRunner(runnerId, 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));
|
||||
dst.loadEconomy(*settings, *r);
|
||||
}
|
||||
@ -1236,7 +1242,7 @@ int TabRunner::runnerCB(gdioutput &gdi, int type, void *data)
|
||||
(listenToPunches || oe->isReadOnly()) && currentMode == 5) {
|
||||
if (ei.getData() > 0) {
|
||||
vector<pRunner> rs;
|
||||
oe->getRunnersByCard(ei.getData(), rs);
|
||||
oe->getRunnersByCardNo(ei.getData(), true, oEvent::CardLookupProperty::Any, rs);
|
||||
if (!rs.empty()) {
|
||||
runnersToReport.resize(rs.size());
|
||||
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;
|
||||
|
||||
if (gdi.isChecked("RentCard")) {
|
||||
cardFee = oe->getDI().getInt("CardFee");
|
||||
cardFee = oe->getBaseCardFee();
|
||||
r->getDI().setInt("CardFee", cardFee);
|
||||
}
|
||||
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);
|
||||
currentMode = 5;
|
||||
|
||||
@ -1546,43 +1551,50 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
gdi.registerEvent("DataUpdate", RunnerCB);
|
||||
gdi.registerEvent("ReadCard", RunnerCB);
|
||||
|
||||
gdi.fillDown();
|
||||
oe->calculateResults(oEvent::RTClassResult);
|
||||
|
||||
if (runnerId > 0) {
|
||||
runnersToReport.resize(1);
|
||||
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;
|
||||
set<int> clsSet;
|
||||
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()) {
|
||||
pClass cls = r->getClassRef(true);
|
||||
if (cls && cls->getClassType() == oClassPatrol)
|
||||
if (cls && cls->getClassType() != oClassRelay)
|
||||
continue;
|
||||
|
||||
if (t == 0)
|
||||
t = r->getTeam();
|
||||
}
|
||||
}
|
||||
|
||||
if (runnersToReport.size() == 1)
|
||||
runnerId = runnersToReport[0].first;
|
||||
oe.calculateResults(clsSet, oEvent::ResultType::PreliminarySplitResults, true);
|
||||
oe.calculateResults(clsSet, oEvent::ResultType::ClassResult);
|
||||
|
||||
if (t == 0) {
|
||||
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 {
|
||||
oe->calculateTeamResults(false);
|
||||
oe.calculateTeamResults(false);
|
||||
|
||||
set<int> selectedRunners;
|
||||
bool selHasRes = false;
|
||||
for (size_t k = 0; k < runnersToReport.size(); k++) {
|
||||
selectedRunners.insert(runnersToReport[k].first);
|
||||
pRunner r = oe->getRunner(runnersToReport[k].first, 0);
|
||||
if (r->getStatus() != StatusUnknown)
|
||||
pRunner r = oe.getRunner(runnersToReport[k].first, 0);
|
||||
if (r && r->hasOnCourseResult())
|
||||
selHasRes = true;
|
||||
}
|
||||
|
||||
@ -1593,7 +1605,7 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
tInfo += L", +" + formatTime(t->getTimeAfter(-1));
|
||||
}
|
||||
else if (t->getStatus() != StatusUnknown) {
|
||||
tInfo += L" " + t->getStatusS();
|
||||
tInfo += L" " + t->getStatusS(true);
|
||||
}
|
||||
|
||||
gdi.addStringUT(fontMediumPlus, t->getClass(true));
|
||||
@ -1613,10 +1625,10 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
bool selected = selectedRunners.count(r->getId()) > 0;
|
||||
|
||||
if (selHasRes) {
|
||||
runnerReport(gdi, r->getId(), !selected);
|
||||
runnerReport(oe, gdi, r->getId(), !selected);
|
||||
}
|
||||
else {
|
||||
runnerReport(gdi, r->getId(), !nextSelected);
|
||||
runnerReport(oe, gdi, r->getId(), !nextSelected);
|
||||
}
|
||||
|
||||
visitedSelected |= selected;
|
||||
@ -1625,8 +1637,8 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
|
||||
}
|
||||
}
|
||||
|
||||
void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
|
||||
pRunner r = oe->getRunner(id, 0);
|
||||
void TabRunner::runnerReport(oEvent &oe, gdioutput &gdi, int id, bool compact) {
|
||||
pRunner r = oe.getRunner(id, 0);
|
||||
if (!r || ! r->getClassRef(false))
|
||||
return;
|
||||
|
||||
@ -1647,18 +1659,18 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
|
||||
|
||||
wstring str;
|
||||
if (r->getTeam() == 0) {
|
||||
str = oe->formatListString(lRunnerTimeStatus, r);
|
||||
str = oe.formatListString(lRunnerTimeStatus, r);
|
||||
}
|
||||
else {
|
||||
str = oe->formatListString(lTeamLegTimeStatus, r);
|
||||
str += L" (" + oe->formatListString(lRunnerTimeStatus, r) + L")";
|
||||
str = oe.formatListString(lTeamLegTimeStatus, r);
|
||||
str += L" (" + oe.formatListString(lRunnerTimeStatus, r) + L")";
|
||||
}
|
||||
|
||||
gdi.dropLine(0.3);
|
||||
|
||||
if (r->statusOK()) {
|
||||
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) {
|
||||
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)
|
||||
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()) {
|
||||
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()) {
|
||||
gdi.addString("", fontMedium, L"Bomtid: X #" + lost).setColor(colorDarkRed);
|
||||
}
|
||||
@ -1798,7 +1810,7 @@ void TabRunner::runnerReport(gdioutput &gdi, int id, bool compact) {
|
||||
}
|
||||
else {
|
||||
vector<pFreePunch> punches;
|
||||
oe->getPunchesForRunner(r->getId(), punches);
|
||||
oe.getPunchesForRunner(r->getId(), punches);
|
||||
|
||||
int lastT = r->getStartTime();
|
||||
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();
|
||||
if (t>0) {
|
||||
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) {
|
||||
wstring split = formatTimeHMS(t-st);
|
||||
if (lastT>0 && st != lastT && lastT < t)
|
||||
@ -2036,7 +2048,6 @@ void TabRunner::showInForestList(gdioutput &gdi)
|
||||
clearInForestData();
|
||||
bool hasDNS;
|
||||
oe->analyseDNS(unknown_dns, known_dns, known, unknown, hasDNS);
|
||||
oe->setupCardHash(false);
|
||||
if (!unknown.empty()) {
|
||||
gdi.dropLine();
|
||||
gdi.dropLine(0.5);
|
||||
@ -2070,8 +2081,6 @@ void TabRunner::showInForestList(gdioutput &gdi)
|
||||
else
|
||||
gdi.disableInput("SetUnknown");
|
||||
|
||||
oe->setupCardHash(true);
|
||||
|
||||
if (known.empty() && unknown.empty() && known_dns.empty()) {
|
||||
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);
|
||||
int c = r[k]->getCardNo();
|
||||
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) {
|
||||
gdi.addStringUT(yp, xp+550, 0, "(" + itos(c) + ")", 190);
|
||||
}
|
||||
@ -2186,7 +2202,6 @@ void disablePunchCourseChange(gdioutput &gdi)
|
||||
gdi.disableInput("PTime");
|
||||
gdi.setText("PTime", L"");
|
||||
gdi.selectItemByData("Punches", -1);
|
||||
|
||||
}
|
||||
|
||||
void disablePunchCourse(gdioutput &gdi)
|
||||
@ -2206,8 +2221,7 @@ void UpdateStatus(gdioutput &gdi, pRunner r)
|
||||
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;
|
||||
if (!rid)
|
||||
return 0;
|
||||
@ -2218,9 +2232,18 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.alert("Deltagaren måste sparas innan stämplingar kan hanteras.");
|
||||
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;
|
||||
|
||||
|
||||
if (type==GUI_LISTBOX){
|
||||
return gdi.sendCtrlMessage("AddC");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == GUI_LISTBOX) {
|
||||
ListBoxInfo bi = *(ListBoxInfo *)data;
|
||||
|
||||
if (bi.id == "Punches") {
|
||||
@ -2231,12 +2254,14 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
if (!punch)
|
||||
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.enableInput("SaveC");
|
||||
|
||||
gdi.enableInput("RemoveC");
|
||||
gdi.enableInput("PTime");
|
||||
}
|
||||
@ -2244,15 +2269,14 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.disableInput("SaveC");
|
||||
gdi.disableInput("RemoveC");
|
||||
gdi.setText("PTime", L"");
|
||||
gdi.disableInput("PTime");
|
||||
}
|
||||
disablePunchCourseAdd(gdi);
|
||||
}
|
||||
else if (bi.id == "Course") {
|
||||
if (signed(bi.data) >= 0) {
|
||||
pCourse pc = r->getCourse(true);
|
||||
|
||||
if (!pc) return 0;
|
||||
|
||||
gdi.enableInput("AddC");
|
||||
gdi.enableInput("AddAllC");
|
||||
}
|
||||
@ -2276,7 +2300,6 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
card->setCardNo(r->getCardNo());
|
||||
vector<int> mp;
|
||||
r->addPunches(card, mp);
|
||||
|
||||
}
|
||||
|
||||
if (bi.id == "AddC") {
|
||||
@ -2319,7 +2342,6 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
r->evaluateCard(true, mp);
|
||||
vector<int>::iterator it = mp.begin();
|
||||
|
||||
|
||||
while (it != mp.end()) {
|
||||
vector<int> nmp;
|
||||
r->evaluateCard(true, nmp, *it); //Add this punch
|
||||
@ -2337,13 +2359,13 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
UpdateStatus(gdi, r);
|
||||
}
|
||||
else if (bi.id == "SaveC") {
|
||||
//int time=oe->GetRelTime();
|
||||
|
||||
if (!savePunchTime(r, gdi))
|
||||
return false;
|
||||
ListBoxInfo lbi;
|
||||
|
||||
if (!gdi.getSelectedItem("Punches", lbi))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
pCard pc=r->getCard();
|
||||
|
||||
if (!pc) return 0;
|
||||
@ -2355,11 +2377,11 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
pc->setPunchTime(pp, gdi.getText("PTime"));
|
||||
|
||||
vector<int> mp;
|
||||
r->evaluateCard(true, mp);
|
||||
|
||||
//synchronize SQL
|
||||
card->synchronize();
|
||||
card->synchronize();*/
|
||||
vector<int> mp;
|
||||
r->synchronize();
|
||||
r->evaluateCard(true, mp);
|
||||
r->hasManuallyUpdatedTimeStatus();
|
||||
@ -2371,6 +2393,30 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
|
||||
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)
|
||||
{
|
||||
oe->reEvaluateAll(set<int>(), true);
|
||||
@ -2503,6 +2549,7 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
||||
if (numSL > 0)
|
||||
gdi.fillRight();
|
||||
|
||||
if (!oe->getMeOSFeatures().withoutCourses(*oe)) {
|
||||
gdi.addSelection("RCourse", numSL == 0 ? 220 : 180, 300, RunnerCB, L"Bana:");
|
||||
oe->fillCourses(gdi, "RCourse", true);
|
||||
gdi.addItem("RCourse", lang.tl("[Klassens bana]"), 0);
|
||||
@ -2524,6 +2571,7 @@ bool TabRunner::loadPage(gdioutput &gdi)
|
||||
gdi.addItem("NumShort", data);
|
||||
gdi.popX();
|
||||
}
|
||||
}
|
||||
|
||||
gdi.pushX();
|
||||
gdi.fillRight();
|
||||
@ -2777,9 +2825,9 @@ bool TabRunner::canSetFinish(pRunner r) const {
|
||||
pRunner TabRunner::warnDuplicateCard(int cno, pRunner r) {
|
||||
pRunner warnCardDupl = 0;
|
||||
|
||||
if (!r->getCard()) {
|
||||
if (!r->getCard() && cno != 0) {
|
||||
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++) {
|
||||
if (!r->canShareCard(allR[k], cno)) {
|
||||
warnCardDupl = allR[k];
|
||||
@ -2815,10 +2863,14 @@ int TabRunner::numShorteningLevels() const {
|
||||
map<int, int> known;
|
||||
int res = 0;
|
||||
for (size_t k = 0; k < allCrs.size(); k++) {
|
||||
pCourse sh = allCrs[k]->getShorterVersion();
|
||||
touch.clear();
|
||||
auto shInfo = allCrs[k]->getShorterVersion();
|
||||
pCourse cCourse = allCrs[k];
|
||||
int count = 0;
|
||||
if (shInfo.second) {
|
||||
pCourse sh = shInfo.second;
|
||||
touch.clear();
|
||||
while (sh && !touch.count(sh->getId())) {
|
||||
cCourse = sh;
|
||||
count++;
|
||||
map<int, int>::iterator r = known.find(sh->getId());
|
||||
if (r != known.end()) {
|
||||
@ -2826,8 +2878,18 @@ int TabRunner::numShorteningLevels() const {
|
||||
break;
|
||||
}
|
||||
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;
|
||||
res = max(res, count);
|
||||
}
|
||||
@ -2836,7 +2898,7 @@ int TabRunner::numShorteningLevels() const {
|
||||
|
||||
void TabRunner::updateNumShort(gdioutput &gdi, pCourse crs, pRunner r) {
|
||||
if (gdi.hasField("NumShort")) {
|
||||
if (crs && crs->getShorterVersion()) {
|
||||
if (crs && crs->getShorterVersion().first) {
|
||||
gdi.enableInput("NumShort");
|
||||
if (r)
|
||||
gdi.selectItemByData("NumShort", r->getNumShortening());
|
||||
@ -2871,7 +2933,6 @@ void TabRunner::autoGrowCourse(gdioutput &gdi) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TabRunner::EconomyHandler::init(oRunner &r) {
|
||||
oe = r.getEvent();
|
||||
runnerId = r.getId();
|
||||
@ -2938,7 +2999,6 @@ void TabRunner::EconomyHandler::save(gdioutput &gdi) {
|
||||
int paid = oe->interpretCurrency(gdi.getText("PaidAmount"));
|
||||
r.getDI().setInt("Paid", paid);
|
||||
|
||||
|
||||
if (paid != 0) {
|
||||
int m = gdi.getSelectedItem("").first;
|
||||
if (m != 1000)
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -71,11 +71,12 @@ private:
|
||||
vector<pRunner> known;
|
||||
vector<pRunner> unknown;
|
||||
void clearInForestData();
|
||||
bool savePunchTime(pRunner r, gdioutput &gdi);
|
||||
|
||||
PrinterObject splitPrinter;
|
||||
|
||||
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 showCardsList(gdioutput &gdi);
|
||||
@ -122,7 +123,7 @@ public:
|
||||
bool loadPage(gdioutput &gdi);
|
||||
bool loadPage(gdioutput &gdi, int runnerId);
|
||||
|
||||
|
||||
static void generateRunnerReport(oEvent &oe, gdioutput &gdi, vector<pair<int, bool>> &runnersToReport);
|
||||
|
||||
TabRunner(oEvent *oe);
|
||||
~TabRunner(void);
|
||||
|
||||
162
code/TabSI.cpp
162
code/TabSI.cpp
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -476,8 +476,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
else if (bi.id == "SaveCards") {
|
||||
int origin = bi.getExtraInt();
|
||||
gdi.restore("Help");
|
||||
oe->synchronizeList(oLCardId, true, false);
|
||||
oe->synchronizeList(oLRunnerId, false, true);
|
||||
oe->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
|
||||
for (size_t k = 0; k < cards.size(); k++)
|
||||
insertSICard(gdi, cards[k]);
|
||||
|
||||
@ -766,16 +765,17 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
pc->setName(gdi.getText("ClassName"));
|
||||
}
|
||||
|
||||
if (pc == 0) {
|
||||
if (pc == 0 && !gEvent->getMeOSFeatures().hasFeature(MeOSFeatures::NoCourses)) {
|
||||
pc = gEvent->addCourse(gdi.getText("ClassName"));
|
||||
for (unsigned i = 0; i < activeSIC.nPunch; i++)
|
||||
pc->addControl(activeSIC.Punch[i].Code);
|
||||
}
|
||||
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);
|
||||
|
||||
int year = 0;
|
||||
pRunner r = gEvent->addRunner(gdi.getText("Runners"), gdi.getText("Club", true),
|
||||
pclass->getId(), activeSIC.CardNumber, year, true);
|
||||
@ -815,8 +815,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
else if (bi.id == "EntryOK") {
|
||||
storedInfo.clear();
|
||||
oe->synchronizeList(oLRunnerId, true, false);
|
||||
oe->synchronizeList(oLCardId, false, true);
|
||||
oe->synchronizeList({ oListId::oLRunnerId, oListId::oLCardId });
|
||||
|
||||
wstring name = gdi.getText("Name");
|
||||
if (name.empty()) {
|
||||
@ -827,7 +826,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
pRunner r = oe->getRunner(rid, 0);
|
||||
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) {
|
||||
gdi.alert(L"Bricknummret är upptaget (X).#" + cardRunner->getName() + L", " + cardRunner->getClass(true));
|
||||
return 0;
|
||||
@ -835,19 +834,36 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
ListBoxInfo lbi;
|
||||
gdi.getSelectedItem("Class", lbi);
|
||||
|
||||
if (signed(lbi.data)<=0) {
|
||||
pClass clz = oe->getClass(lbi.data);
|
||||
if (!clz) {
|
||||
if (oe->getNumClasses() > 0) {
|
||||
gdi.alert(L"Ingen klass vald");
|
||||
return 0;
|
||||
}
|
||||
pClass pc = oe->getClassCreate(0, lang.tl(L"Öppen klass"));
|
||||
lbi.data = pc->getId();
|
||||
pc->setAllowQuickEntry(true);
|
||||
pc->synchronize();
|
||||
set<wstring> dmy;
|
||||
clz = oe->getClassCreate(0, lang.tl(L"Öppen klass"), dmy);
|
||||
lbi.data = clz->getId();
|
||||
clz->setAllowQuickEntry(true);
|
||||
clz->synchronize();
|
||||
}
|
||||
bool updated = false;
|
||||
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) {
|
||||
r = oe->addRunner(name, gdi.getText("Club", true), lbi.data, cardNo, year, true);
|
||||
@ -880,7 +896,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
oDataInterface di = r->getDI();
|
||||
|
||||
int cardFee = gdi.isChecked("RentCard") ? oe->getDI().getInt("CardFee") : 0;
|
||||
int cardFee = gdi.isChecked("RentCard") ? oe->getBaseCardFee() : 0;
|
||||
|
||||
di.setInt("CardFee", cardFee);
|
||||
di.setInt("Fee", lastFeeNum);
|
||||
r->setFlag(oRunner::FlagFeeSpecified, true);
|
||||
@ -889,12 +906,15 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
writePayMode(gdi, totFee, *r);
|
||||
|
||||
di.setString("Phone", gdi.getText("Phone"));
|
||||
|
||||
r->setFlag(oRunner::FlagTransferSpecified, gdi.hasField("AllStages"));
|
||||
r->setFlag(oRunner::FlagTransferNew, gdi.isChecked("AllStages"));
|
||||
|
||||
r->setStartTimeS(gdi.getText("StartTime"));
|
||||
|
||||
wstring bibIn = gdi.getText("Bib");
|
||||
wstring bib;
|
||||
if (bibIn.empty()) {
|
||||
switch (r->autoAssignBib()) {
|
||||
case oRunner::BibAssignResult::Assigned:
|
||||
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");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r->setBib(bibIn, 0, false, false);
|
||||
bib = L", " + lang.tl(L"Nummerlapp: ") + r->getBib();
|
||||
}
|
||||
r->synchronize();
|
||||
|
||||
gdi.restore("EntryLine");
|
||||
@ -949,6 +974,9 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
if (warnPayment) {
|
||||
gdi.addString("", fontMediumPlus, "Varning: avgiften kan ej faktureras").setColor(colorRed);
|
||||
}
|
||||
if (warnClassFull) {
|
||||
gdi.addString("", fontMediumPlus, "Varning: Kartorna är slut").setColor(colorRed);
|
||||
}
|
||||
|
||||
generateStartInfo(gdi, *r);
|
||||
|
||||
@ -1270,7 +1298,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
if (nr > 0) {
|
||||
r = oe->getRunnerByBibOrStartNo(text, false);
|
||||
if (r == 0)
|
||||
r = oe->getRunnerByCardNo(nr, 0, true, true);
|
||||
r = oe->getRunnerByCardNo(nr, 0, oEvent::CardLookupProperty::ForReadout);
|
||||
}
|
||||
|
||||
if (nr == 0 && text.size() > 2) {
|
||||
@ -1324,7 +1352,7 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.setInputStatus("TieOK", runnerMatchedId != -1);
|
||||
}
|
||||
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) {
|
||||
gdi.setText("Start", r->getStartTimeS());
|
||||
gdi.check("HasStart", false);
|
||||
@ -1374,7 +1402,8 @@ int TabSI::siCB(gdioutput &gdi, int type, void *data)
|
||||
if (r && r->getCardNo() != si) {
|
||||
if (si == 0 || !oe->checkCardUsed(gdi, *r, si)) {
|
||||
r->setCardNo(si, false);
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
|
||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||
r->synchronize();
|
||||
}
|
||||
|
||||
@ -1470,7 +1499,7 @@ void TabSI::showReadPunches(gdioutput &gdi, vector<PunchInfo> &punches, set<stri
|
||||
sprintf_s(bf, "%d.", k+1);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
gdi.addStringUT(yp, xp+40, 0, bf, 240);
|
||||
|
||||
@ -1836,8 +1865,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
}
|
||||
return;
|
||||
}
|
||||
gEvent->synchronizeList(oLCardId, true, false);
|
||||
gEvent->synchronizeList(oLRunnerId, false, true);
|
||||
gEvent->synchronizeList({ oListId::oLCardId, oListId::oLRunnerId });
|
||||
|
||||
if (sic.punchOnly) {
|
||||
processPunchOnly(gdi, sic);
|
||||
@ -1845,7 +1873,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
}
|
||||
pRunner r;
|
||||
if (sic.runnerId == 0)
|
||||
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, false);
|
||||
r = gEvent->getRunnerByCardNo(sic.CardNumber, 0, oEvent::CardLookupProperty::ForReadout);
|
||||
else {
|
||||
r = gEvent->getRunner(sic.runnerId, 0);
|
||||
sic.CardNumber = r->getCardNo();
|
||||
@ -1923,7 +1951,7 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
|
||||
if (!gdi.ask(bf)) {
|
||||
if (printSplits) {
|
||||
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0);
|
||||
pRunner runner = getRunnerForCardSplitPrint(sic);
|
||||
if (runner)
|
||||
generateSplits(runner, gdi);
|
||||
}
|
||||
@ -1936,7 +1964,8 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
}
|
||||
else {
|
||||
if (printSplits) {
|
||||
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0);
|
||||
pRunner runner = getRunnerForCardSplitPrint(sic);
|
||||
|
||||
if (runner)
|
||||
generateSplits(runner, gdi);
|
||||
}
|
||||
@ -1955,7 +1984,10 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
|
||||
pRunner db_r = 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()) {
|
||||
//Look up in database.
|
||||
@ -1971,10 +2003,13 @@ void TabSI::insertSICardAux(gdioutput &gdi, SICard &sic)
|
||||
gdi.dropLine();
|
||||
gdi.addString("", 1, "Skapar saknad klass").setColor(colorGreen);
|
||||
gdi.dropLine();
|
||||
pCourse pc=gEvent->addCourse(lang.tl("Okänd klass"));
|
||||
pCourse pc = nullptr;
|
||||
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);
|
||||
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
|
||||
@ -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)
|
||||
{
|
||||
if (!r) {
|
||||
@ -2093,7 +2150,7 @@ void TabSI::processInsertCard(const SICard &sic)
|
||||
if (oe->isCardRead(sic))
|
||||
return;
|
||||
|
||||
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0, true);
|
||||
pRunner runner = oe->getRunnerByCardNo(sic.CardNumber, 0, oEvent::CardLookupProperty::ForReadout);
|
||||
pCard card = oe->allocateCard(runner);
|
||||
card->setReadId(sic);
|
||||
card->setCardNo(sic.CardNumber);
|
||||
@ -2229,7 +2286,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
|
||||
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()) {
|
||||
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();
|
||||
|
||||
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())
|
||||
gEvent->calculateTeamResults(runner->getLegNumber(), false);
|
||||
bool qfClass = runner->getClassId(false) != runner->getClassId(true);
|
||||
@ -2391,7 +2451,7 @@ bool TabSI::processCard(gdioutput &gdi, pRunner runner, const SICard &csic, bool
|
||||
}
|
||||
}
|
||||
else {
|
||||
wstring msg=lang.tl(L"Status: ") + lang.tl(runner->getStatusS());
|
||||
wstring msg=lang.tl(L"Status: ") + runner->getStatusS(true);
|
||||
|
||||
if (!MP.empty()) {
|
||||
msg=msg + L", (";
|
||||
@ -2507,7 +2567,7 @@ void TabSI::entryCard(gdioutput &gdi, const SICard &sic)
|
||||
name=wstring(sic.lastName) + L", " + wstring(sic.firstName);
|
||||
|
||||
gdi.setText("Name", name);
|
||||
if (gdi.hasField("Club"))
|
||||
if (gdi.hasField("Club") && !club.empty())
|
||||
gdi.setText("Club", club);
|
||||
|
||||
if (club.empty() && gdi.hasField("Club"))
|
||||
@ -2571,7 +2631,7 @@ void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
|
||||
gdi.ask(L"Skriv över existerande bricknummer?")) {
|
||||
|
||||
r->setCardNo(sic.CardNumber, false);
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||
r->synchronize();
|
||||
gdi.setText(ii->id, sicode);
|
||||
}
|
||||
@ -2582,10 +2642,8 @@ void TabSI::assignCard(gdioutput &gdi, const SICard &sic)
|
||||
checkMoreCardsInQueue(gdi);
|
||||
}
|
||||
|
||||
void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
|
||||
{
|
||||
oe->synchronizeList(oLRunnerId, true, false);
|
||||
oe->synchronizeList(oLCardId, false, true);
|
||||
void TabSI::generateEntryLine(gdioutput &gdi, pRunner r) {
|
||||
oe->synchronizeList({ oListId::oLRunnerId, oListId::oLCardId });
|
||||
|
||||
gdi.restore("EntryLine", false);
|
||||
gdi.setRestorePoint("EntryLine");
|
||||
@ -2651,16 +2709,22 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
|
||||
gdi.dropLine(-0.2);
|
||||
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.setCX(gdi.getCX()+gdi.scaleLength(5));
|
||||
|
||||
gdi.addString("", 0, "Telefon:");
|
||||
gdi.dropLine(-0.2);
|
||||
gdi.addInput("Phone", storedInfo.storedPhone, 12, 0, L"");
|
||||
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);
|
||||
if (oe->hasNextStage())
|
||||
@ -2681,6 +2745,7 @@ void TabSI::generateEntryLine(gdioutput &gdi, pRunner r)
|
||||
gdi.setText("Fee", oe->formatCurrency(dci.getInt("Fee")));
|
||||
|
||||
gdi.setText("Phone", dci.getString("Phone"));
|
||||
gdi.setText("Bib", r->getBib());
|
||||
|
||||
gdi.check("RentCard", dci.getInt("CardFee") != 0);
|
||||
if (gdi.hasField("Paid"))
|
||||
@ -2876,7 +2941,8 @@ void TabSI::tieCard(gdioutput &gdi) {
|
||||
|
||||
bool rent = gdi.isChecked("RentCardTie");
|
||||
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);
|
||||
|
||||
gdi.restore("ManualTie");
|
||||
@ -3373,9 +3439,17 @@ void TabSI::StoredStartInfo::clear() {
|
||||
}
|
||||
|
||||
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;
|
||||
checkedCardFlags.clear();
|
||||
currentAssignIndex = 0;
|
||||
warnedClassOutOfMaps.clear();
|
||||
}
|
||||
|
||||
SICard &TabSI::getCard(int id) const {
|
||||
@ -3529,7 +3603,7 @@ void TabSI::showCheckCardStatus(gdioutput &gdi, const string &cmd) {
|
||||
wstring cp = r[k]->getCompleteIdentification();
|
||||
|
||||
if (r[k]->getStatus() != StatusUnknown)
|
||||
cp += L" " + r[k]->getStatusS();
|
||||
cp += L" " + r[k]->getStatusS(true);
|
||||
else
|
||||
cp += makeDash(L" -");
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -71,6 +71,8 @@ private:
|
||||
vector<SICard> cards;
|
||||
vector<wstring> filterDate;
|
||||
|
||||
set<int> warnedClassOutOfMaps;
|
||||
|
||||
int runnerMatchedId;
|
||||
bool printErrorShown;
|
||||
void printProtected(gdioutput &gdi, gdioutput &gdiprint);
|
||||
@ -132,7 +134,6 @@ private:
|
||||
// Insert card without converting times and with/without runner
|
||||
void processInsertCard(const SICard &csic);
|
||||
|
||||
|
||||
void generateSplits(const pRunner r, gdioutput &gdi);
|
||||
int logcounter;
|
||||
csvparser *logger;
|
||||
@ -141,6 +142,8 @@ private:
|
||||
|
||||
void insertSICardAux(gdioutput &gdi, SICard &sic);
|
||||
|
||||
pRunner getRunnerForCardSplitPrint(const SICard &sic) const;
|
||||
|
||||
// Ask if card is to be overwritten
|
||||
bool askOverwriteCard(gdioutput &gdi, pRunner r) const;
|
||||
|
||||
@ -246,7 +249,7 @@ public:
|
||||
TabType getType() const {return TSITab;}
|
||||
|
||||
void insertSICard(gdioutput &gdi, SICard &sic);
|
||||
|
||||
void clearQueue() { CardQueue.clear(); }
|
||||
void refillComPorts(gdioutput &gdi);
|
||||
|
||||
bool loadPage(gdioutput &gdi);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -39,6 +39,7 @@
|
||||
|
||||
#include "TabSpeaker.h"
|
||||
#include "TabList.h"
|
||||
#include "TabRunner.h"
|
||||
#include "speakermonitor.h"
|
||||
#include "meosexception.h"
|
||||
|
||||
@ -100,6 +101,34 @@ int TabSpeaker::handleEvent(gdioutput &gdi, const EventInfo &ei)
|
||||
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)
|
||||
{
|
||||
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.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") {
|
||||
gdi.clearPage(false);
|
||||
gdi.addString("", boldLarge, "Bevakningsprioritering");
|
||||
@ -424,7 +484,7 @@ void TabSpeaker::drawTimeLine(gdioutput &gdi) {
|
||||
}
|
||||
|
||||
void TabSpeaker::updateTimeLine(gdioutput &gdi) {
|
||||
int storedY = gdi.GetOffsetY();
|
||||
int storedY = gdi.getOffsetY();
|
||||
int storedHeight = gdi.getHeight();
|
||||
bool refresh = gdi.hasData("TimeLineLoaded");
|
||||
|
||||
@ -442,7 +502,7 @@ void TabSpeaker::updateTimeLine(gdioutput &gdi) {
|
||||
gdi.pushX(); gdi.pushY();
|
||||
gdi.updatePos(0,0,0, storedHeight);
|
||||
gdi.popX(); gdi.popY();
|
||||
gdi.SetOffsetY(storedY);
|
||||
gdi.setOffsetY(storedY);
|
||||
|
||||
SpeakerMonitor &sm = *getSpeakerMonitor();
|
||||
int limit = 1000;
|
||||
@ -899,11 +959,14 @@ int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
|
||||
int classId = int(bu.data);
|
||||
loadPriorityClass(gdi, classId);
|
||||
}
|
||||
else if (bu.id == "ReportRunner") {
|
||||
runnerId = bu.data;
|
||||
gdi.sendCtrlMessage("Report");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
{
|
||||
bool TabSpeaker::loadPage(gdioutput &gdi) {
|
||||
oe->checkDB();
|
||||
|
||||
gdi.clearPage(false);
|
||||
@ -925,12 +988,19 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
int cx=basex;
|
||||
int cy=basey;
|
||||
int cb=1;
|
||||
for (set<int>::iterator it=classesToWatch.begin();it!=classesToWatch.end();++it) {
|
||||
char classid[32];
|
||||
sprintf_s(classid, "cid%d", *it);
|
||||
pClass pc=oe->getClass(*it);
|
||||
|
||||
vector<pClass> clsToWatch;
|
||||
for (int cid : classesToWatch) {
|
||||
pClass pc = oe->getClass(cid);
|
||||
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);
|
||||
cx+=bw;
|
||||
cb++;
|
||||
@ -941,8 +1011,8 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
cy+=gdi.getButtonHeight()+4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool pm = false;
|
||||
int db = 0;
|
||||
if (classesToWatch.empty()) {
|
||||
gdi.addString("", boldLarge, "Speakerstöd");
|
||||
@ -956,11 +1026,23 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
cb = 1, cx = basex, db = 0;
|
||||
cy += gdi.getButtonHeight()+4;
|
||||
} else db += bw;
|
||||
pm = true;
|
||||
}
|
||||
|
||||
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);
|
||||
if (++cb>nbtn) {
|
||||
cb = 1, cx = basex, db = 0;
|
||||
@ -978,13 +1060,12 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
cy += gdi.getButtonHeight()+4;
|
||||
} 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) {
|
||||
cb = 1, cx = basex, db = 0;
|
||||
cy += gdi.getButtonHeight()+4;
|
||||
} else db += bw;
|
||||
|
||||
|
||||
if (!ownWindow) {
|
||||
gdi.addButton(cx+db, cy, bw-2, "Priority", "Prioritering", tabSpeakerCB, "Välj löpare att prioritera bevakning för", false, false);
|
||||
if (++cb>nbtn) {
|
||||
@ -1028,6 +1109,11 @@ bool TabSpeaker::loadPage(gdioutput &gdi)
|
||||
if (gdi.hasField(btn))
|
||||
gdi.sendCtrlMessage(btn);
|
||||
}
|
||||
else if (classId == -2) {
|
||||
string btn = "Report";
|
||||
if (gdi.hasField(btn))
|
||||
gdi.sendCtrlMessage(btn);
|
||||
}
|
||||
else if (classId > 0) {
|
||||
string btn = "cid" + itos(classId);
|
||||
if (gdi.hasField(btn))
|
||||
@ -1054,6 +1140,7 @@ void TabSpeaker::clearCompetitionData()
|
||||
|
||||
delete speakerMonitor;
|
||||
speakerMonitor = 0;
|
||||
runnerId = -1;
|
||||
}
|
||||
|
||||
void TabSpeaker::manualTimePage(gdioutput &gdi) const
|
||||
@ -1101,7 +1188,7 @@ void TabSpeaker::storeManualTime(gdioutput &gdi)
|
||||
pRunner r=oe->getRunnerByBibOrStartNo(r_str, false);
|
||||
int r_no = _wtoi(r_str.c_str());
|
||||
if (!r)
|
||||
r=oe->getRunnerByCardNo(r_no, itime);
|
||||
r=oe->getRunnerByCardNo(r_no, itime, oEvent::CardLookupProperty::Any);
|
||||
|
||||
wstring Name;
|
||||
int sino=r_no;
|
||||
@ -1153,8 +1240,7 @@ void TabSpeaker::loadPriorityClass(gdioutput &gdi, int classId) {
|
||||
}
|
||||
|
||||
void TabSpeaker::savePriorityClass(gdioutput &gdi) {
|
||||
oe->synchronizeList(oLRunnerId, true, false);
|
||||
oe->synchronizeList(oLTeamId, false, true);
|
||||
oe->synchronizeList({ oListId::oLRunnerId,oListId::oLTeamId });
|
||||
|
||||
for (size_t k = 0; k<runnersToSet.size(); k++) {
|
||||
pRunner r = oe->getRunner(runnersToSet[k], 0);
|
||||
@ -1223,6 +1309,9 @@ void TabSpeaker::getSettings(gdioutput &gdi, multimap<string, wstring> &settings
|
||||
if (classId == -1) {
|
||||
settings.insert(make_pair("currentClass", L"@Events"));
|
||||
}
|
||||
else if (classId == -2) {
|
||||
settings.insert(make_pair("currentClass", L"@Report"));
|
||||
}
|
||||
|
||||
for (auto ctrl : controlsToWatch) {
|
||||
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") {
|
||||
classId = -1;
|
||||
}
|
||||
else if (s.second == L"@Report") {
|
||||
classId = -2;
|
||||
}
|
||||
else {
|
||||
pClass cls = oe->getClass(s.second);
|
||||
classId = cls ? cls->getId() : 0;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -58,6 +58,9 @@ private:
|
||||
set<int> controlsToWatch;
|
||||
set<int> classesToWatch;
|
||||
|
||||
// For runner report
|
||||
int runnerId = -1;
|
||||
|
||||
int lastControlToWatch;
|
||||
int lastClassToWatch;
|
||||
|
||||
@ -100,6 +103,8 @@ private:
|
||||
static wstring getSpeakerSettingsFile();
|
||||
public:
|
||||
|
||||
void setSelectedRunner(const oRunner &r) { runnerId = r.getId(); }
|
||||
|
||||
bool onClear(gdioutput &gdi);
|
||||
void loadPriorityClass(gdioutput &gdi, int classId);
|
||||
void savePriorityClass(gdioutput &gdi);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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("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("Teams", t->getId());
|
||||
|
||||
@ -205,6 +205,10 @@ void TabTeam::selectTeam(gdioutput &gdi, pTeam t)
|
||||
gdi.setText("PointIn", t->getInputPoints());
|
||||
}
|
||||
|
||||
if (gdi.hasField("NoRestart")) {
|
||||
gdi.check("NoRestart", t->preventRestart());
|
||||
}
|
||||
|
||||
loadTeamMembers(gdi, 0, 0, t);
|
||||
}
|
||||
else {
|
||||
@ -320,6 +324,10 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
if (gdi.hasField("Fee"))
|
||||
t->getDI().setInt("Fee", oe->interpretCurrency(gdi.getText("Fee")));
|
||||
|
||||
|
||||
if (gdi.hasField("NoRestart"))
|
||||
t->preventRestart(gdi.isChecked("NoRestart"));
|
||||
|
||||
t->apply(false, 0, false);
|
||||
|
||||
if (gdi.hasField("Club")) {
|
||||
@ -436,7 +444,7 @@ bool TabTeam::save(gdioutput &gdi, bool dontReloadTeams) {
|
||||
r->setCardNo(cardNo, true);
|
||||
|
||||
if (gdi.isChecked("RENT" + itos(i)))
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||
else
|
||||
r->getDI().setInt("CardFee", 0);
|
||||
|
||||
@ -617,15 +625,14 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
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) {
|
||||
throw meosException(L"Brickan används av X.#" + old->getName() );
|
||||
}
|
||||
|
||||
|
||||
pClub clb = 0;
|
||||
if (!rExists) {
|
||||
pRunner rOrig = oe->getRunnerByCardNo(card, 0, false, false);
|
||||
pRunner rOrig = oe->getRunnerByCardNo(card, 0, oEvent::CardLookupProperty::Any);
|
||||
if (rOrig)
|
||||
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);
|
||||
}
|
||||
if (rent)
|
||||
r->getDI().setInt("CardFee", oe->getDI().getInt("CardFee"));
|
||||
r->getDI().setInt("CardFee", oe->getBaseCardFee());
|
||||
|
||||
t->synchronize();
|
||||
pRunner oldR = t->getRunner(leg);
|
||||
@ -653,13 +660,17 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
oldR->synchronize(true);
|
||||
t->setRunner(leg, r, true);
|
||||
t->checkValdParSetup();
|
||||
|
||||
if (oldR->isAnnonumousTeamMember())
|
||||
oe->removeRunner({ oldR->getId() });
|
||||
t->synchronize(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
t->setRunner(leg, r, true);
|
||||
t->checkValdParSetup();
|
||||
t->synchronize(true);
|
||||
}
|
||||
|
||||
selectTeam(gdi, t);
|
||||
}
|
||||
else if (bi.id == "Browse") {
|
||||
@ -1017,7 +1028,6 @@ int TabTeam::teamCB(gdioutput &gdi, int type, void *data)
|
||||
pClass pc=oe->getClass(lbi.data);
|
||||
|
||||
if (pc) {
|
||||
vector<pRunner> rCache;
|
||||
for(unsigned i=0;i<pc->getNumStages();i++){
|
||||
char bf[16];
|
||||
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);
|
||||
int cno = r->getCardNo();
|
||||
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");
|
||||
if (cno > 0 && gdi.getText("DirName").empty()) {
|
||||
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) ) {
|
||||
// Switch to exactly this runner. Has not run before
|
||||
gdi.setText("DirName", r->getName())->setExtra(r->getId());
|
||||
matched = true;
|
||||
}
|
||||
else {
|
||||
r = oe->getRunnerByCardNo(cno, 0, false, false);
|
||||
r = oe->getRunnerByCardNo(cno, 0, oEvent::CardLookupProperty::Any);
|
||||
if (r) {
|
||||
// Copy only the name.
|
||||
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());
|
||||
pTeam t = oe->getTeam(teamId);
|
||||
if (t) {
|
||||
vector<pRunner> rc;
|
||||
warnDuplicateCard(gdi, ii.id, cardNo, t->getRunner(i), rc);
|
||||
warnDuplicateCard(gdi, ii.id, cardNo, t->getRunner(i));
|
||||
}
|
||||
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[5], 0, "Status:");
|
||||
gdi.dropLine(0.5);
|
||||
vector<pRunner> rCache;
|
||||
|
||||
for (unsigned i=0;i<pc->getNumStages();i++) {
|
||||
yp = gdi.getCY();
|
||||
@ -1249,7 +1257,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
||||
if (hasSI) {
|
||||
int cno = r->getCardNo();
|
||||
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);
|
||||
}
|
||||
string sid = "STATUS"+itos(i);
|
||||
@ -1259,7 +1267,7 @@ void TabTeam::loadTeamMembers(gdioutput &gdi, int ClassId, int ClubId, pTeam t)
|
||||
ti->setColor(colorGreen);
|
||||
}
|
||||
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)
|
||||
ti->setColor(colorRed);
|
||||
}
|
||||
@ -1378,7 +1386,7 @@ bool TabTeam::loadPage(gdioutput &gdi)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (oe->getMeOSFeatures().hasFeature(MeOSFeatures::Economy))
|
||||
@ -1432,6 +1440,9 @@ bool TabTeam::loadPage(gdioutput &gdi)
|
||||
gdi.popX();
|
||||
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);
|
||||
|
||||
const bool multiDay = oe->hasPrevStage();
|
||||
@ -1491,18 +1502,18 @@ bool TabTeam::loadPage(gdioutput &gdi)
|
||||
rc.left = posXForButtons;
|
||||
rc.top = posYForButtons;
|
||||
|
||||
gdi.setCY(posYForButtons + gdi.scaleLength(4));
|
||||
gdi.setCY(posYForButtons + gdi.scaleLength(10));
|
||||
gdi.setCX(posXForButtons + gdi.getLineHeight());
|
||||
gdi.fillDown();
|
||||
gdi.addString("", 1, "Verktyg");
|
||||
gdi.addString("", fontMediumPlus, "Verktyg");
|
||||
gdi.dropLine(0.3);
|
||||
gdi.fillRight();
|
||||
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.)");
|
||||
rc.right = gdi.getCX() + gdi.getLineHeight();
|
||||
gdi.dropLine(1.5);
|
||||
gdi.dropLine(2);
|
||||
rc.bottom = gdi.getHeight();
|
||||
gdi.addRectangle(rc, colorLightCyan);
|
||||
gdi.addRectangle(rc, colorLightBlue);
|
||||
|
||||
gdi.setRestorePoint();
|
||||
|
||||
@ -1692,7 +1703,7 @@ pRunner TabTeam::findRunner(const wstring &name, int cardNo) const {
|
||||
|
||||
if (cardNo != 0) {
|
||||
vector<pRunner> pr;
|
||||
oe->getRunnersByCard(cardNo, pr);
|
||||
oe->getRunnersByCardNo(cardNo, true, oEvent::CardLookupProperty::Any, pr);
|
||||
for (size_t k = 0; k < pr.size(); k++) {
|
||||
wstring a = canonizeName(pr[k]->getName().c_str());
|
||||
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) {
|
||||
vector<int> mp;
|
||||
bool removeAnnonumousTeamMember = false;
|
||||
|
||||
if (r->getTeam()) {
|
||||
pTeam otherTeam = r->getTeam();
|
||||
@ -1890,7 +1902,11 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
|
||||
else if (oldR) {
|
||||
t->setRunner(leg, 0, false);
|
||||
t->synchronize(true);
|
||||
if (r->getClassRef(false) && r->getClassRef(false)->isTeamClass())
|
||||
oldR->setClassId(0, false);
|
||||
else
|
||||
oldR->setClassId(r->getClassId(false), true);
|
||||
removeAnnonumousTeamMember = oldR->isAnnonumousTeamMember();
|
||||
oldR->evaluateCard(true, mp, 0, true);
|
||||
oldR->synchronize(true);
|
||||
}
|
||||
@ -1900,6 +1916,9 @@ void TabTeam::switchRunners(pTeam t, int leg, pRunner r, pRunner oldR) {
|
||||
t->checkValdParSetup();
|
||||
t->apply(true, 0, false);
|
||||
t->synchronize(true);
|
||||
|
||||
if (removeAnnonumousTeamMember)
|
||||
oe->removeRunner({ oldR->getId() });
|
||||
}
|
||||
|
||||
void TabTeam::clearCompetitionData() {
|
||||
@ -1911,16 +1930,15 @@ void TabTeam::clearCompetitionData() {
|
||||
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;
|
||||
|
||||
if (r && !r->getCard()) {
|
||||
if (allRCache.empty()) // Fill cache if not initialized
|
||||
oe->getRunners(0, 0, allRCache, false);
|
||||
|
||||
for (size_t k = 0; k < allRCache.size(); k++) {
|
||||
if (!r->canShareCard(allRCache[k], cno)) {
|
||||
warnCardDupl = allRCache[k];
|
||||
if (r && !r->getCard() && cno != 0) {
|
||||
vector<pRunner> allR;
|
||||
oe->getRunnersByCardNo(cno, true, oEvent::CardLookupProperty::Any, allR);
|
||||
for (pRunner ar : allR) {
|
||||
if (!r->canShareCard(ar, cno)) {
|
||||
warnCardDupl = ar;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -70,7 +70,7 @@ private:
|
||||
vector<TeamLineup> teamLineup;
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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,
|
||||
const TextInfo &ti, const wstring &symbol, bool highLight) {
|
||||
int cx = ti.xp - gdi.GetOffsetX() + ti.xlimit/2;
|
||||
int cy = ti.yp - gdi.GetOffsetY() + height/2 - 2;
|
||||
int cx = ti.xp - gdi.getOffsetX() + ti.xlimit/2;
|
||||
int cy = ti.yp - gdi.getOffsetY() + height/2 - 2;
|
||||
int h = int(height * 0.4);
|
||||
int w = h/3;
|
||||
h-=2;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#endif // _MSC_VER > 1000
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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"
|
||||
|
||||
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) {
|
||||
|
||||
lastTime = 0;
|
||||
@ -56,7 +56,7 @@ AnimationData::AnimationData(gdioutput &gdi, int timePerPage, int nCol,
|
||||
pageInfo.yMM2PrintK = 0;
|
||||
|
||||
list<RectangleInfo> rectangles;
|
||||
pageInfo.renderPages(gdi.getTL(), rectangles, false, pages);
|
||||
pageInfo.renderPages(gdi.getTL(), rectangles, false, respectPageBreak, pages);
|
||||
}
|
||||
|
||||
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) {
|
||||
int ox = gdi.GetOffsetX();
|
||||
int oy = gdi.GetOffsetY();
|
||||
int ox = gdi.getOffsetX();
|
||||
int oy = gdi.getOffsetY();
|
||||
|
||||
int top = 10000;
|
||||
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);
|
||||
}
|
||||
}
|
||||
gdi.SetOffsetY(-y+top-margin/2);
|
||||
gdi.SetOffsetX(-x);
|
||||
gdi.setOffsetY(-y+top-margin/2);
|
||||
gdi.setOffsetX(-x);
|
||||
|
||||
int currentRow = 0;
|
||||
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.SetOffsetY(ox);
|
||||
gdi.SetOffsetX(oy);
|
||||
gdi.setOffsetY(ox);
|
||||
gdi.setOffsetX(oy);
|
||||
}
|
||||
|
||||
void AnimationData::handle(gdioutput &gdi, BaseInfo &info, GuiEventType type) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -54,7 +54,7 @@ class AnimationData : public GuiHandler {
|
||||
public:
|
||||
|
||||
AnimationData(gdioutput &gdi, int timePerPage, int nCol,
|
||||
int marginPercent, bool animate);
|
||||
int marginPercent, bool animate, bool respectPageBreak);
|
||||
~AnimationData();
|
||||
|
||||
void handle(gdioutput &gdi, BaseInfo &info, GuiEventType type);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,4 +1,27 @@
|
||||
#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 "gdioutput.h"
|
||||
|
||||
|
||||
@ -1,4 +1,25 @@
|
||||
#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 gdioutput;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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.hasMultiEvent = hasPrevStage() || hasNextStage();
|
||||
map<int, vector<const oRunner *>> runnerPerClass;
|
||||
|
||||
for (it = Classes.begin(); it != Classes.end(); ++it) {
|
||||
if (it->isRemoved())
|
||||
@ -129,6 +130,57 @@ void oEvent::getClassConfigurationInfo(ClassConfigInfo &cnf) const
|
||||
if (it->getCourse() == 0)
|
||||
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() ) {
|
||||
for (size_t k = 0; k< it->MultiCourse.size(); k++) {
|
||||
if (it->MultiCourse[k].size() > 1)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -44,6 +44,11 @@ public:
|
||||
|
||||
vector<int> rogainingClasses;
|
||||
|
||||
vector<int> knockout;
|
||||
|
||||
vector<int> lapcountsingle;
|
||||
vector<int> lapcountextra;
|
||||
|
||||
// True if predefined forking
|
||||
bool hasMultiCourse;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -63,34 +63,39 @@ csvparser::~csvparser()
|
||||
|
||||
}
|
||||
|
||||
int csvparser::iscsv(const wstring &file)
|
||||
{
|
||||
fin.open(file);
|
||||
csvparser::CSV csvparser::iscsv(const wstring &file) {
|
||||
ifstream fin(file);
|
||||
|
||||
if (!fin.good())
|
||||
return false;
|
||||
return CSV::NoCSV;
|
||||
|
||||
char bf[2048];
|
||||
bool isCSVType = false;
|
||||
while (fin.good() && !isCSVType) {
|
||||
fin.getline(bf, 2048);
|
||||
|
||||
while(fin.good() && strlen(bf)<3)
|
||||
fin.getline(bf, 2048);
|
||||
isCSVType = strlen(bf) >= 3;
|
||||
}
|
||||
|
||||
fin.close();
|
||||
|
||||
vector<char *> 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)
|
||||
return 3;
|
||||
return CSV::RAID;
|
||||
|
||||
if (sp.size()<5)//No csv
|
||||
return 0;
|
||||
if (sp.size()<2)//No csv
|
||||
return CSV::NoCSV;
|
||||
|
||||
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)??
|
||||
return 2;
|
||||
else return 1; //OE?!
|
||||
return CSV::OS;
|
||||
else return CSV::OE; //OE?!
|
||||
}
|
||||
|
||||
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,
|
||||
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;
|
||||
list< vector<wstring> > allLines;
|
||||
parse(file, allLines);
|
||||
//vector<wchar_t *> sp;
|
||||
list< vector<wstring> >::iterator it = allLines.begin();
|
||||
|
||||
set<wstring> matchedClasses;
|
||||
// Skip first line
|
||||
while (++it != allLines.end()) {
|
||||
//fin.getline(bf, 1024);
|
||||
@ -161,7 +159,7 @@ bool csvparser::importOS_CSV(oEvent &event, const wstring &file)
|
||||
|
||||
//Create class with this class number...
|
||||
int ClassId=wtoi(sp[OSclassno]);
|
||||
event.getClassCreate(ClassId, sp[OSclass]);
|
||||
event.getClassCreate(ClassId, sp[OSclass], matchedClasses);
|
||||
|
||||
//Club is autocreated...
|
||||
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]) );
|
||||
|
||||
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)
|
||||
r->setStatus(StatusUnknown, true, false);
|
||||
r->setStatus(StatusUnknown, true, false, 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,
|
||||
OElength=40};
|
||||
|
||||
/* fin.open(file);
|
||||
|
||||
if (!fin.good())
|
||||
return false;
|
||||
|
||||
char bf[1024];
|
||||
fin.getline(bf, 1024);
|
||||
*/
|
||||
list< vector<wstring> > allLines;
|
||||
parse(file, allLines);
|
||||
list< vector<wstring> >::iterator it = allLines.begin();
|
||||
|
||||
set<wstring> matchedClasses;
|
||||
// Skip first line
|
||||
|
||||
|
||||
nimport=0;
|
||||
while (++it != allLines.end()) {
|
||||
//fin.getline(bf, 1024);
|
||||
//split(bf, sp);
|
||||
const vector<wstring> &sp = *it;
|
||||
if (sp.size()>20) {
|
||||
nimport++;
|
||||
@ -348,7 +336,7 @@ bool csvparser::importOE_CSV(oEvent &event, const wstring &file) {
|
||||
//Autocreate class if it does not exist...
|
||||
int classId=wtoi(sp[OEclassno]);
|
||||
if (classId>0 && !pr->hasFlag(oAbstractRunner::FlagUpdateClass)) {
|
||||
pClass pc=event.getClassCreate(classId, sp[OEclass]);
|
||||
pClass pc=event.getClassCreate(classId, sp[OEclass], matchedClasses);
|
||||
|
||||
if (pc) {
|
||||
pc->synchronize();
|
||||
@ -675,6 +663,8 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
|
||||
|
||||
list< vector<wstring> > allLines;
|
||||
parse(file, allLines);
|
||||
|
||||
set<wstring> matchedClasses;
|
||||
list< vector<wstring> >::iterator it = allLines.begin();
|
||||
nimport=0;
|
||||
while (++it != allLines.end()) {
|
||||
@ -686,7 +676,7 @@ bool csvparser::importRAID(oEvent &event, const wstring &file)
|
||||
int ClubId=0;
|
||||
//Create class with this class number...
|
||||
int ClassId=wtoi(sp[RAIDclassid]);
|
||||
pClass pc = event.getClassCreate(ClassId, sp[RAIDclass]);
|
||||
pClass pc = event.getClassCreate(ClassId, sp[RAIDclass], matchedClasses);
|
||||
ClassId = pc->getId();
|
||||
|
||||
//Club is autocreated...
|
||||
@ -1357,3 +1347,127 @@ void csvparser::importTeamLineup(const wstring &file,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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,
|
||||
vector<SICard> &punches);
|
||||
|
||||
int split(char *line, vector<char *> &split);
|
||||
int split(wchar_t *line, vector<wchar_t *> &split);
|
||||
int importRanking(oEvent &oe, const wstring &file, vector<wstring> & problems);
|
||||
|
||||
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();
|
||||
virtual ~csvparser();
|
||||
|
||||
|
||||
@ -752,7 +752,7 @@ Radera tävlingen = Smaž závod
|
||||
Radera vakanser = Odstraň vakanty
|
||||
Radiotider, kontroll = Radio-čas, kontrola
|
||||
Ranking = Ranking
|
||||
Ranking (IOF, xml) = Ranking (IOF, xml)
|
||||
Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
|
||||
Rapport inför = Protokol pro
|
||||
Rapporter = Protokoly
|
||||
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
|
||||
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.
|
||||
Kval-Final-Schema = Načti kvalifikační schéma
|
||||
Kval/final-schema = Načti kvalifikační schéma
|
||||
Lås startlista = Zamkni startovku
|
||||
FilterNoCancel = Není zrušeno
|
||||
CourseStartTime = Trať, čas startu
|
||||
|
||||
@ -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 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)
|
||||
Kval-Final-Schema = Kval-Finale-Skema
|
||||
Kval/final-schema = Kval/Finale-Skema
|
||||
Kvar-i-skogen = Løbere i skoven
|
||||
Kvinna = Kvinde
|
||||
Kvinnor = Kvinder
|
||||
@ -1468,7 +1468,7 @@ Radera tävlingen = Slet løbet
|
||||
Radera vakanser = Slet vakante
|
||||
radio X = radio X
|
||||
Radiotider, kontroll = Radiotider, post
|
||||
Ranking (IOF, xml) = Rangliste (IOF, XML)
|
||||
Ranking (IOF, xml, csv) = Rangliste (IOF, xml, csv)
|
||||
Ranking = Rangliste
|
||||
Rapport = Rapport
|
||||
Rapport inför = Rapport før
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -27,13 +27,18 @@
|
||||
#include "meos_util.h"
|
||||
#include "progress.h"
|
||||
#include "meosexception.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <cassert>
|
||||
#include <sys/stat.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <process.h>
|
||||
|
||||
#pragma comment(lib, "IPHLPAPI.lib")
|
||||
#define INET_ADDRSTRLEN 16
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -472,3 +477,124 @@ bool Download::httpSendReqEx(HINTERNET hConnect, bool https, const wstring &dest
|
||||
InternetCloseHandle(hRequest);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
132
code/english.lng
132
code/english.lng
@ -619,9 +619,9 @@ Mata in radiotider manuellt = Enter radio times by hand
|
||||
Max antal gemensamma kontroller = Max number common controls
|
||||
Max parallellt startande = Max. number parallel start
|
||||
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 efter = Maximum time after
|
||||
Maxtid efter = Maximum time behind
|
||||
MeOS = MeOS
|
||||
MeOS lokala datakatalog är = MeOS local data folder is
|
||||
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 omstartstid = Invalid restart 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 tid = Invalid time
|
||||
Ogiltigt bricknummer X = Invalid card number X
|
||||
@ -753,7 +753,7 @@ Radera tävlingen = Remove Competition
|
||||
Radera vakanser = Delete Vacancies
|
||||
Radiotider, kontroll = Radio times, control
|
||||
Ranking = Ranking
|
||||
Ranking (IOF, xml) = Ranking (IOF, xml)
|
||||
Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
|
||||
Rapport inför = Report for
|
||||
Rapporter = Reports
|
||||
Rapportläge = Report Mode
|
||||
@ -804,7 +804,7 @@ Runner = Competitor
|
||||
RunnerBib = Competitor's bib
|
||||
RunnerCard = Card number
|
||||
RunnerClassCoursePlace = Position on course within class
|
||||
RunnerClassCourseTimeAfter = Time after on course within class
|
||||
RunnerClassCourseTimeAfter = Time behind on course within class
|
||||
RunnerClub = Competitor's club
|
||||
RunnerCompleteName = Complete name
|
||||
RunnerCourse = Competitor's course
|
||||
@ -820,17 +820,17 @@ RunnerRank = Ranking
|
||||
RunnerRogainingPoint = Rogaining points
|
||||
RunnerStart = Competitor's start time
|
||||
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
|
||||
RunnerTime = Competitor's time
|
||||
RunnerTimeAfter = Competitor's time after
|
||||
RunnerTimeAfterDiff = Competitor's time after difference
|
||||
RunnerTimeAfter = Competitor's time behind
|
||||
RunnerTimeAfterDiff = Competitor's time behind difference
|
||||
RunnerTimeLost = Competitor's lost time
|
||||
RunnerTimePlaceFixed = Time when Competitor's place is set
|
||||
RunnerTimeStatus = Competitor's time / status
|
||||
RunnerTotalPlace = Competitor's total place
|
||||
RunnerTotalTime = Competitor's total time
|
||||
RunnerTotalTimeAfter = Competitor's total time after
|
||||
RunnerTotalTimeAfter = Competitor's total time behind
|
||||
RunnerTotalTimeStatus = Competitor's total time / status
|
||||
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
|
||||
@ -1038,7 +1038,7 @@ Tabelläge = Table Mode
|
||||
Team = Team
|
||||
TeamBib = Team's bib
|
||||
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
|
||||
TeamName = Team name
|
||||
TeamPlace = Team's place
|
||||
@ -1049,7 +1049,7 @@ TeamStart = Team's start time
|
||||
TeamStartNo = Team's start number
|
||||
TeamStatus = Team status
|
||||
TeamTime = Team's time
|
||||
TeamTimeAfter = Team's time after
|
||||
TeamTimeAfter = Team's time behind
|
||||
TeamTimeStatus = Team's time / status
|
||||
Telefon = Phone
|
||||
Test = Test
|
||||
@ -1060,9 +1060,9 @@ Text: X = Text: X
|
||||
Textfiler = Text files
|
||||
Textstorlek = Text size
|
||||
Tid = Time
|
||||
Tid efter: X = Time after: X
|
||||
Tid efter: X; har tagit in Y = Time after: X; gained Y
|
||||
Tid efter: X; har tappat Y = Time after: X; lost Y
|
||||
Tid efter: X = Time behind: X
|
||||
Tid efter: X; har tagit in Y = Time behind: X; gained Y
|
||||
Tid efter: X; har tappat Y = Time behind: X; lost Y
|
||||
Tid in = Time in
|
||||
Tid: X, nuvarande placering Y/Z = Time: X, current place Y/Z
|
||||
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.'
|
||||
Verkställ = Apply
|
||||
Version X = Version X
|
||||
Vi stöder MeOS = We support MeOS
|
||||
Vi stöder MeOS = We Support MeOS
|
||||
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 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äxeln = the changeover
|
||||
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
|
||||
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.
|
||||
@ -1506,8 +1506,8 @@ Rogainingresultat - %s = Rogaining results - %s
|
||||
TeamPlaceDiff = Team's place difference (this stages)
|
||||
TeamTotalPlace = Team's summed place (all stages)
|
||||
TeamTotalTime = Team's summed time (all stages)
|
||||
TeamTotalTimeAfter = Team's summed time after (all stages)
|
||||
TeamTotalTimeDiff = Team's summed time after difference (this stage)
|
||||
TeamTotalTimeAfter = Team's summed time behind (all stages)
|
||||
TeamTotalTimeDiff = Team's summed time behind difference (this stage)
|
||||
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?
|
||||
Radera alla klubbar = Delete All Clubs
|
||||
@ -1614,7 +1614,7 @@ Höger = Right
|
||||
PunchControlCode = Control code
|
||||
PunchControlNumber = Punch code
|
||||
PunchControlPlace = Place, leg to control
|
||||
PunchControlPlaceAcc = Place, total after control
|
||||
PunchControlPlaceAcc = Place, total at control
|
||||
PunchLostTime = Time lost at control
|
||||
Slå ihop text med föregående = Merge with previous
|
||||
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
|
||||
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 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
|
||||
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
|
||||
@ -1952,7 +1952,7 @@ Hela banan = Entire course
|
||||
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
|
||||
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
|
||||
Country = Country
|
||||
CourseShortening = Course shortening
|
||||
@ -2010,7 +2010,7 @@ Tabellverktyg = Table tools
|
||||
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).
|
||||
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
|
||||
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.
|
||||
@ -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
|
||||
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.
|
||||
Kval-Final-Schema = Load qualification scheme
|
||||
Kval/final-schema = Qualification/final scheme
|
||||
Lås startlista = Lock start list
|
||||
FilterNoCancel = Not cancelled
|
||||
CourseStartTime = Course, start time
|
||||
@ -2321,3 +2321,89 @@ Finish order = Finish order
|
||||
First to finish = First to finish
|
||||
Individual result by finish time = Individual result by finish time
|
||||
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
|
||||
|
||||
@ -753,7 +753,7 @@ Radera tävlingen = Supprimer la compétition
|
||||
Radera vakanser = Supprimer les vacants
|
||||
Radiotider, kontroll = Heures radio, poste
|
||||
Ranking = Classement
|
||||
Ranking (IOF, xml) = Classement (IOF, xml)
|
||||
Ranking (IOF, xml, csv) = Classement (IOF, xml, csv)
|
||||
Rapport inför = Rapport pour
|
||||
Rapporter = Rapports
|
||||
Rapportläge = Mode rapport
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
************************************************************************/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
enum gdiFonts {
|
||||
@ -46,6 +47,7 @@ enum gdiFonts {
|
||||
const int pageNewPage=100;
|
||||
//const int pageReserveHeight=101;
|
||||
const int pagePageInfo=102;
|
||||
const int pageNewChapter = 103;
|
||||
|
||||
const int textRight=256;
|
||||
const int textCenter=512;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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) {
|
||||
format &= 0xFF;
|
||||
return format == pageNewPage ||
|
||||
format == pagePageInfo;
|
||||
format == pagePageInfo ||
|
||||
format == pageNewChapter;
|
||||
}
|
||||
|
||||
#ifndef MEOSDB
|
||||
@ -117,6 +118,7 @@ gdioutput::gdioutput(const string &_tag, double _scale) :
|
||||
|
||||
isTestMode = false;
|
||||
}
|
||||
extern gdioutput *gdi_main;
|
||||
|
||||
gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) :
|
||||
recorder((Recorder *)0, false) {
|
||||
@ -125,8 +127,12 @@ gdioutput::gdioutput(double _scale, HWND hWnd, const PrinterObject &prndef) :
|
||||
tabs = 0;
|
||||
setWindow(hWnd);
|
||||
constructor(_scale);
|
||||
|
||||
isTestMode = false;
|
||||
if (gdi_main) {
|
||||
isTestMode = gdi_main->isTestMode;
|
||||
if (isTestMode)
|
||||
cmdAnswers.swap(gdi_main->cmdAnswers);
|
||||
}
|
||||
else isTestMode = false;
|
||||
}
|
||||
|
||||
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.yp=y;
|
||||
lbi.width = scale*width;
|
||||
lbi.height = scale*height;
|
||||
lbi.height = scale*30;
|
||||
lbi.id=id;
|
||||
lbi.callBack=cb;
|
||||
|
||||
@ -3098,6 +3104,11 @@ bool gdioutput::hasField(const string &id) const
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto &tl : TL) {
|
||||
if (tl.id == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3651,8 +3662,8 @@ void gdioutput::refreshSmartFromSnapshot(bool allowMoveOffset) {
|
||||
}
|
||||
}
|
||||
|
||||
int maxOffsetY=max<int>(GetPageY()-clientRC.bottom, 0);
|
||||
int maxOffsetX=max<int>(GetPageX()-clientRC.right, 0);
|
||||
int maxOffsetY=max<int>(getPageY()-clientRC.bottom, 0);
|
||||
int maxOffsetX=max<int>(getPageX()-clientRC.right, 0);
|
||||
int noy = OffsetY - offset.second;
|
||||
int nox = OffsetX - offset.first;
|
||||
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 ox=OffsetX;
|
||||
|
||||
MaxOffsetY=max(GetPageY()-PageY, 0);
|
||||
MaxOffsetX=max(GetPageX()-PageX, 0);
|
||||
MaxOffsetY=max(getPageY()-PageY, 0);
|
||||
MaxOffsetX=max(getPageX()-PageX, 0);
|
||||
|
||||
if (OffsetY<0) OffsetY=0;
|
||||
else if (OffsetY>MaxOffsetY)
|
||||
@ -5856,7 +5867,7 @@ int gdioutput::setHighContrastMaxWidth() {
|
||||
OutputDebugString("Set high contrast\n");
|
||||
#endif
|
||||
|
||||
double w = GetPageX();
|
||||
double w = getPageX();
|
||||
double s = rc.right / w;
|
||||
if (!highContrast || (fabs(s-1.0) > 1e-3 && (s * scale) >= 1.0) ) {
|
||||
lockRefresh = true;
|
||||
@ -6441,12 +6452,18 @@ const string &gdioutput::recodeToNarrow(const wstring &input) {
|
||||
|
||||
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();
|
||||
size_t alloc = winput.length()*4+32;
|
||||
output.resize(alloc);
|
||||
@ -6957,3 +6974,21 @@ AutoCompleteInfo &gdioutput::addAutoComplete(const string &key) {
|
||||
void gdioutput::clearAutoComplete(const string &key) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -122,7 +122,7 @@ protected:
|
||||
bool startDoc(PrinterObject &po);
|
||||
|
||||
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;
|
||||
|
||||
@ -329,7 +329,8 @@ public:
|
||||
static const wstring &widen(const string &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);
|
||||
//FontEncoding getEncoding() const;
|
||||
@ -400,16 +401,8 @@ public:
|
||||
void disableTables();
|
||||
|
||||
void pasteText(const char *id);
|
||||
|
||||
bool writeHTML(const wstring &file, const wstring &title, int refreshTimeOut) const;
|
||||
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 print(pEvent oe, Table *t = 0, bool printMeOSHeader = true, bool noMargin = false, bool respectPageBreak = true);
|
||||
void print(PrinterObject &po, pEvent oe, bool printMeOSHeader = true, bool noMargin=false, bool respectPageBreak = true);
|
||||
void printSetup(PrinterObject &po);
|
||||
void destroyPrinterDC(PrinterObject &po);
|
||||
|
||||
@ -488,12 +481,12 @@ public:
|
||||
|
||||
void updateScrollbars() const;
|
||||
|
||||
void SetOffsetY(int oy){OffsetY=oy;}
|
||||
void SetOffsetX(int ox){OffsetX=ox;}
|
||||
int GetPageY(){return max(MaxY, 100)+60;}
|
||||
int GetPageX(){return max(MaxX, 100)+100;}
|
||||
int GetOffsetY(){return OffsetY;}
|
||||
int GetOffsetX(){return OffsetX;}
|
||||
void setOffsetY(int oy) {OffsetY=oy;}
|
||||
void setOffsetX(int ox) {OffsetX=ox;}
|
||||
int getPageY() const;
|
||||
int getPageX() const;
|
||||
int getOffsetY() const {return OffsetY;}
|
||||
int getOffsetX() const {return OffsetX;}
|
||||
|
||||
void RenderString(TextInfo &ti, const wstring &text, HDC hDC);
|
||||
void RenderString(TextInfo &ti, HDC hDC=0);
|
||||
@ -753,7 +746,7 @@ public:
|
||||
void setDBErrorState(bool state);
|
||||
friend int TablesCB(gdioutput *gdi, int type, void *data);
|
||||
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(double _scale, HWND hWndTarget, const PrinterObject &defprn);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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
|
||||
|
||||
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);}
|
||||
gdiFonts getGdiFont() const {return gdiFonts(format & 0xFF);}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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 {
|
||||
compile(false);
|
||||
oe.calculateResults(oEvent::RTClassResult);
|
||||
oe.calculateResults(oEvent::RTTotalResult);
|
||||
oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult);
|
||||
oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult);
|
||||
|
||||
declareSymbols(MRScore, true);
|
||||
if (prepareForTeam) {
|
||||
@ -1344,7 +1344,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
|
||||
controlId.first == oPunch::PunchStart) {
|
||||
|
||||
if (!totalResults) {
|
||||
oe.calculateResults(oEvent::RTClassResult, true);
|
||||
oe.calculateResults(set<int>(), oEvent::ResultType::ClassResult, true);
|
||||
for (pRunner r : runners) {
|
||||
ri.status = r->getStatus();
|
||||
if (ri.status == StatusUnknown) {
|
||||
@ -1373,7 +1373,7 @@ void GeneralResult::calculateIndividualResults(vector<pRunner> &runners,
|
||||
}
|
||||
}
|
||||
else {
|
||||
oe.calculateResults(oEvent::RTTotalResult, true);
|
||||
oe.calculateResults(set<int>(), oEvent::ResultType::TotalResult, true);
|
||||
for (pRunner r : runners) {
|
||||
ri.status = r->getTotalStatus();
|
||||
if (ri.status == StatusUnknown && r->getInputStatus() == StatusOK) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -539,7 +539,7 @@ Radera tävlingen = Wettkampf löschen
|
||||
Radera vakanser = Vakantplätze löschen
|
||||
Radiotider, kontroll = Funkposten-Zeiten, Posten
|
||||
Ranking = Ranking
|
||||
Ranking (IOF, xml) = Ranking (IOF, xml)
|
||||
Ranking (IOF, xml, csv) = Ranking (IOF, xml, csv)
|
||||
Rapport inför = Bericht für
|
||||
Rapporter = Berichte
|
||||
Redigera deltagaren = Teilnehmer bearbeiten
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
<image source="/meos?image=meos"><br>
|
||||
<h1>Documentation of MeOS REST API</h1>
|
||||
|
||||
<h2>Competition</h2>
|
||||
|
||||
@ -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 "png/png.h"
|
||||
#include <vector>
|
||||
|
||||
28
code/image.h
28
code/image.h
@ -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 <vector>
|
||||
@ -12,8 +34,6 @@ public:
|
||||
|
||||
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_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);
|
||||
@ -31,6 +51,8 @@ public:
|
||||
|
||||
HBITMAP loadImage(int resource, ImageMethod method);
|
||||
|
||||
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
|
||||
|
||||
int getWidth(int resource);
|
||||
int getHeight(int resource);
|
||||
void drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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;
|
||||
if (oe.getName() != name) {
|
||||
name = oe.getName();
|
||||
@ -170,6 +170,8 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
vector<pClass> cls;
|
||||
oe.getClasses(cls, false);
|
||||
for (size_t k = 0; k < cls.size(); k++) {
|
||||
if (cls[k]->getQualificationFinal())
|
||||
continue;
|
||||
int wid = cls[k]->getId();
|
||||
if (!includeCls.count(wid))
|
||||
continue;
|
||||
@ -207,7 +209,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
// Check if something was deleted
|
||||
for (map<int, InfoOrganization>::iterator it = organizations.begin(); it != organizations.end();) {
|
||||
if (!knownId.count(it->first)) {
|
||||
int oid = it->first;
|
||||
organizations.erase(it++);
|
||||
|
||||
if (allowDeletion)
|
||||
deleteMap.emplace_back("org", oid);
|
||||
else
|
||||
forceComplete = true;
|
||||
}
|
||||
else
|
||||
@ -218,8 +225,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
vector<pTeam> t;
|
||||
oe.getTeams(0, t, false);
|
||||
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;
|
||||
if (cid != 0 && t[k]->getClassRef(false)->getQualificationFinal() != nullptr)
|
||||
continue;
|
||||
|
||||
int wid = t[k]->getId();
|
||||
knownId.insert(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
|
||||
for (map<int, InfoTeam>::iterator it = teams.begin(); it != teams.end();) {
|
||||
if (!knownId.count(it->first)) {
|
||||
int tid = it->first;
|
||||
teams.erase(it++);
|
||||
|
||||
if (allowDeletion)
|
||||
deleteMap.emplace_back("tm", tid);
|
||||
else
|
||||
forceComplete = true;
|
||||
}
|
||||
else
|
||||
@ -243,8 +259,12 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
vector<pRunner> r;
|
||||
oe.getRunners(0, 0, r, false);
|
||||
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;
|
||||
if (cid != 0 && r[k]->getClassRef(true)->getQualificationFinal() != nullptr)
|
||||
continue;
|
||||
|
||||
int wid = r[k]->getId();
|
||||
knownId.insert(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
|
||||
for (map<int, InfoCompetitor>::iterator it = competitors.begin(); it != competitors.end();) {
|
||||
if (!knownId.count(it->first)) {
|
||||
int rid = it->first;
|
||||
competitors.erase(it++);
|
||||
if (allowDeletion)
|
||||
deleteMap.emplace_back("cmp", rid);
|
||||
else
|
||||
forceComplete = true;
|
||||
}
|
||||
else
|
||||
@ -265,7 +289,7 @@ bool InfoCompetition::synchronize(oEvent &oe, bool onlyCmp, const set<int> &incl
|
||||
}
|
||||
knownId.clear();
|
||||
|
||||
return !toCommit.empty() || forceComplete;
|
||||
return !toCommit.empty() || forceComplete || !deleteMap.empty();
|
||||
}
|
||||
|
||||
void InfoCompetition::needCommit(InfoBase &obj) {
|
||||
@ -499,7 +523,8 @@ bool InfoBaseCompetitor::synchronizeBase(oAbstractRunner &bc) {
|
||||
|
||||
bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &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 legInput = 0;
|
||||
@ -521,7 +546,7 @@ bool InfoCompetitor::synchronize(bool useTotalResults, bool useCourse, oRunner &
|
||||
legInput = r.getTotalTimeInput() * 10;
|
||||
s = r.getTotalStatusInput();
|
||||
}
|
||||
else if (t && r.getLegNumber() > 0) {
|
||||
else if (t && !isQF && r.getLegNumber() > 0) {
|
||||
legInput = t->getLegRunningTime(r.getLegNumber() - 1, false) * 10;
|
||||
s = t->getLegStatus(r.getLegNumber() - 1, false);
|
||||
}
|
||||
@ -549,7 +574,7 @@ bool InfoCompetitor::synchronize(const InfoCompetition &cmp, oRunner &r) {
|
||||
|
||||
vector<RadioTime> newRT;
|
||||
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++) {
|
||||
RadioTime radioTime;
|
||||
RunnerStatus s_split;
|
||||
@ -693,12 +718,21 @@ void InfoCompetition::getDiffXML(xmlbuffer &xml) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
(*it)->serialize(xml, true);
|
||||
}
|
||||
}
|
||||
|
||||
void InfoCompetition::commitComplete() {
|
||||
deleteMap.clear();
|
||||
toCommit.clear();
|
||||
forceComplete = false;
|
||||
}
|
||||
@ -767,8 +801,6 @@ void xmlbuffer::write(const char *tag,
|
||||
blocks.back().value = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void xmlbuffer::startXML(xmlparser &xml, const wstring &dest) {
|
||||
xml.openOutput(dest.c_str(), false);
|
||||
if (complete) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -227,6 +227,7 @@ protected:
|
||||
map<int, InfoOrganization> organizations;
|
||||
map<int, InfoCompetitor> competitors;
|
||||
map<int, InfoTeam> teams;
|
||||
vector<pair<string, int>> deleteMap;
|
||||
|
||||
void needCommit(InfoBase &obj);
|
||||
|
||||
@ -240,10 +241,10 @@ protected:
|
||||
void includeCourse(bool inc) { withCourse = inc; }
|
||||
|
||||
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) {
|
||||
set<int> dmy;
|
||||
return synchronize(oe, true, dmy, dmy);
|
||||
return synchronize(oe, true, dmy, dmy, false);
|
||||
}
|
||||
void getCompleteXML(xmlbuffer &xml);
|
||||
void getDiffXML(xmlbuffer &xml);
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
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/>.
|
||||
|
||||
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 {
|
||||
private:
|
||||
const static KEY NoKey = -1013;
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
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/>.
|
||||
|
||||
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 "intkeymap.hpp"
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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;
|
||||
xClsAssignment.getObjectString("ClassName", cname);
|
||||
if (cname.length() > 0) {
|
||||
pClass pc = oe.getClassCreate(0, cname);
|
||||
pClass pc = oe.getClassCreate(0, cname, matchedClasses);
|
||||
if (pc)
|
||||
cls2Stages.insert(make_pair(pc->getId(), vector<int>()) );
|
||||
}
|
||||
@ -510,7 +510,7 @@ void IOF30Interface::classAssignmentObsolete(gdioutput &gdi, xmlList &xAssignmen
|
||||
wstring cName;
|
||||
xCls[j].getObjectString("Name", cName);
|
||||
int id = xCls[j].getObjectInt("Id");
|
||||
pClass cls = oe.getClassCreate(id, cName);
|
||||
pClass cls = oe.getClassCreate(id, cName, matchedClasses);
|
||||
if (cls) {
|
||||
class2Courses[cls->getId()].push_back(pc);
|
||||
|
||||
@ -2314,7 +2314,8 @@ void IOF30Interface::setupRelayClasses(const map<int, vector<LegInfo> > &teamCla
|
||||
if (classId > 0) {
|
||||
pClass pc = oe.getClass(classId);
|
||||
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);
|
||||
}
|
||||
@ -2732,13 +2733,13 @@ void IOF30Interface::writeResult(xmlparser &xml, const oRunner &rPerson, const o
|
||||
|
||||
xml.endTag();
|
||||
}
|
||||
|
||||
pCourse crs = r.getCourse(!unrollLoops);
|
||||
bool doUnroll = unrollLoops && r.getNumShortening() == 0;
|
||||
pCourse crs = r.getCourse(!doUnroll);
|
||||
if (crs) {
|
||||
if (includeCourse)
|
||||
writeCourse(xml, *crs);
|
||||
|
||||
const vector<SplitData> &sp = r.getSplitTimes(unrollLoops);
|
||||
const vector<SplitData> &sp = r.getSplitTimes(doUnroll);
|
||||
if (r.getStatus()>0 && r.getStatus() != StatusDNS &&
|
||||
r.getStatus() != StatusCANCEL &&
|
||||
r.getStatus() != StatusNotCompetiting) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -65,6 +65,8 @@ class IOF30Interface {
|
||||
bool includeStageRaceInfo;
|
||||
void operator=(const IOF30Interface &);
|
||||
|
||||
set<wstring> matchedClasses;
|
||||
|
||||
struct LegInfo {
|
||||
int maxRunners;
|
||||
int minRunners;
|
||||
|
||||
@ -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.
|
||||
|
||||
------------------------------------
|
||||
Copyright 2007-2017 Melin Software HB.
|
||||
Copyright 2007-2019 Melin Software HB.
|
||||
|
||||
------------------------------------
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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;
|
||||
gdi.setCX(xp);
|
||||
yp += int(1.3 * gdi.getLineHeight());
|
||||
gdi.dropLine(1.3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/********************i****************************************************
|
||||
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
|
||||
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;
|
||||
vector<const oFreePunch *> pp;
|
||||
oe->synchronizeList(oLRunnerId, true, false);
|
||||
oe->synchronizeList(oLPunchId, false, true);
|
||||
oe->synchronizeList({ oListId::oLRunnerId, oListId::oLPunchId });
|
||||
|
||||
oe->getLatestPunches(lastTime, pp);
|
||||
processedPunches.clear();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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];
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (key.length() > 1)
|
||||
if (key.length() > 1 && _wtoi(key.c_str()) == 0)
|
||||
unknown[key] = L"";
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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
|
||||
static wchar_t settings[260];
|
||||
// Startup path
|
||||
static wchar_t programPath[MAX_PATH];
|
||||
wchar_t programPath[MAX_PATH];
|
||||
// Exe path
|
||||
static wchar_t exePath[MAX_PATH];
|
||||
wchar_t exePath[MAX_PATH];
|
||||
|
||||
|
||||
void mainMessageLoop(HACCEL hAccelTable, DWORD time) {
|
||||
@ -830,7 +830,7 @@ gdioutput *getExtraWindow(const string &tag, bool toForeGround) {
|
||||
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)
|
||||
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++) {
|
||||
if (gdi_extra[k]) {
|
||||
HWND hWnd = gdi_extra[k]->getHWNDTarget();
|
||||
RECT rc;
|
||||
if (GetWindowRect(hWnd, &rc)) {
|
||||
xp = max<int>(rc.left + 16, xp);
|
||||
yp = max<int>(rc.top + 32, yp);
|
||||
RECT rcc;
|
||||
if (GetWindowRect(hWnd, &rcc)) {
|
||||
xp = max<int>(rcc.left + 16, xp);
|
||||
yp = max<int>(rcc.top + 32, yp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int xs = gEvent->getPropertyInt("xsize", max(850, min(int(rc.right)-yp, 1124)));
|
||||
int ys = gEvent->getPropertyInt("ysize", max(650, min(int(rc.bottom)-yp-40, 800)));
|
||||
if (xp > rc.right - 100)
|
||||
xp = rc.right - 100;
|
||||
|
||||
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);
|
||||
if (max_y > 0)
|
||||
ys = min(max_y, ys);
|
||||
}
|
||||
|
||||
hWnd = CreateWindowEx(0, szWorkSpaceClass, title.c_str(),
|
||||
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
|
||||
@ -944,7 +953,8 @@ void InsertSICard(gdioutput &gdi, SICard &sic);
|
||||
|
||||
//static int xPos=0, yPos=0;
|
||||
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 skipTeamP = false;
|
||||
@ -952,11 +962,12 @@ void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
|
||||
static bool skipEconomyP = false;
|
||||
static bool skipListsP = false;
|
||||
static bool skipRunnersP = false;
|
||||
static bool skipCoursesP = false;
|
||||
static bool skipControlsP = false;
|
||||
|
||||
if (!force && onlyMain==onlyMainP && skipTeam==skipTeamP && skipSpeaker==skipSpeakerP &&
|
||||
skipEconomy==skipEconomyP && skipLists==skipListsP &&
|
||||
skipRunners==skipRunnersP && skipControls==skipControlsP)
|
||||
skipRunners==skipRunnersP && skipControls==skipControlsP && skipCourses == skipCoursesP)
|
||||
return;
|
||||
|
||||
onlyMainP = onlyMain;
|
||||
@ -965,6 +976,7 @@ void createTabs(bool force, bool onlyMain, bool skipTeam, bool skipSpeaker,
|
||||
skipEconomyP = skipEconomy;
|
||||
skipListsP = skipLists;
|
||||
skipRunnersP = skipRunners;
|
||||
skipCoursesP = skipCourses;
|
||||
skipControlsP = skipControls;
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
if (skipCourses && it->getType() == typeid(TabCourse))
|
||||
continue;
|
||||
|
||||
if (skipControls && it->getType() == typeid(TabControl))
|
||||
continue;
|
||||
|
||||
@ -1055,7 +1070,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
ic.dwICC=ICC_TAB_CLASSES ;
|
||||
InitCommonControlsEx(&ic);
|
||||
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
|
||||
break;
|
||||
@ -1278,7 +1293,7 @@ void scrollVertical(gdioutput *gdi, int yInc, HWND hWnd) {
|
||||
if (si.nPage==0)
|
||||
yInc = 0;
|
||||
|
||||
int yPos=gdi->GetOffsetY();
|
||||
int yPos=gdi->getOffsetY();
|
||||
int a=si.nMax-signed(si.nPage-1) - yPos;
|
||||
|
||||
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.bottom+=gdi->getHeight();
|
||||
ScrollArea.right=gdi->getWidth()-gdi->GetOffsetX()+15;
|
||||
ScrollArea.right=gdi->getWidth()-gdi->getOffsetX()+15;
|
||||
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.
|
||||
|
||||
@ -1331,7 +1346,7 @@ void updateScrollInfo(HWND hWnd, gdioutput &gdi, int nHeight, int nWidth) {
|
||||
|
||||
if (maxy>0) {
|
||||
si.nMax=maxy+nHeight;
|
||||
si.nPos=gdi.GetOffsetY();
|
||||
si.nPos=gdi.getOffsetY();
|
||||
si.nPage=nHeight;
|
||||
}
|
||||
else {
|
||||
@ -1344,7 +1359,7 @@ void updateScrollInfo(HWND hWnd, gdioutput &gdi, int nHeight, int nWidth) {
|
||||
si.nMin=0;
|
||||
if (maxx>0) {
|
||||
si.nMax=maxx+nWidth;
|
||||
si.nPos=gdi.GetOffsetX();
|
||||
si.nPos=gdi.getOffsetX();
|
||||
si.nPage=nWidth;
|
||||
}
|
||||
else {
|
||||
@ -1431,7 +1446,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
||||
//int hwndScrollBar = (HWND) lParam; // handle to scroll bar
|
||||
|
||||
int yInc;
|
||||
int yPos=gdi->GetOffsetY();
|
||||
int yPos=gdi->getOffsetY();
|
||||
RECT rc;
|
||||
GetClientRect(hWnd, &rc);
|
||||
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);
|
||||
gdi->storeAutoPos(gdi->GetOffsetY());
|
||||
gdi->storeAutoPos(gdi->getOffsetY());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1488,7 +1503,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
||||
//int hwndScrollBar = (HWND) lParam; // handle to scroll bar
|
||||
|
||||
int xInc;
|
||||
int xPos=gdi->GetOffsetX();
|
||||
int xPos=gdi->getOffsetX();
|
||||
|
||||
switch(nScrollCode)
|
||||
{
|
||||
@ -1552,7 +1567,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
||||
GetClientRect(hWnd, &ScrollArea);
|
||||
ClipArea=ScrollArea;
|
||||
|
||||
gdi->SetOffsetX(xPos);
|
||||
gdi->setOffsetX(xPos);
|
||||
|
||||
ScrollWindowEx (hWnd, -xInc, 0,
|
||||
0, &ClipArea,
|
||||
@ -1571,7 +1586,7 @@ LRESULT CALLBACK WorkSpaceWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
|
||||
case WM_MOUSEWHEEL: {
|
||||
int dz = GET_WHEEL_DELTA_WPARAM(wParam);
|
||||
scrollVertical(gdi, -dz, hWnd);
|
||||
gdi->storeAutoPos(gdi->GetOffsetY());
|
||||
gdi->storeAutoPos(gdi->getOffsetY());
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@ -169,7 +169,7 @@ BEGIN
|
||||
VALUE "FileDescription", "meos"
|
||||
VALUE "FileVersion", "3.3.0.1"
|
||||
VALUE "InternalName", "meos"
|
||||
VALUE "LegalCopyright", "Copyright © 2007-2018"
|
||||
VALUE "LegalCopyright", "Copyright © 2007-2019"
|
||||
VALUE "OriginalFilename", "meos.exe"
|
||||
VALUE "ProductName", " meos"
|
||||
VALUE "ProductVersion", "3.4.0.1"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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. */
|
||||
int getTimeZoneInfo(const wstring &date) {
|
||||
static wchar_t lastDate[16] = {0};
|
||||
@ -1839,7 +1853,10 @@ int getTimeZoneInfo(const wstring &date) {
|
||||
convertDateYMS(date, st, false);
|
||||
st.wHour = 12;
|
||||
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 datecodeUTC = ((utc.wYear * 12 + utc.wMonth) * 31) + utc.wDay;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -53,17 +53,10 @@ public:
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
bool checkValidDate(const wstring &date);
|
||||
|
||||
wstring convertSystemTime(const SYSTEMTIME &st);
|
||||
wstring convertSystemTimeOnly(const SYSTEMTIME &st);
|
||||
wstring convertSystemDate(const SYSTEMTIME &st);
|
||||
@ -83,7 +76,6 @@ const wstring &getTimeMS(int m);
|
||||
const wstring &formatTime(int rt);
|
||||
const wstring &formatTimeHMS(int rt);
|
||||
|
||||
//const string &formatTimeN(int rt);
|
||||
wstring formatTimeIOF(int rt, int zeroTime);
|
||||
|
||||
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, SYSTEMTIME &st, bool checkValid);
|
||||
|
||||
|
||||
// Convert a "general" time string to a MeOS compatible time string
|
||||
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)
|
||||
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
|
||||
@param m time to convert
|
||||
@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 getMeosCompectVersion();
|
||||
|
||||
void getSupporters(vector<wstring> &supp, vector<wstring> developSupp);
|
||||
void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp);
|
||||
|
||||
int countWords(const wchar_t *p);
|
||||
|
||||
@ -255,11 +241,6 @@ void capitalize(wstring &str);
|
||||
/** Initial capital letter for each word. */
|
||||
void capitalizeWords(wstring &str);
|
||||
|
||||
/*
|
||||
void capitalize(string &str);
|
||||
void capitalizeWords(string &str);*/
|
||||
|
||||
|
||||
wstring getTimeZoneString(const wstring &date);
|
||||
|
||||
/** Return bias in seconds. UTC = local time + bias. */
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
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();
|
||||
queryset << " Name=" << quote << toString(r->sName) << ", "
|
||||
<< " CardNo=" << r->CardNo << ", "
|
||||
<< " CardNo=" << r->cardNumber << ", "
|
||||
<< " StartNo=" << r->StartNo << ", "
|
||||
<< " StartTime=" << r->startTime << ", "
|
||||
<< " FinishTime=" << r->FinishTime << ", "
|
||||
@ -3680,6 +3680,11 @@ bool MeosSQL::skipSynchronize(const oBase &entity) const {
|
||||
notskipped++;
|
||||
return false;
|
||||
}
|
||||
namespace {
|
||||
int encode(oListId id) {
|
||||
return int(id);
|
||||
}
|
||||
}
|
||||
|
||||
int MeosSQL::getModifiedMask(oEvent &oe) {
|
||||
try {
|
||||
@ -3699,23 +3704,23 @@ int MeosSQL::getModifiedMask(oEvent &oe) {
|
||||
int e = r["oEvent"];
|
||||
|
||||
if (ctrl > oe.sqlCounterControls)
|
||||
res |= oLControlId;
|
||||
res |= encode(oListId::oLControlId);
|
||||
if (crs > oe.sqlCounterCourses)
|
||||
res |= oLCourseId;
|
||||
res |= encode(oListId::oLCourseId);
|
||||
if (cls > oe.sqlCounterClasses)
|
||||
res |= oLClassId;
|
||||
res |= encode(oListId::oLClassId);
|
||||
if (card > oe.sqlCounterCards)
|
||||
res |= oLCardId;
|
||||
res |= encode(oListId::oLCardId);
|
||||
if (club > oe.sqlCounterClubs)
|
||||
res |= oLClubId;
|
||||
res |= encode(oListId::oLClubId);
|
||||
if (punch > oe.sqlCounterPunches)
|
||||
res |= oLPunchId;
|
||||
res |= encode(oListId::oLPunchId);
|
||||
if (runner > oe.sqlCounterRunners)
|
||||
res |= oLRunnerId;
|
||||
res |= encode(oListId::oLRunnerId);
|
||||
if (t > oe.sqlCounterTeams)
|
||||
res |= oLTeamId;
|
||||
res |= encode(oListId::oLTeamId);
|
||||
if (e > oe.counter)
|
||||
res |= oLEventId;
|
||||
res |= encode(oListId::oLEventId);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -20,6 +20,7 @@
|
||||
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#pragma warning( disable : 4251)
|
||||
|
||||
#include <mysql++.h>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -55,7 +55,6 @@ using namespace std;
|
||||
Localizer lang;
|
||||
#endif
|
||||
|
||||
extern "C"{
|
||||
|
||||
int MEOSDB_API getMeosVersion()
|
||||
{
|
||||
@ -70,27 +69,27 @@ int getListMask(oEvent &oe) {
|
||||
return msql.getModifiedMask(oe);
|
||||
}
|
||||
|
||||
bool MEOSDB_API msSynchronizeList(oEvent *oe, int lid)
|
||||
bool MEOSDB_API msSynchronizeList(oEvent *oe, oListId lid)
|
||||
{
|
||||
nSynchList++;
|
||||
if (nSynchList % 100 == 99)
|
||||
OutputDebugString(L"Synchronized 100 lists\n");
|
||||
|
||||
if (lid==oLRunnerId)
|
||||
if (lid == oListId::oLRunnerId)
|
||||
return msql.syncListRunner(oe);
|
||||
else if (lid==oLClassId)
|
||||
else if (lid == oListId::oLClassId)
|
||||
return msql.syncListClass(oe);
|
||||
else if (lid==oLCourseId)
|
||||
else if (lid == oListId::oLCourseId)
|
||||
return msql.syncListCourse(oe);
|
||||
else if (lid==oLControlId)
|
||||
else if (lid == oListId::oLControlId)
|
||||
return msql.syncListControl(oe);
|
||||
else if (lid==oLClubId)
|
||||
else if (lid == oListId::oLClubId)
|
||||
return msql.syncListClub(oe);
|
||||
else if (lid==oLCardId)
|
||||
else if (lid == oListId::oLCardId)
|
||||
return msql.syncListCard(oe);
|
||||
else if (lid==oLPunchId)
|
||||
else if (lid == oListId::oLPunchId)
|
||||
return msql.syncListPunch(oe);
|
||||
else if (lid==oLTeamId)
|
||||
else if (lid == oListId::oLTeamId)
|
||||
return msql.syncListTeam(oe);
|
||||
|
||||
return false;
|
||||
@ -227,7 +226,6 @@ bool MEOSDB_API msReConnect()
|
||||
}
|
||||
|
||||
|
||||
} //Extern "C"
|
||||
|
||||
bool repairTables(const string &db, vector<string> &output) {
|
||||
return msql.repairTables(db, output);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -33,11 +33,10 @@ enum OpFailStatus {
|
||||
class oEvent;
|
||||
class oBase;
|
||||
|
||||
extern "C"{
|
||||
|
||||
#define MEOSDB_API
|
||||
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 msSynchronizeRead(oBase *obj);
|
||||
int MEOSDB_API msRemove(oBase *obj);
|
||||
@ -52,7 +51,7 @@ extern "C"{
|
||||
int MEOSDB_API msListCompetitions(oEvent *oe);
|
||||
|
||||
int getListMask(oEvent &oe);
|
||||
}
|
||||
|
||||
|
||||
bool repairTables(const string &db, vector<string> &output);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -27,9 +27,10 @@
|
||||
//V2: ABCDEFGHIHJKMN
|
||||
//V31: a
|
||||
//V33: abcde
|
||||
//V35: abcdefgh
|
||||
//V35: abcdef
|
||||
//V36: abcdef
|
||||
int getMeosBuild() {
|
||||
string revision("$Rev: 810 $");
|
||||
string revision("$Rev: 859 $");
|
||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||
}
|
||||
|
||||
@ -41,16 +42,16 @@ int getMeosBuild() {
|
||||
//V33: abcdefghij
|
||||
//V34: abcdfge
|
||||
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);
|
||||
}
|
||||
|
||||
wstring getBuildType() {
|
||||
return L"U3"; // No parantheses (...)
|
||||
return L"RC1"; // No parantheses (...)
|
||||
}
|
||||
|
||||
wstring getMajorVersion() {
|
||||
return L"3.5";
|
||||
return L"3.6";
|
||||
}
|
||||
|
||||
wstring getMeosFullVersion() {
|
||||
@ -70,24 +71,8 @@ wstring getMeosCompectVersion() {
|
||||
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"Western Race Services");
|
||||
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"Mats Holmberg, OK Gränsen");
|
||||
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"Hans Carlstedt, Sävedalens AIK");
|
||||
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"O-Travel");
|
||||
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"Ingemar Carlsson");
|
||||
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"Sala OK");
|
||||
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"SC vebr-sport");
|
||||
supp.emplace_back(L"IP Skogen Göteborg");
|
||||
reverse(supp.begin(), supp.end());
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************************
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -69,6 +69,10 @@ oListParam::oListParam() {
|
||||
timePerPage = 8000;
|
||||
margin = 5;
|
||||
screenMode = 0;
|
||||
|
||||
htmlScale = 1.0;
|
||||
htmlRows = 60;
|
||||
htmlTypeTag = "free";
|
||||
}
|
||||
|
||||
void oListParam::serialize(xmlparser &xml,
|
||||
@ -77,10 +81,10 @@ void oListParam::serialize(xmlparser &xml,
|
||||
xml.startTag("ListParam", "Name", name);
|
||||
xml.write("ListId", container.getUniqueId(listCode));
|
||||
string sel;
|
||||
for (set<int>::const_iterator it = selection.begin(); it != selection.end(); ++it) {
|
||||
for (int s : selection) {
|
||||
if (!sel.empty())
|
||||
sel += ";";
|
||||
sel += itos(*it);
|
||||
sel += itos(s);
|
||||
}
|
||||
xml.write("ClassId", sel);
|
||||
xml.write("LegNumber", legNumber);
|
||||
@ -90,13 +94,15 @@ void oListParam::serialize(xmlparser &xml,
|
||||
xml.write("Title", title);
|
||||
xml.writeBool("Large", useLargeSize);
|
||||
xml.writeBool("PageBreak", pageBreak);
|
||||
xml.writeBool("HideHeader", !showHeader);
|
||||
|
||||
xml.writeBool("ShowNamedSplits", showInterTimes);
|
||||
xml.writeBool("ShowInterTitle", showInterTitle);
|
||||
xml.writeBool("ShowSplits", showSplitTimes);
|
||||
xml.writeBool("ShowAnalysis", splitAnalysis);
|
||||
xml.write("InputNumber", inputNumber);
|
||||
if (nextList != 0) {
|
||||
map<int, int>::const_iterator res = idToIndex.find(nextList);
|
||||
auto res = idToIndex.find(nextList);
|
||||
if (res != idToIndex.end())
|
||||
xml.write("NextList", res->second);
|
||||
}
|
||||
@ -111,13 +117,19 @@ void oListParam::serialize(xmlparser &xml,
|
||||
|
||||
xml.write("ScreenMode", screenMode);
|
||||
|
||||
if (nColumns != 0) {
|
||||
if (nColumns != 0 || htmlTypeTag != "free") {
|
||||
xml.write("NumColumns", itos(nColumns));
|
||||
xml.writeBool("Animate", animate);
|
||||
xml.write("TimePerPage", timePerPage);
|
||||
xml.write("Margin", margin);
|
||||
}
|
||||
|
||||
if (htmlTypeTag != "free") {
|
||||
xml.write("HTML", htmlTypeTag);
|
||||
xml.write("PageRows", htmlRows);
|
||||
xml.write("Scale", to_string(htmlScale));
|
||||
}
|
||||
|
||||
xml.endTag();
|
||||
}
|
||||
|
||||
@ -142,6 +154,8 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
|
||||
|
||||
useLargeSize = xml.getObjectBool("Large");
|
||||
pageBreak = xml.getObjectBool("PageBreak");
|
||||
showHeader = !xml.getObjectBool("HideHeader");
|
||||
|
||||
showInterTimes = xml.getObjectBool("ShowNamedSplits");
|
||||
showSplitTimes = xml.getObjectBool("ShowSplits");
|
||||
splitAnalysis = xml.getObjectBool("ShowAnalysis");
|
||||
@ -163,7 +177,7 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
|
||||
|
||||
xml.getObjectString("Image", bgImage);
|
||||
|
||||
int nColumns = xml.getObjectInt("NumColumns");
|
||||
nColumns = xml.getObjectInt("NumColumns");
|
||||
|
||||
screenMode = xml.getObjectInt("ScreenMode");
|
||||
animate = xml.getObjectBool("Animate");
|
||||
@ -172,7 +186,22 @@ void oListParam::deserialize(const xmlobject &xml, const MetaListContainer &cont
|
||||
timePerPage = xml.getObjectInt("TimePerPage");
|
||||
|
||||
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;
|
||||
}
|
||||
@ -374,10 +403,18 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
li.calcResults = false;
|
||||
li.calcTotalResults = false;
|
||||
li.rogainingResults = false;
|
||||
li.calculateLiveResults = false;
|
||||
li.calcCourseClassResults = false;
|
||||
if (par.useControlIdResultFrom > 0 || par.useControlIdResultTo > 0)
|
||||
li.needPunches = true;
|
||||
const bool isPunchList = mList.listSubType == oListInfo::EBaseTypePunches;
|
||||
li.needPunches = oListInfo::PunchMode::SpecificPunch;
|
||||
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< pair<int, int>, int> linePostCount;
|
||||
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
|
||||
if (mp.type == lTeamPlace || mp.type == lRunnerPlace || mp.type == lRunnerGeneralPlace) {
|
||||
if (!li.calcResults) {
|
||||
oe->calculateResults(oEvent::RTClassResult);
|
||||
oe->calculateResults(set<int>(), oEvent::ResultType::ClassResult);
|
||||
oe->calculateTeamResults(false);
|
||||
}
|
||||
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 == lRunnerGeneralPlace) {
|
||||
if (!li.calcTotalResults) {
|
||||
oe->calculateResults(oEvent::RTTotalResult);
|
||||
oe->calculateResults(set<int>(), oEvent::ResultType::TotalResult);
|
||||
oe->calculateTeamResults(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) {
|
||||
if (!li.calcCourseClassResults)
|
||||
oe->calculateResults(oEvent::RTClassCourseResult);
|
||||
oe->calculateResults(set<int>(), oEvent::ResultType::ClassCourseResult);
|
||||
|
||||
li.calcCourseClassResults = true;
|
||||
}
|
||||
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);
|
||||
@ -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) {
|
||||
if (it->second == 1) {
|
||||
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
|
||||
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) {
|
||||
li.setFilter(*it);
|
||||
}
|
||||
if (li.filter(EFilterList::EFilterAnyResult) || sortOrder == SortOrder::ClassLiveResult)
|
||||
li.calculateLiveResults = true;
|
||||
|
||||
for (set<ESubFilterList>::const_iterator it = subFilter.begin();
|
||||
it != subFilter.end(); ++it) {
|
||||
li.setSubFilter(*it);
|
||||
@ -750,7 +791,6 @@ void MetaList::interpret(oEvent *oe, const gdioutput &gdi, const oListParam &par
|
||||
hasResults_ = true;
|
||||
}
|
||||
|
||||
|
||||
void Position::indent(int ind) {
|
||||
int end = pos.size() - 1;
|
||||
if (end < 1)
|
||||
@ -1629,15 +1669,17 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lPatrolClubNameNames] = L"PatrolClubNameNames";
|
||||
typeToSymbol[lRunnerFinish] = L"RunnerFinish";
|
||||
typeToSymbol[lRunnerTime] = L"RunnerTime";
|
||||
typeToSymbol[lRunnerGrossTime] = L"RunnerGrossTime";
|
||||
typeToSymbol[lRunnerTimeStatus] = L"RunnerTimeStatus";
|
||||
typeToSymbol[lRunnerTempTimeStatus] = L"RunnerTempTimeStatus";
|
||||
typeToSymbol[lRunnerTempTimeAfter] = L"RunnerTempTimeAfter";
|
||||
typeToSymbol[lRunnerTimeAfter] = L"RunnerTimeAfter";
|
||||
typeToSymbol[lRunnerClassCourseTimeAfter] = L"RunnerClassCourseTimeAfter";
|
||||
typeToSymbol[lRunnerMissedTime] = L"RunnerTimeLost";
|
||||
typeToSymbol[lRunnerLostTime] = L"RunnerTimeLost";
|
||||
typeToSymbol[lRunnerPlace] = L"RunnerPlace";
|
||||
typeToSymbol[lRunnerClassCoursePlace] = L"RunnerClassCoursePlace";
|
||||
typeToSymbol[lRunnerStart] = L"RunnerStart";
|
||||
typeToSymbol[lRunnerCheck] = L"RunnerCheck";
|
||||
typeToSymbol[lRunnerStartCond] = L"RunnerStartCond";
|
||||
typeToSymbol[lRunnerStartZero] = L"RunnerStartZero";
|
||||
typeToSymbol[lRunnerClub] = L"RunnerClub";
|
||||
@ -1674,6 +1716,7 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lRunnerPayMethod] = L"RunnerPayMethod";
|
||||
typeToSymbol[lRunnerEntryDate] = L"RunnerEntryDate";
|
||||
typeToSymbol[lRunnerEntryTime] = L"RunnerEntryTime";
|
||||
typeToSymbol[lRunnerId] = L"RunnerId";
|
||||
|
||||
typeToSymbol[lTeamName] = L"TeamName";
|
||||
typeToSymbol[lTeamStart] = L"TeamStart";
|
||||
@ -1693,13 +1736,18 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lTeamPointAdjustment] = L"TeamPointAdjustment";
|
||||
|
||||
typeToSymbol[lTeamTime] = L"TeamTime";
|
||||
typeToSymbol[lTeamGrossTime] = L"TeamGrossTime";
|
||||
typeToSymbol[lTeamStatus] = L"TeamStatus";
|
||||
typeToSymbol[lTeamClub] = L"TeamClub";
|
||||
typeToSymbol[lTeamRunner] = L"TeamRunner";
|
||||
typeToSymbol[lTeamRunnerCard] = L"TeamRunnerCard";
|
||||
typeToSymbol[lTeamBib] = L"TeamBib";
|
||||
typeToSymbol[lTeamStartNo] = L"TeamStartNo";
|
||||
|
||||
typeToSymbol[lPunchNamedTime] = L"PunchNamedTime";
|
||||
typeToSymbol[lPunchName] = L"PunchName";
|
||||
typeToSymbol[lPunchNamedSplit] = L"PunchNamedSplit";
|
||||
|
||||
typeToSymbol[lPunchTime] = L"PunchTime";
|
||||
typeToSymbol[lPunchControlNumber] = L"PunchControlNumber";
|
||||
typeToSymbol[lPunchControlCode] = L"PunchControlCode";
|
||||
@ -1707,6 +1755,12 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lPunchControlPlace] = L"PunchControlPlace";
|
||||
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[lTotalCounter] = L"TotalCounter";
|
||||
typeToSymbol[lSubCounter] = L"SubCounter";
|
||||
@ -1746,6 +1800,8 @@ void MetaList::initSymbols() {
|
||||
typeToSymbol[lControlRunnersLeft] = L"ControlRunnersLeft";
|
||||
typeToSymbol[lControlCodes] = L"ControlCodes";
|
||||
|
||||
typeToSymbol[lLineBreak] = L"LineBreak";
|
||||
|
||||
for (map<EPostType, wstring>::iterator it = typeToSymbol.begin();
|
||||
it != typeToSymbol.end(); ++it) {
|
||||
symbolToType[it->second] = it->first;
|
||||
@ -1760,7 +1816,8 @@ void MetaList::initSymbols() {
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeRunner] = "Runner";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeTeam] = "Team";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeClub] = "ClubRunner";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypePunches] = "Punches";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeCoursePunches] = "CoursePunches";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeAllPunches] = "AllPunches";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeNone] = "None";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeRunnerGlobal] = "RunnerGlobal";
|
||||
baseTypeToSymbol[oListInfo::EBaseTypeRunnerLeg] = "RunnerLeg";
|
||||
@ -1778,6 +1835,7 @@ void MetaList::initSymbols() {
|
||||
|
||||
if (symbolToBaseType.size() != oListInfo::EBasedTypeLast_)
|
||||
throw std::exception("Bad symbol setup");
|
||||
symbolToBaseType["Punches"] = oListInfo::EBaseTypeCoursePunches; // Back comp MeOS --3.5
|
||||
|
||||
orderToSymbol[ClassStartTime] = "ClassStartTime";
|
||||
orderToSymbol[ClassStartTimeClub] = "ClassStartTimeClub";
|
||||
@ -1789,6 +1847,7 @@ void MetaList::initSymbols() {
|
||||
orderToSymbol[SortByFinishTimeReverse] = "FinishTimeReverse";
|
||||
orderToSymbol[ClassFinishTime] = "ClassFinishTime";
|
||||
orderToSymbol[SortByStartTime] = "StartTime";
|
||||
orderToSymbol[SortByStartTimeClass] = "StartTimeClass";
|
||||
orderToSymbol[SortByEntryTime] = "EntryTime";
|
||||
orderToSymbol[ClassPoints] = "ClassPoints";
|
||||
orderToSymbol[ClassTotalResult] = "ClassTotalResult";
|
||||
@ -1796,6 +1855,8 @@ void MetaList::initSymbols() {
|
||||
orderToSymbol[CourseResult] = "CourseResult";
|
||||
orderToSymbol[CourseStartTime] = "CourseStartTime";
|
||||
orderToSymbol[ClassTeamLeg] = "ClassTeamLeg";
|
||||
orderToSymbol[ClassLiveResult] = "ClassLiveResult";
|
||||
orderToSymbol[ClassKnockoutTotalResult] = "ClassKnockoutTotalResult";
|
||||
orderToSymbol[Custom] = "CustomSort";
|
||||
|
||||
for (map<SortOrder, string>::iterator it = orderToSymbol.begin();
|
||||
@ -1818,6 +1879,8 @@ void MetaList::initSymbols() {
|
||||
filterToSymbol[EFilterVacant] = "FilterNotVacant";
|
||||
filterToSymbol[EFilterOnlyVacant] = "FilterOnlyVacant";
|
||||
filterToSymbol[EFilterHasNoCard] = "FilterNoCard";
|
||||
filterToSymbol[EFilterAnyResult] = "FilterAnyResult";
|
||||
filterToSymbol[EFilterAPIEntry] = "EFilterAPIEntry";
|
||||
|
||||
for (map<EFilterList, string>::iterator it = filterToSymbol.begin();
|
||||
it != filterToSymbol.end(); ++it) {
|
||||
@ -1836,6 +1899,8 @@ void MetaList::initSymbols() {
|
||||
subFilterToSymbol[ESubFilterVacant] = "FilterNotVacant";
|
||||
subFilterToSymbol[ESubFilterSameParallel] = "FilterSameParallel";
|
||||
subFilterToSymbol[ESubFilterSameParallelNotFirst] = "FilterSameParallelNotFirst";
|
||||
subFilterToSymbol[ESubFilterNotFinish] = "FilterNotFinish";
|
||||
subFilterToSymbol[ESubFilterNamedControl] = "FilterNamedControl";
|
||||
|
||||
for (map<ESubFilterList, string>::iterator it = subFilterToSymbol.begin();
|
||||
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() {}
|
||||
|
||||
@ -2426,7 +2498,8 @@ void MetaList::getBaseType(vector< pair<wstring, size_t> > &types, int ¤tT
|
||||
types.clear();
|
||||
for(map<oListInfo::EBaseType, string>::const_iterator it = baseTypeToSymbol.begin();
|
||||
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;
|
||||
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 ¤tTy
|
||||
tt.insert(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);
|
||||
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");
|
||||
}
|
||||
|
||||
void MetaListContainer::addListParam(oListParam ¶m) {
|
||||
int MetaListContainer::addListParam(oListParam ¶m) {
|
||||
param.saved = true;
|
||||
int ix = 0;
|
||||
if (!listParam.empty())
|
||||
@ -2502,6 +2579,7 @@ void MetaListContainer::addListParam(oListParam ¶m) {
|
||||
listParam[ix] = param;
|
||||
if (owner)
|
||||
owner->updateChanged();
|
||||
return ix;
|
||||
}
|
||||
|
||||
const oListParam &MetaListContainer::getParam(int index) const {
|
||||
@ -2606,3 +2684,79 @@ bool MetaList::supportClasses() const {
|
||||
else
|
||||
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
Loading…
Reference in New Issue
Block a user