MeOS version 3.6-1033 RC1

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

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
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);
}
void HTMLWriter::writeHTML(gdioutput &gdi, ostream &fout, const wstring &title, int refreshTimeOut, double scale) {
if (scale <= 0)
scale = 1.0;
fout << "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n" <<
" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n";
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";
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\">";
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);
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,
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";
void HTMLWriter::writeTableHTML(gdioutput &gdi,
ostream &fout,
const wstring &title,
bool simpleFormat,
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
@ -463,39 +506,39 @@ bool gdioutput::writeTableHTML(ostream &fout,
for (size_t k=0;k<row.size();k++) {
int thisCol=tableCoordinates[row[k]->xp];
if (k==0 && thisCol!=0)
fout << "<td" << lineclass << " colspan=\"" << thisCol << "\">&nbsp;</td>";
if (k == 0 && thisCol != 0)
fout << "<td" << lineclass << " colspan=\"" << thisCol << "\">&nbsp;</td>";
int nextCol;
if (row.size()==k+1)
nextCol=tableCoordinates.rbegin()->second;
else
nextCol=tableCoordinates[row[k+1]->xp];
int nextCol;
if (row.size() == k + 1)
nextCol = tableCoordinates.rbegin()->second;
else
nextCol = tableCoordinates[row[k + 1]->xp];
int colspan=nextCol-thisCol;
int colspan = nextCol - thisCol;
assert(colspan>0);
assert(colspan > 0);
string style;
string style;
if (row[k]->format&textRight)
style=" style=\"text-align:right\"";
if (row[k]->format&textRight)
style = " style=\"text-align:right\"";
if (colspan==1 && !sizeSet[thisCol]) {
fout << " <td" << lineclass << style << " width=\"" << int( (k+1<row.size()) ?
(row[k+1]->xp - row[k]->xp) : (MaxX-row[k]->xp)) << "\">";
sizeSet[thisCol]=true;
}
else if (colspan>1)
fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">";
else
fout << " <td" << lineclass << style << ">";
if (colspan == 1 && !sizeSet[thisCol]) {
fout << " <td" << lineclass << style << " width=\"" << int((k + 1 < row.size()) ?
(row[k + 1]->xp - row[k]->xp) : (MaxX - row[k]->xp)) << "\">";
sizeSet[thisCol] = true;
}
else if (colspan > 1)
fout << " <td" << lineclass << style << " colspan=\"" << colspan << "\">";
else
fout << " <td" << lineclass << style << ">";
gdiFonts font = row[k]->getGdiFont();
string starttag, endtag;
getStyle(styles, font, narrow(row[k]->font), "", starttag, endtag);
gdiFonts font = row[k]->getGdiFont();
string 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 &param, const oEvent &oe) {
write(gdi, file, title, param.getContentsDescriptor(oe), param.pageBreak, param.htmlTypeTag,
refresh != 0 ? refresh : param.timePerPage / 1000, param.htmlRows, param.nColumns,
param.timePerPage, param.margin, param.htmlScale);
}
void HTMLWriter::getPage(const oEvent &oe, string &out) const {
out = page;
}

114
code/HTMLWriter.h Normal file
View File

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

View File

@ -1,6 +1,6 @@
/************************************************************************
MeOS - Orienteering Software
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);
}

View File

@ -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);
};

View File

@ -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;

View File

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

View File

@ -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

View File

@ -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
}
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -36,7 +36,7 @@ bool getDesktopFile(wchar_t *fileNamePath, const wchar_t *fileName, const wchar_
bool getMeOSFile(wchar_t *FileNamePath, const wchar_t *FileName);
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);

View File

@ -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,8 +291,10 @@ int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
gdi.setInputStatus("ExportScript", stat);
gdi.setInputStatus("BrowseFile", stat);
gdi.setInputStatus("BrowseScript", stat);
gdi.setInputStatus("HTMLRefresh", stat);
gdi.setInputStatus("StructuredExport", stat);
if (gdi.hasField("HTMLRefresh")) {
gdi.setInputStatus("HTMLRefresh", stat);
gdi.setInputStatus("StructuredExport", stat);
}
}
else if (bu.id == "DoPrint") {
bool stat = gdi.isChecked(bu.id);
@ -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");
prm->structuredExport = gdi.isChecked("StructuredExport");
prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
if (!prm->readOnly) {
prm->structuredExport = gdi.isChecked("StructuredExport");
prm->htmlRefresh = gdi.isChecked("HTMLRefresh") ? t : 0;
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);
gdi.addCheckbox("StructuredExport", "Strukturerat exportformat", 0, structuredExport);
gdi.addCheckbox("HTMLRefresh", "HTML med AutoRefresh", 0, htmlRefresh != 0);
gdi.dropLine(1.2);
if (!readOnly) {
gdi.addCheckbox("StructuredExport", "Strukturerat exportformat", 0, structuredExport);
gdi.addCheckbox("HTMLRefresh", "HTML med AutoRefresh", 0, htmlRefresh != 0);
}
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,16 +750,17 @@ 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);
gdi.addListBox("Classes", 150, 300, 0, L"", L"", true);
gdi.pushX();
gdi.fillDown();
vector< pair<wstring, size_t> > d;
@ -771,8 +792,10 @@ 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.");
"Mellantider visas för namngivna kontroller.");
gdi.addCheckbox("SplitAnalysis", "Med sträcktidsanalys", 0, splitAnalysis);
gdi.addCheckbox("OnlyChanged", "Skriv endast ut ändade sidor", 0, po.onlyChanged);
@ -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()) {
if (structuredExport)
gdiPrint.writeTableHTML(exportFile, oe->getName(), htmlRefresh);
else
gdiPrint.writeHTML(exportFile, oe->getName(), htmlRefresh);
checkWriteAccess(exportFile);
wstring tExport = exportFile + L"~";
if (!readOnly) {
if (structuredExport)
HTMLWriter::writeTableHTML(gdiPrint, tExport, oe->getName(), htmlRefresh, 1.0);
else
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);

View File

@ -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;}

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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

View File

@ -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,7 +3262,8 @@ 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();
gdi.addListBox("ClassNewEntries", 200, 400, 0, L"Klasser där nyanmälningar ska överföras:", L"", true);
@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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;
@ -1523,13 +1528,13 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
else if (oe->isReadOnly())
gdi.addString("", fontLarge, makeDash(L"MeOS - Resultatkiosk")).setColor(colorDarkBlue);
gdi.dropLine();
gdi.dropLine();
gdi.pushX();
gdi.fillRight();
gdi.addSelection("ReportRunner", 300, 300, RunnerCB);
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll|oEvent::RunnerCompactMode);
oe->fillRunners(gdi, "ReportRunner", true, oEvent::RunnerFilterShowAll | oEvent::RunnerCompactMode);
gdi.selectItemByData("ReportRunner", runnerId);
if (!oe->isReadOnly()) {
@ -1545,44 +1550,51 @@ void TabRunner::showRunnerReport(gdioutput &gdi)
gdi.popX();
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,11 +1637,11 @@ 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;
gdi.pushX();
gdi.fillDown();
if (r->getTeam() == 0) {
@ -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,37 +2221,47 @@ void UpdateStatus(gdioutput &gdi, pRunner r)
gdi.setText("RunnerInfo", lang.tl(r->getProblemDescription()), true);
}
int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
{
DWORD rid=runnerId;
int TabRunner::punchesCB(gdioutput &gdi, int type, void *data) {
DWORD rid = runnerId;
if (!rid)
return 0;
pRunner r=oe->getRunner(rid, 0);
pRunner r = oe->getRunner(rid, 0);
if (!r){
if (!r) {
gdi.alert("Deltagaren måste sparas innan stämplingar kan hanteras.");
return 0;
}
if (type == GUI_LISTBOXSELECT) {
ListBoxInfo bi = *(ListBoxInfo *)data;
if (bi.id == "Course") {
if (signed(bi.data) >= 0) {
pCourse pc = r->getCourse(true);
if (!pc) return 0;
return gdi.sendCtrlMessage("AddC");
}
}
}
else if (type == GUI_LISTBOX) {
ListBoxInfo bi = *(ListBoxInfo *)data;
if (type==GUI_LISTBOX){
ListBoxInfo bi=*(ListBoxInfo *)data;
if (bi.id=="Punches") {
if (bi.id == "Punches") {
if (bi.data != -1) {
pCard card=r->getCard();
pCard card = r->getCard();
if (!card) return 0;
pPunch punch = card->getPunchByIndex(bi.data);
if (!punch)
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.setText("PTime", ptime);
gdi.enableInput("SaveC");
gdi.enableInput("RemoveC");
gdi.enableInput("PTime");
}
@ -2244,46 +2269,44 @@ 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);
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");
}
else{
else {
gdi.disableInput("AddC");
gdi.disableInput("AddAllC");
}
disablePunchCourseChange(gdi);
}
}
else if (type==GUI_BUTTON){
ButtonInfo bi=*(ButtonInfo *)data;
pCard card=r->getCard();
else if (type == GUI_BUTTON) {
ButtonInfo bi = *(ButtonInfo *)data;
pCard card = r->getCard();
if (!card){
if (!card) {
if (!gdi.ask(L"ask:addpunches"))
return 0;
card=oe->allocateCard(r);
card = oe->allocateCard(r);
card->setCardNo(r->getCardNo());
vector<int> mp;
r->addPunches(card, mp);
}
if (bi.id=="AddC"){
if (bi.id == "AddC") {
vector<int> mp;
r->evaluateCard(true, mp);
pCourse pc=r->getCourse(true);
pCourse pc = r->getCourse(true);
if (!pc) return 0;
@ -2292,7 +2315,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
if (!gdi.getSelectedItem("Course", lbi))
return 0;
oControl *oc=pc->getControl(lbi.data);
oControl *oc = pc->getControl(lbi.data);
if (!oc) return 0;
vector<int> nmp;
@ -2301,7 +2324,7 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
r->evaluateCard(true, nmp, oc->getFirstNumber()); //Add this punch
}
else {
for (size_t k = 0; k<mp.size(); k++) {
for (size_t k = 0; k < mp.size(); k++) {
if (oc->hasNumber(mp[k]))
r->evaluateCard(true, nmp, mp[k]); //Add this punch
}
@ -2314,13 +2337,12 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
card->fillPunches(gdi, "Punches", pc);
UpdateStatus(gdi, r);
}
else if (bi.id=="AddAllC"){
else if (bi.id == "AddAllC") {
vector<int> mp;
r->evaluateCard(true, mp);
vector<int>::iterator it=mp.begin();
vector<int>::iterator it = mp.begin();
while(it!=mp.end()){
while (it != mp.end()) {
vector<int> nmp;
r->evaluateCard(true, nmp, *it); //Add this punch
++it;
@ -2336,30 +2358,30 @@ int TabRunner::punchesCB(gdioutput &gdi, int type, void *data)
r->hasManuallyUpdatedTimeStatus();
UpdateStatus(gdi, r);
}
else if (bi.id=="SaveC"){
//int time=oe->GetRelTime();
else if (bi.id == "SaveC") {
if (!savePunchTime(r, gdi))
return false;
ListBoxInfo lbi;
if (!gdi.getSelectedItem("Punches", lbi))
return 0;
/*
pCard pc=r->getCard();
pCard pc=r->getCard();
if (!pc) return 0;
if (!pc) return 0;
pPunch pp = pc->getPunchByIndex(lbi.data);
pPunch pp = pc->getPunchByIndex(lbi.data);
if (!pp)
throw meosException("Punch not found.");
if (!pp)
throw meosException("Punch not found.");
pc->setPunchTime(pp, gdi.getText("PTime"));
pc->setPunchTime(pp, gdi.getText("PTime"));
r->evaluateCard(true, mp);
//synchronize SQL
card->synchronize();*/
vector<int> mp;
r->evaluateCard(true, mp);
//synchronize SQL
card->synchronize();
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,26 +2549,28 @@ bool TabRunner::loadPage(gdioutput &gdi)
if (numSL > 0)
gdi.fillRight();
gdi.addSelection("RCourse", numSL == 0 ? 220 : 180, 300, RunnerCB, L"Bana:");
oe->fillCourses(gdi, "RCourse", true);
gdi.addItem("RCourse", lang.tl("[Klassens bana]"), 0);
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);
if (numSL > 0) {
gdi.fillDown();
gdi.addSelection("NumShort", 60, 300, RunnerCB, L"Avkortning:");
vector< pair<wstring, size_t> > data;
if (numSL == 1) {
data.push_back(make_pair(lang.tl("Nej"), 0));
data.push_back(make_pair(lang.tl("Ja"), 1));
}
else {
data.push_back(make_pair(lang.tl("Nej"), 0));
for (int i = 1; i <= numSL; i++) {
data.push_back(make_pair(itow(i), i));
if (numSL > 0) {
gdi.fillDown();
gdi.addSelection("NumShort", 60, 300, RunnerCB, L"Avkortning:");
vector< pair<wstring, size_t> > data;
if (numSL == 1) {
data.push_back(make_pair(lang.tl("Nej"), 0));
data.push_back(make_pair(lang.tl("Ja"), 1));
}
else {
data.push_back(make_pair(lang.tl("Nej"), 0));
for (int i = 1; i <= numSL; i++) {
data.push_back(make_pair(itow(i), i));
}
}
gdi.addItem("NumShort", data);
gdi.popX();
}
gdi.addItem("NumShort", data);
gdi.popX();
}
gdi.pushX();
@ -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,19 +2863,33 @@ 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;
while (sh && !touch.count(sh->getId())) {
count++;
map<int, int>::iterator r = known.find(sh->getId());
if (r != known.end()) {
count += r->second;
break;
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()) {
count += r->second;
break;
}
touch.insert(sh->getId());
shInfo = sh->getShorterVersion();
sh = shInfo.second;
}
touch.insert(sh->getId());
sh = sh->getShorterVersion();
}
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)

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;
@ -864,14 +924,14 @@ int TabSpeaker::deducePreviousControl(int classId, int leg, int control) {
int TabSpeaker::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
{
if (bu.id=="Leg") {
if (classId>0) {
selectedControl[classId].setLeg(bu.data>=1000, bu.data%1000);
if (bu.id == "Leg") {
if (classId > 0) {
selectedControl[classId].setLeg(bu.data >= 1000, bu.data % 1000);
generateControlList(gdi, classId);
gdi.setRestorePoint("speaker");
gdi.setRestorePoint("SpeakerList");
bool shortNames = oe->getPropertyInt("SpeakerShortNames", false) != 0;
bool shortNames = oe->getPropertyInt("SpeakerShortNames", false) != 0;
oe->speakerList(gdi, classId, selectedControl[classId].getLeg(),
selectedControl[classId].getControl(),
selectedControl[classId].getPreviousControl(),
@ -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,24 +988,31 @@ 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) {
gdi.addButton(cx, cy, bw, classid, L"#" + pc->getName(), tabSpeakerCB, L"", false, false);
cx+=bw;
cb++;
if (cb>nbtn) {
cb=1;
cx=basex;
cy+=gdi.getButtonHeight()+4;
}
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++;
if (cb>nbtn) {
cb=1;
cx=basex;
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;
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;
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;
@ -1296,7 +1388,7 @@ void TabSpeaker::importSettings(gdioutput &gdi, multimap<string, wstring> &setti
if (rc.right > rc.left && rc.bottom > rc.top &&
rc.right > 50 && rc.left < (desktop.right - 50) &&
rc.bottom > 50 && rc.top < (desktop.bottom - 50))
gdi.setWindowsPosition(rc);
gdi.setWindowsPosition(rc);
}
wstring TabSpeaker::getSpeakerSettingsFile() {

View File

@ -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);

View File

@ -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))
@ -1431,9 +1439,12 @@ bool TabTeam::loadPage(gdioutput &gdi)
gdi.popX();
gdi.selectItemByData("Status", 0);
gdi.dropLine(1.5);
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();
if (multiDay) {
@ -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,7 +1887,8 @@ 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();
int otherLeg = r->getLegNumber();
@ -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);
oldR->setClassId(r->getClassId(false), 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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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())
@ -128,7 +129,58 @@ 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)

View File

@ -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;

View File

@ -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,35 +63,40 @@ 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];
fin.getline(bf, 2048);
while(fin.good() && strlen(bf)<3)
bool isCSVType = false;
while (fin.good() && !isCSVType) {
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;
}

View File

@ -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();

View File

@ -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

View File

@ -1014,7 +1014,7 @@ Kunde inte öppna tävlingen = Kan ikke åbne løbet
Kunde inte ansluta till Eventor = Kunne ikke forbinde til Eventor
Kunde inte 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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);}

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -1,4 +1,26 @@
#pragma once
/************************************************************************
MeOS - Orienteering Software
Copyright (C) 2009-2019 Melin Software HB
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Melin Software HB - software@melin.nu - www.melin.nu
Eksoppsvägen 16, SE-75646 UPPSALA, Sweden
************************************************************************/
#pragma once
#include <map>
#include <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);
@ -30,6 +50,8 @@ private:
public:
HBITMAP loadImage(int resource, ImageMethod method);
static vector<uint8_t> loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType);
int getWidth(int resource);
int getHeight(int resource);

View File

@ -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

View File

@ -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

View File

@ -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,8 +209,13 @@ 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++);
forceComplete = true;
if (allowDeletion)
deleteMap.emplace_back("org", oid);
else
forceComplete = true;
}
else
++it;
@ -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,8 +243,13 @@ 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++);
forceComplete = true;
if (allowDeletion)
deleteMap.emplace_back("tm", tid);
else
forceComplete = true;
}
else
++it;
@ -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,15 +277,19 @@ 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++);
forceComplete = true;
if (allowDeletion)
deleteMap.emplace_back("cmp", rid);
else
forceComplete = true;
}
else
++it;
}
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) {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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) {

View File

@ -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;

View File

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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,22 +847,31 @@ 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 (max_x>0)
xs = min(max_x, xs);
if (max_y>0)
ys = min(max_y, ys);
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,
xp, yp, max(xs, 200), max(ys, 100), 0, NULL, hInst, NULL);
@ -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;

View File

@ -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"

View File

@ -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;

View File

@ -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. */

View File

@ -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;
}

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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());
}

View File

@ -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 &currentT
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 &currentTy
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 &param) {
int MetaListContainer::addListParam(oListParam &param) {
param.saved = true;
int ix = 0;
if (!listParam.empty())
@ -2502,6 +2579,7 @@ void MetaListContainer::addListParam(oListParam &param) {
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