1183 lines
34 KiB
C++
1183 lines
34 KiB
C++
/************************************************************************
|
|
MeOS - Orienteering Software
|
|
Copyright (C) 2009-2018 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 "resource.h"
|
|
|
|
#include <commctrl.h>
|
|
#include <commdlg.h>
|
|
|
|
#include "oEvent.h"
|
|
#include "xmlparser.h"
|
|
#include "gdioutput.h"
|
|
#include "csvparser.h"
|
|
#include "SportIdent.h"
|
|
#include "classconfiginfo.h"
|
|
#include "onlineresults.h"
|
|
#include "onlineinput.h"
|
|
#include "RestService.h"
|
|
|
|
#include "TabAuto.h"
|
|
#include "TabSI.h"
|
|
#include "meos_util.h"
|
|
#include <shellapi.h>
|
|
|
|
#include "gdiconstants.h"
|
|
#include "meosexception.h"
|
|
|
|
static TabAuto *tabAuto = 0;
|
|
int AutoMachine::uniqueId = 1;
|
|
|
|
extern HWND hWndMain;
|
|
extern HWND hWndWorkspace;
|
|
|
|
TabAuto::TabAuto(oEvent *poe):TabBase(poe)
|
|
{
|
|
synchronize=false;
|
|
synchronizePunches=false;
|
|
}
|
|
|
|
AutoMachine *AutoMachine::getMachine(int id) {
|
|
if (tabAuto)
|
|
return tabAuto->getMachine(id);
|
|
throw meosException("Internal error");
|
|
}
|
|
|
|
AutoMachine* AutoMachine::construct(Machines ms) {
|
|
switch(ms) {
|
|
case mPrintResultsMachine:
|
|
return new PrintResultMachine(0);
|
|
case mSplitsMachine:
|
|
return new SplitsMachine();
|
|
case mPrewarningMachine:
|
|
return new PrewarningMachine();
|
|
case mPunchMachine:
|
|
return new PunchMachine();
|
|
case mOnlineInput:
|
|
return new OnlineInput();
|
|
case mOnlineResults:
|
|
return new OnlineResults();
|
|
case mSaveBackup:
|
|
return new SaveMachine();
|
|
case mInfoService:
|
|
return new RestService();
|
|
}
|
|
throw meosException("Invalid machine");
|
|
}
|
|
|
|
AutoMachine *TabAuto::getMachine(int id) {
|
|
if (id == 0)
|
|
return 0;
|
|
list<AutoMachine *>::iterator it;
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
if (*it != 0 && (*it)->getId() == id) {
|
|
return *it;
|
|
}
|
|
}
|
|
throw meosException("Service X not found.#" + itos(id));
|
|
}
|
|
|
|
TabAuto::~TabAuto(void)
|
|
{
|
|
list<AutoMachine *>::iterator it;
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
delete *it;
|
|
*it=0;
|
|
}
|
|
tabAuto=0;
|
|
}
|
|
|
|
|
|
void tabAutoKillMachines()
|
|
{
|
|
if (tabAuto)
|
|
tabAuto->killMachines();
|
|
}
|
|
|
|
void tabAutoRegister(TabAuto *ta)
|
|
{
|
|
tabAuto=ta;
|
|
}
|
|
|
|
void tabAutoAddMachinge(const AutoMachine &am)
|
|
{
|
|
if (tabAuto) {
|
|
tabAuto->addMachine(am);
|
|
}
|
|
}
|
|
|
|
void tabForceSync(gdioutput &gdi, pEvent oe)
|
|
{
|
|
if (tabAuto)
|
|
tabAuto->syncCallback(gdi);
|
|
}
|
|
|
|
int AutomaticCB(gdioutput *gdi, int type, void *data)
|
|
{
|
|
if (!tabAuto)
|
|
throw std::exception("tabAuto undefined.");
|
|
|
|
switch(type){
|
|
case GUI_BUTTON: {
|
|
//Make a copy
|
|
ButtonInfo bu=*static_cast<ButtonInfo *>(data);
|
|
return tabAuto->processButton(*gdi, bu);
|
|
}
|
|
case GUI_LISTBOX:{
|
|
ListBoxInfo lbi=*static_cast<ListBoxInfo *>(data);
|
|
return tabAuto->processListBox(*gdi, lbi);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void TabAuto::syncCallback(gdioutput &gdi)
|
|
{
|
|
wstring msg;
|
|
try {
|
|
list<AutoMachine *>::iterator it;
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
AutoMachine *am=*it;
|
|
if (am && am->synchronize && !am->isEditMode())
|
|
am->process(gdi, oe, SyncDataUp);
|
|
}
|
|
}
|
|
catch (meosException &ex) {
|
|
msg = ex.wwhat();
|
|
}
|
|
catch(std::exception &ex) {
|
|
msg = gdi.widen(ex.what());
|
|
}
|
|
catch(...) {
|
|
msg = L"Ett okänt fel inträffade.";
|
|
}
|
|
if (!msg.empty()) {
|
|
gdi.alert(msg);
|
|
gdi.setWaitCursor(false);
|
|
}
|
|
|
|
}
|
|
|
|
void TabAuto::updateSyncInfo()
|
|
{
|
|
list<AutoMachine *>::iterator it;
|
|
synchronize=false;
|
|
synchronizePunches=false;
|
|
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
AutoMachine *am=*it;
|
|
if (am){
|
|
am->synchronize= am->synchronize || am->synchronizePunches;
|
|
synchronize=synchronize || am->synchronize;
|
|
synchronizePunches=synchronizePunches || am->synchronizePunches;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TabAuto::timerCallback(gdioutput &gdi)
|
|
{
|
|
DWORD tc=GetTickCount();
|
|
|
|
list<AutoMachine *>::iterator it;
|
|
bool reload=false;
|
|
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
AutoMachine *am=*it;
|
|
if (am && am->interval && tc >= am->timeout && !am->isEditMode()) {
|
|
am->process(gdi, oe, SyncTimer);
|
|
setTimer(am);
|
|
reload=true;
|
|
}
|
|
}
|
|
|
|
DWORD d=0;
|
|
if (reload && !editMode && gdi.getData("AutoPage", d) && d)
|
|
loadPage(gdi);
|
|
}
|
|
|
|
void TabAuto::setTimer(AutoMachine *am)
|
|
{
|
|
DWORD tc=GetTickCount();
|
|
|
|
if (am->interval>0) {
|
|
DWORD to=am->interval*1000+tc;
|
|
|
|
if (to<tc) { //Warp-around. No reasonable way to handle it
|
|
to=DWORD(0);
|
|
am->interval=0;
|
|
}
|
|
|
|
am->timeout=to;
|
|
}
|
|
}
|
|
|
|
int TabAuto::processButton(gdioutput &gdi, const ButtonInfo &bu)
|
|
{
|
|
|
|
if (bu.id=="GenerateCMP") {
|
|
#ifndef MEOSDB
|
|
int nClass=gdi.getTextNo("nClass");
|
|
int nRunner=gdi.getTextNo("nRunner");
|
|
|
|
if (nRunner>0 &&
|
|
gdi.ask(L"Vill du dumpa aktuellt tävling och skapa en testtävling?")) {
|
|
oe->generateTestCompetition(nClass, nRunner, gdi.isChecked("UseRelay"));
|
|
gdi.getTabs().get(TCmpTab)->loadPage(gdi);
|
|
return 0;
|
|
}
|
|
#endif
|
|
}
|
|
else if (bu.id == "BrowseFolder") {
|
|
const wchar_t *edit = bu.getExtra();
|
|
wstring currentPath = gdi.getText(gdi.narrow(edit));
|
|
wstring newPath = gdi.browseForFolder(currentPath, 0);
|
|
if (!newPath.empty())
|
|
gdi.setText(edit, newPath);
|
|
}
|
|
else if (bu.id == "StartBackup") {
|
|
SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt()));
|
|
if (sm)
|
|
sm->saveSettings(gdi);
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id=="Result") {
|
|
PrintResultMachine *sm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mPrintResultsMachine);
|
|
}
|
|
else if (bu.id == "BrowseFile") {
|
|
static int index = 0;
|
|
vector< pair<wstring, wstring> > ext;
|
|
ext.push_back(make_pair(L"Webbdokument", L"*.html;*.htm"));
|
|
|
|
wstring file = gdi.browseForSave(ext, L"html", index);
|
|
if (!file.empty())
|
|
gdi.setText("ExportFile", file);
|
|
}
|
|
else if (bu.id == "BrowseScript") {
|
|
vector< pair<wstring, wstring> > ext;
|
|
ext.push_back(make_pair(L"Skript", L"*.bat;*.exe;*.js"));
|
|
|
|
wstring file = gdi.browseForOpen(ext, L"bat");
|
|
if (!file.empty())
|
|
gdi.setText("ExportScript", file);
|
|
}
|
|
else if (bu.id == "DoExport") {
|
|
bool stat = gdi.isChecked(bu.id);
|
|
gdi.setInputStatus("ExportFile", stat);
|
|
gdi.setInputStatus("ExportScript", stat);
|
|
gdi.setInputStatus("BrowseFile", stat);
|
|
gdi.setInputStatus("BrowseScript", stat);
|
|
gdi.setInputStatus("HTMLRefresh", stat);
|
|
gdi.setInputStatus("StructuredExport", stat);
|
|
}
|
|
else if (bu.id == "DoPrint") {
|
|
bool stat = gdi.isChecked(bu.id);
|
|
gdi.setInputStatus("PrinterSetup", stat);
|
|
}
|
|
else if (bu.id=="Splits") {
|
|
SplitsMachine *sm=dynamic_cast<SplitsMachine*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mSplitsMachine);
|
|
}
|
|
else if (bu.id=="Prewarning") {
|
|
PrewarningMachine *sm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mPrewarningMachine);
|
|
}
|
|
else if (bu.id=="Punches") {
|
|
PunchMachine *sm=dynamic_cast<PunchMachine*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mPunchMachine);
|
|
}
|
|
else if (bu.id=="OnlineResults") {
|
|
OnlineResults *sm=dynamic_cast<OnlineResults*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mOnlineResults);
|
|
}
|
|
else if (bu.id=="OnlineInput") {
|
|
OnlineInput *sm=dynamic_cast<OnlineInput*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mOnlineInput);
|
|
}
|
|
else if (bu.id=="SaveBackup") {
|
|
SaveMachine *sm=dynamic_cast<SaveMachine*>(getMachine(bu.getExtraInt()));
|
|
settings(gdi, sm, mSaveBackup);
|
|
}
|
|
else if (bu.id == "InfoService") {
|
|
settings(gdi, getMachine(bu.getExtraInt()), mInfoService);
|
|
}
|
|
else if (bu.id=="StartResult") {
|
|
#ifndef MEOSDB
|
|
wstring minute=gdi.getText("Interval");
|
|
int t=convertAbsoluteTimeMS(minute);
|
|
|
|
if (t<2 || t>7200) {
|
|
gdi.alert("Intervallet måste anges på formen MM:SS.");
|
|
}
|
|
else {
|
|
PrintResultMachine *prm=dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (prm) {
|
|
prm->interval = t;
|
|
prm->doExport = gdi.isChecked("DoExport");
|
|
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) {
|
|
gdi.getSelection("Classes", prm->classesToPrint);
|
|
|
|
ListBoxInfo lbi;
|
|
if (gdi.getSelectedItem("ListType", lbi)) {
|
|
oListParam par;
|
|
par.selection=prm->classesToPrint;
|
|
par.listCode = EStdListType(lbi.data);
|
|
par.pageBreak = gdi.isChecked("PageBreak");
|
|
par.showInterTimes = gdi.isChecked("ShowInterResults");
|
|
par.splitAnalysis = gdi.isChecked("SplitAnalysis");
|
|
int legNr = gdi.getSelectedItem("LegNumber").first;
|
|
if (legNr >= 0)
|
|
par.setLegNumberCoded(legNr);
|
|
else
|
|
par.setLegNumberCoded(0);
|
|
|
|
oe->generateListInfo(par, gdi.getLineHeight(), prm->listInfo);
|
|
}
|
|
}
|
|
prm->po.onlyChanged = gdi.isChecked("OnlyChanged");
|
|
prm->pageBreak = gdi.isChecked("PageBreak");
|
|
prm->showInterResult = gdi.isChecked("ShowInterResults");
|
|
prm->splitAnalysis = gdi.isChecked("SplitAnalysis");
|
|
prm->synchronize=true; //To force continuos data sync.
|
|
setTimer(prm);
|
|
}
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
#endif
|
|
}
|
|
else if (bu.id=="StartSplits") {
|
|
|
|
wstring ivt = gdi.getText("Interval");
|
|
|
|
int iv = gdi.getTextNo("Interval");
|
|
const wstring &file=gdi.getText("FileName");
|
|
|
|
if (!ivt.empty() && (iv < 1 || iv > 7200)) {
|
|
throw meosException(L"Ogiltigt antal sekunder: X#" + gdi.getText("Interval"));
|
|
}
|
|
|
|
if (file.empty()) {
|
|
throw meosException("Filnamnet får inte vara tomt");
|
|
}
|
|
|
|
//Try exporting.
|
|
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false,
|
|
set<int>(), -1, false, true, true, false);
|
|
SplitsMachine *sm=dynamic_cast<SplitsMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (sm) {
|
|
sm->interval=iv;
|
|
|
|
sm->file=file;
|
|
sm->synchronize=true;
|
|
setTimer(sm);
|
|
}
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id=="Save") { // General save
|
|
AutoMachine *sm=getMachine(bu.getExtraInt());
|
|
if (sm) {
|
|
sm->save(*oe, gdi);
|
|
setTimer(sm);
|
|
}
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id=="StartPrewarning") {
|
|
PrewarningMachine *pwm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (pwm) {
|
|
pwm->waveFolder=gdi.getText("WaveFolder");
|
|
gdi.getSelection("Controls", pwm->controls);
|
|
|
|
oe->synchronizeList(oLPunchId);
|
|
oe->clearPrewarningSounds();
|
|
|
|
pwm->synchronizePunches=true;
|
|
pwm->controlsSI.clear();
|
|
for (set<int>::iterator it=pwm->controls.begin();it!=pwm->controls.end();++it) {
|
|
pControl pc=oe->getControl(*it, false);
|
|
|
|
if (pc)
|
|
pwm->controlsSI.insert(pc->Numbers, pc->Numbers+pc->nNumbers);
|
|
}
|
|
}
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id=="StartPunch") {
|
|
|
|
wstring minute=gdi.getText("Interval");
|
|
int t=_wtoi(minute.c_str());
|
|
|
|
if (t<1 || t>7200) {
|
|
throw meosException(L"Ogiltigt antal sekunder: X#" + minute);
|
|
}
|
|
else {
|
|
PunchMachine *pm=dynamic_cast<PunchMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (pm) {
|
|
pm->interval=t;
|
|
pm->radio=gdi.getTextNo("Radio");
|
|
setTimer(pm);
|
|
}
|
|
}
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id == "Cancel") {
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id == "Stop") {
|
|
if (bu.getExtraInt())
|
|
stopMachine(getMachine(bu.getExtraInt()));
|
|
|
|
updateSyncInfo();
|
|
loadPage(gdi);
|
|
}
|
|
else if (bu.id == "PrinterSetup") {
|
|
PrintResultMachine *prm =
|
|
dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (prm) {
|
|
gdi.printSetup(prm->po);
|
|
}
|
|
}
|
|
else if (bu.id == "PrintNow") {
|
|
PrintResultMachine *prm =
|
|
dynamic_cast<PrintResultMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (prm) {
|
|
prm->process(gdi, oe, SyncNone);
|
|
setTimer(prm);
|
|
loadPage(gdi);
|
|
}
|
|
}
|
|
else if (bu.id == "SelectAll") {
|
|
const wchar_t *ctrl = bu.getExtra();
|
|
set<int> lst;
|
|
lst.insert(-1);
|
|
gdi.setSelection(ctrl, lst);
|
|
}
|
|
else if (bu.id == "SelectNone") {
|
|
const wchar_t *ctrl= bu.getExtra();
|
|
set<int> lst;
|
|
gdi.setSelection(ctrl, lst);
|
|
}
|
|
else if (bu.id == "TestVoice") {
|
|
PrewarningMachine *pwm=dynamic_cast<PrewarningMachine*>(getMachine(bu.getExtraInt()));
|
|
|
|
if (pwm)
|
|
oe->tryPrewarningSounds(pwm->waveFolder, rand()%400+1);
|
|
}
|
|
else if ( bu.id == "WaveBrowse") {
|
|
wstring wf=gdi.browseForFolder(gdi.getText("WaveFolder"), 0);
|
|
|
|
if (wf.length()>0)
|
|
gdi.setText("WaveFolder", wf);
|
|
}
|
|
else if ( bu.id == "BrowseSplits") {
|
|
int index=0;
|
|
vector< pair<wstring, wstring> > ext;
|
|
ext.push_back(make_pair(L"Sträcktider", L"*.xml"));
|
|
|
|
wstring wf = gdi.browseForSave(ext, L"xml", index);
|
|
|
|
if (!wf.empty())
|
|
gdi.setText("FileName", wf);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int TabAuto::processListBox(gdioutput &gdi, const ListBoxInfo &bu)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
bool TabAuto::stopMachine(AutoMachine *am)
|
|
{
|
|
list<AutoMachine *>::iterator it;
|
|
for (it=machines.begin(); it!=machines.end(); ++it)
|
|
if (am==*it) {
|
|
if (am->stop()) {
|
|
delete am;
|
|
machines.erase(it);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TabAuto::settings(gdioutput &gdi, AutoMachine *sm, Machines ms) {
|
|
editMode=true;
|
|
bool createNew = (sm==0);
|
|
if (!sm) {
|
|
sm = AutoMachine::construct(ms);
|
|
machines.push_back(sm);
|
|
}
|
|
|
|
gdi.restore("", false);
|
|
gdi.dropLine();
|
|
int cx = gdi.getCX();
|
|
int cy = gdi.getCY();
|
|
int d = gdi.scaleLength(6);
|
|
gdi.setCX(cx + d);
|
|
sm->setEditMode(true);
|
|
sm->settings(gdi, *oe, createNew);
|
|
int w = gdi.getWidth();
|
|
int h = gdi.getHeight();
|
|
|
|
RECT rc;
|
|
rc.top = cy - d;
|
|
rc.bottom = h + d;
|
|
rc.left = cx - d;
|
|
rc.right = w + d;
|
|
gdi.addRectangle(rc, colorLightBlue, true, true);
|
|
gdi.refresh();
|
|
}
|
|
|
|
void TabAuto::killMachines()
|
|
{
|
|
while(!machines.empty()) {
|
|
machines.back()->stop();
|
|
delete machines.back();
|
|
machines.pop_back();
|
|
}
|
|
AutoMachine::resetGlobalId();
|
|
}
|
|
|
|
bool TabAuto::loadPage(gdioutput &gdi)
|
|
{
|
|
oe->checkDB();
|
|
tabAuto=this;
|
|
editMode=false;
|
|
gdi.selectTab(tabId);
|
|
DWORD isAP = 0;
|
|
gdi.getData("AutoPage", isAP);
|
|
int storedOY = 0;
|
|
int storedOX = 0;
|
|
if (isAP) {
|
|
storedOY = gdi.GetOffsetY();
|
|
storedOX = gdi.GetOffsetX();
|
|
}
|
|
|
|
gdi.clearPage(false);
|
|
gdi.setData("AutoPage", 1);
|
|
gdi.addString("", boldLarge, "Automater");
|
|
gdi.setRestorePoint();
|
|
|
|
gdi.addString("", 10, "help:10000");
|
|
|
|
gdi.dropLine();
|
|
gdi.addString("", fontMediumPlus, "Tillgängliga automater").setColor(colorDarkBlue);
|
|
gdi.dropLine();
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
gdi.addButton("Result", "Resultatutskrift / export", AutomaticCB, "tooltip:resultprint");
|
|
gdi.addButton("OnlineResults", "Resultat online", AutomaticCB, "Publicera resultat direkt på nätet");
|
|
gdi.addButton("OnlineInput", "Inmatning online", AutomaticCB, "Hämta stämplingar m.m. från nätet");
|
|
gdi.popX();
|
|
gdi.dropLine(2.5);
|
|
gdi.addButton("SaveBackup", "Säkerhetskopiering", AutomaticCB);
|
|
gdi.addButton("InfoService", "Informationsserver", AutomaticCB);
|
|
gdi.addButton("Punches", "Stämplingstest", AutomaticCB, "Simulera inläsning av stämplar");
|
|
gdi.popX();
|
|
gdi.dropLine(2.5);
|
|
gdi.addButton("Splits", "Sträcktider (WinSplits)", AutomaticCB, "Spara sträcktider till en fil för automatisk synkronisering med WinSplits");
|
|
gdi.addButton("Prewarning", "Förvarningsröst", AutomaticCB, "tooltip:voice");
|
|
|
|
|
|
gdi.fillDown();
|
|
gdi.dropLine(3);
|
|
gdi.popX();
|
|
|
|
if (!machines.empty()) {
|
|
gdi.addString("", fontMediumPlus, "Startade automater").setColor(colorDarkBlue);;
|
|
list<AutoMachine *>::iterator it;
|
|
|
|
int baseX = gdi.getCX();
|
|
int dx = gdi.scaleLength(6);
|
|
|
|
for (it=machines.begin(); it!=machines.end(); ++it) {
|
|
AutoMachine *am=*it;
|
|
if (am) {
|
|
RECT rc;
|
|
rc.left = baseX;
|
|
rc.right = gdi.scaleLength(500);
|
|
rc.top = gdi.getCY();
|
|
gdi.dropLine(0.5);
|
|
gdi.setCX(baseX+dx);
|
|
am->setEditMode(false);
|
|
am->status(gdi);
|
|
gdi.setCX(baseX);
|
|
gdi.dropLine(0.5);
|
|
rc.bottom = gdi.getCY();
|
|
gdi.addRectangle(rc, colorLightGreen, true, true);
|
|
gdi.dropLine();
|
|
}
|
|
}
|
|
gdi.dropLine();
|
|
}
|
|
|
|
if (isAP) {
|
|
gdi.setOffset(storedOY, storedOY, true);
|
|
}
|
|
|
|
gdi.refresh();
|
|
return true;
|
|
}
|
|
|
|
void AutoMachine::settingsTitle(gdioutput &gdi, char *title) {
|
|
gdi.dropLine(0.5);
|
|
gdi.addString("", fontMediumPlus, title).setColor(colorDarkBlue);
|
|
gdi.dropLine(0.5);
|
|
}
|
|
|
|
void AutoMachine::startCancelInterval(gdioutput &gdi, char *startCommand, bool created, IntervalType type, const wstring &intervalIn) {
|
|
gdi.pushX();
|
|
gdi.fillRight();
|
|
if (type == IntervalMinute)
|
|
gdi.addInput("Interval", intervalIn, 7, 0, L"Tidsintervall (MM:SS):");
|
|
else if (type == IntervalSecond)
|
|
gdi.addInput("Interval", intervalIn, 7, 0, L"Tidsintervall (sekunder):");
|
|
gdi.dropLine(1);
|
|
gdi.addButton(startCommand, created ? "Starta automaten" : "OK", AutomaticCB).setExtra(getId());
|
|
if (!created)
|
|
gdi.addButton("Cancel", "Avbryt", AutomaticCB).setExtra(getId());
|
|
|
|
gdi.addButton("Stop", created ? "Avbryt" : "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
|
|
gdi.popX();
|
|
gdi.fillDown();
|
|
gdi.dropLine(2.5);
|
|
int dx = gdi.scaleLength(3);
|
|
RECT rc;
|
|
rc.left = gdi.getCX() - dx;
|
|
rc.right = rc.left + gdi.scaleLength(450);
|
|
rc.top = gdi.getCY();
|
|
rc.bottom = rc.top + dx;
|
|
gdi.addRectangle(rc, colorDarkBlue, false, false);
|
|
gdi.dropLine();
|
|
}
|
|
|
|
|
|
void PrintResultMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|
settingsTitle(gdi, "Resultatutskrift / export");
|
|
wstring time=created ? L"10:00" : getTimeMS(interval);
|
|
startCancelInterval(gdi, "StartResult", created, IntervalMinute, time);
|
|
|
|
if (created) {
|
|
oe.getAllClasses(classesToPrint);
|
|
}
|
|
|
|
gdi.pushX();
|
|
gdi.fillRight();
|
|
gdi.addCheckbox("DoPrint", "Skriv ut", AutomaticCB, doPrint);
|
|
gdi.dropLine(-0.5);
|
|
gdi.addButton("PrinterSetup", "Skrivare...", AutomaticCB, "Välj skrivare...").setExtra(getId());
|
|
|
|
gdi.dropLine(4);
|
|
gdi.popX();
|
|
gdi.addCheckbox("DoExport", "Exportera", AutomaticCB, doExport);
|
|
gdi.dropLine(-1);
|
|
int cx = gdi.getCX();
|
|
gdi.addInput("ExportFile", exportFile, 32, 0, L"Fil att exportera till:");
|
|
gdi.dropLine(0.7);
|
|
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);
|
|
gdi.setCX(cx);
|
|
gdi.addInput("ExportScript", exportScript, 32, 0, L"Skript att köra efter export:");
|
|
gdi.dropLine(0.7);
|
|
gdi.addButton("BrowseScript", "Bläddra...", AutomaticCB);
|
|
gdi.dropLine(3);
|
|
gdi.popX();
|
|
|
|
gdi.setInputStatus("ExportFile", doExport);
|
|
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.fillDown();
|
|
gdi.addString("", 1, "Listval");
|
|
gdi.dropLine();
|
|
gdi.fillRight();
|
|
gdi.addListBox("Classes", 150,300,0, L"", L"", true);
|
|
gdi.pushX();
|
|
gdi.fillDown();
|
|
vector< pair<wstring, size_t> > d;
|
|
gdi.addItem("Classes", oe.fillClasses(d, oEvent::extraNone, oEvent::filterNone));
|
|
gdi.setSelection("Classes", classesToPrint);
|
|
|
|
gdi.addSelection("ListType", 200, 100, 0, L"Lista");
|
|
oe.fillListTypes(gdi, "ListType", 1);
|
|
if (notShown) {
|
|
notShown = false;
|
|
ClassConfigInfo cnf;
|
|
oe.getClassConfigurationInfo(cnf);
|
|
int type = EStdResultListLARGE;
|
|
if (cnf.hasRelay())
|
|
type = EStdTeamAllLegLARGE;
|
|
else if (cnf.hasPatrol())
|
|
type = EStdPatrolResultListLARGE;
|
|
|
|
gdi.selectItemByData("ListType", type);
|
|
}
|
|
else
|
|
gdi.selectItemByData("ListType", listInfo.getListCode());
|
|
|
|
gdi.addSelection("LegNumber", 140, 300, 0, L"Sträcka:");
|
|
set<int> clsUnused;
|
|
vector< pair<wstring, size_t> > out;
|
|
oe.fillLegNumbers(clsUnused, listInfo.isTeamList(), true, out);
|
|
gdi.addItem("LegNumber", out);
|
|
gdi.selectItemByData("LegNumber", listInfo.getLegNumberCoded());
|
|
|
|
gdi.addCheckbox("PageBreak", "Sidbrytning mellan klasser", 0, pageBreak);
|
|
gdi.addCheckbox("ShowInterResults", "Visa mellantider", 0, showInterResult,
|
|
"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);
|
|
|
|
gdi.popX();
|
|
gdi.addButton("SelectAll", "Välj allt", AutomaticCB, "").setExtra(L"Classes");
|
|
gdi.popX();
|
|
gdi.addButton("SelectNone", "Välj inget", AutomaticCB, "").setExtra(L"Classes");
|
|
}
|
|
else {
|
|
gdi.fillDown();
|
|
gdi.addString("", 1, L"Lista av typ 'X'#" + listInfo.getName());
|
|
gdi.addCheckbox("OnlyChanged", "Skriv endast ut ändade sidor", 0, po.onlyChanged);
|
|
}
|
|
}
|
|
|
|
void PrintResultMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|
{
|
|
if (lock)
|
|
return;
|
|
|
|
if (ast!=SyncDataUp) {
|
|
wstring printError;
|
|
lock = true;
|
|
try {
|
|
gdioutput gdiPrint("print", gdi.getScale());
|
|
gdiPrint.clearPage(false);
|
|
oe->generateList(gdiPrint, true, listInfo, false);
|
|
if (doPrint) {
|
|
gdiPrint.refresh();
|
|
try {
|
|
gdiPrint.print(po, oe);
|
|
}
|
|
catch (const meosException &ex) {
|
|
printError = ex.wwhat();
|
|
if (printError.empty())
|
|
printError = L"Printing failed (X: Y) Z#Auto#0#Unknown";
|
|
}
|
|
}
|
|
if (doExport) {
|
|
if (!exportFile.empty()) {
|
|
if (structuredExport)
|
|
gdiPrint.writeTableHTML(exportFile, oe->getName(), htmlRefresh);
|
|
else
|
|
gdiPrint.writeHTML(exportFile, oe->getName(), htmlRefresh);
|
|
|
|
if (!exportScript.empty()) {
|
|
ShellExecute(NULL, NULL, exportScript.c_str(), exportFile.c_str(), NULL, SW_HIDE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (...) {
|
|
lock = false;
|
|
throw;
|
|
}
|
|
lock = false;
|
|
|
|
if (!printError.empty() && !errorLock) {
|
|
errorLock = true;
|
|
gdi.alert(printError);
|
|
errorLock = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PrintResultMachine::status(gdioutput &gdi)
|
|
{
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
gdi.addString("", 0, name);
|
|
gdi.addString("", 0, listInfo.getName());
|
|
gdi.dropLine();
|
|
if (doExport) {
|
|
gdi.popX();
|
|
gdi.addString("", 0, "Målfil: ");
|
|
gdi.addStringUT(0, exportFile).setColor(colorRed);
|
|
gdi.dropLine();
|
|
}
|
|
gdi.fillRight();
|
|
gdi.popX();
|
|
if (interval>0){
|
|
gdi.addString("", 0, "Automatisk utskrift / export: ");
|
|
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount()-timeout)/1000);
|
|
}
|
|
else {
|
|
|
|
}
|
|
gdi.popX();
|
|
gdi.dropLine(2);
|
|
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
gdi.addButton("PrintNow", "Exportera nu", AutomaticCB).setExtra(getId());
|
|
gdi.fillDown();
|
|
gdi.addButton("Result", "Inställningar...", AutomaticCB).setExtra(getId());
|
|
gdi.popX();
|
|
}
|
|
|
|
void PrewarningMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|
settingsTitle(gdi, "Förvarningsröst");
|
|
startCancelInterval(gdi, "StartPrewarning", created, IntervalNone, L"");
|
|
|
|
gdi.addString("", 10, "help:computer_voice");
|
|
|
|
gdi.pushX();
|
|
gdi.fillRight();
|
|
gdi.addInput("WaveFolder", waveFolder, 32, 0, L"Ljudfiler, baskatalog.");
|
|
|
|
gdi.fillDown();
|
|
gdi.dropLine();
|
|
gdi.addButton("WaveBrowse", "Bläddra...", AutomaticCB);
|
|
gdi.popX();
|
|
|
|
gdi.addListBox("Controls", 100, 200, 0, L"", L"", true);
|
|
gdi.pushX();
|
|
gdi.fillDown();
|
|
vector< pair<wstring, size_t> > d;
|
|
oe.fillControls(d, oEvent::CTCourseControl);
|
|
gdi.addItem("Controls", d);
|
|
gdi.setSelection("Controls", controls);
|
|
gdi.popX();
|
|
gdi.addButton("SelectAll", "Välj alla", AutomaticCB, "").setExtra(L"Controls");
|
|
gdi.popX();
|
|
}
|
|
|
|
void PrewarningMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|
{
|
|
oe->playPrewarningSounds(waveFolder, controlsSI);
|
|
}
|
|
|
|
void PrewarningMachine::status(gdioutput &gdi)
|
|
{
|
|
gdi.addString("", 1, name);
|
|
|
|
string info="Förvarning på (SI-kod): ";
|
|
bool first=true;
|
|
|
|
if (controls.empty())
|
|
info+="alla stämplingar";
|
|
else {
|
|
for (set<int>::iterator it=controlsSI.begin();it!=controlsSI.end();++it) {
|
|
char bf[32];
|
|
_itoa_s(*it, bf, 10);
|
|
|
|
if (!first) info+=", ";
|
|
else first=false;
|
|
|
|
info+=bf;
|
|
}
|
|
}
|
|
gdi.addString("", 0, info);
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
|
|
gdi.popX();
|
|
gdi.dropLine(0.3);
|
|
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
gdi.addButton("TestVoice", "Testa rösten", AutomaticCB).setExtra(getId());
|
|
gdi.fillDown();
|
|
gdi.addButton("Prewarning", "Inställningar...", AutomaticCB).setExtra(getId());
|
|
gdi.popX();
|
|
}
|
|
|
|
void PunchMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|
settingsTitle(gdi, "Test av stämplingsinläsningar");
|
|
wstring time=created ? L"10" : itow(interval);
|
|
startCancelInterval(gdi, "StartPunch", created, IntervalSecond, time);
|
|
|
|
gdi.addString("", 10, "help:simulate");
|
|
|
|
gdi.pushX();
|
|
gdi.fillRight();
|
|
gdi.dropLine();
|
|
|
|
gdi.addString("", 0, "Radiotider, kontroll:");
|
|
gdi.dropLine(-0.2);
|
|
gdi.addInput("Radio", L"", 6, 0);
|
|
|
|
gdi.fillDown();
|
|
gdi.popX();
|
|
gdi.dropLine(5);
|
|
gdi.addString("", 1, "Generera testtävling");
|
|
gdi.fillRight();
|
|
gdi.addInput("nRunner", L"100", 10, 0, L"Antal löpare");
|
|
gdi.addInput("nClass", L"10", 10, 0, L"Antal klasser");
|
|
gdi.dropLine();
|
|
gdi.addCheckbox("UseRelay", "Med stafettklasser");
|
|
gdi.addButton("GenerateCMP", "Generera testtävling", AutomaticCB);
|
|
}
|
|
|
|
void PunchMachine::status(gdioutput &gdi)
|
|
{
|
|
gdi.addString("", 1, name);
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
if (interval>0){
|
|
gdi.addString("", 0, "Stämplar om: ");
|
|
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign|timeSeconds, (GetTickCount()-timeout)/1000);
|
|
gdi.addString("", 0, "(sekunder)");
|
|
}
|
|
else {
|
|
|
|
}
|
|
gdi.popX();
|
|
gdi.dropLine(2);
|
|
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
gdi.fillDown();
|
|
gdi.addButton("Punches", "Inställningar...", AutomaticCB).setExtra(getId());
|
|
gdi.popX();
|
|
}
|
|
|
|
void PunchMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|
{
|
|
#ifndef MEOSDB
|
|
SICard sic(ConvertedTimeStatus::Hour24);
|
|
SportIdent &si = TabSI::getSI(gdi);
|
|
|
|
if (radio == 0) {
|
|
oe->generateTestCard(sic);
|
|
if (!sic.empty()) {
|
|
if (!radio) si.addCard(sic);
|
|
}
|
|
else gdi.addInfoBox("", L"Failed to generate card.", interval * 2);
|
|
}
|
|
else {
|
|
SICard sic(ConvertedTimeStatus::Hour24);
|
|
vector<pRunner> rr;
|
|
oe->getRunners(0, 0, rr);
|
|
vector<pRunner> cCand;
|
|
vector<pFreePunch> pp;
|
|
for (auto r : rr) {
|
|
if (r->getStatus() == StatusUnknown && r->startTimeAvailable()) {
|
|
auto pc = r->getCourse(false);
|
|
if (radio < 10 || pc->hasControlCode(radio)) {
|
|
pp.clear();
|
|
oe->getPunchesForRunner(r->getId(), pp);
|
|
bool hit = false;
|
|
for (auto p : pp) {
|
|
if (p->getTypeCode() == radio)
|
|
hit = true;
|
|
}
|
|
if (!hit)
|
|
cCand.push_back(r);
|
|
}
|
|
}
|
|
}
|
|
if (cCand.size() > 0) {
|
|
int ix = rand() % cCand.size();
|
|
pRunner r = cCand[ix];
|
|
sic.convertedTime = ConvertedTimeStatus::Done;
|
|
sic.CardNumber = r->getCardNo();
|
|
sic.punchOnly = true;
|
|
sic.nPunch = 1;
|
|
sic.Punch[0].Code = radio;
|
|
sic.Punch[0].Time = 600 + rand() % 1200 + r->getStartTime();
|
|
si.addCard(sic);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SplitsMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|
wstring time;
|
|
if (interval>0)
|
|
time = itow(interval);
|
|
else if (created)
|
|
time = L"30";
|
|
|
|
settingsTitle(gdi, "Sträcktider / WinSplits");
|
|
startCancelInterval(gdi, "StartSplits", created, IntervalSecond, time);
|
|
|
|
gdi.addString("", 0, "Intervall (sekunder). Lämna blankt för att uppdatera när "
|
|
"tävlingsdata ändras.");
|
|
gdi.dropLine();
|
|
|
|
gdi.addString("", 10, "help:winsplits_auto");
|
|
|
|
|
|
gdi.dropLine();
|
|
gdi.fillRight();
|
|
gdi.addInput("FileName", file, 30, 0, L"Filnamn:");
|
|
gdi.dropLine(0.9);
|
|
gdi.addButton("BrowseSplits", "Bläddra...", AutomaticCB);
|
|
|
|
gdi.popX();
|
|
gdi.dropLine(2);
|
|
|
|
}
|
|
|
|
void SplitsMachine::status(gdioutput &gdi)
|
|
{
|
|
gdi.addString("", 1, name);
|
|
if (!file.empty()) {
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
gdi.addString("", 0, L"Fil: X#" + file);
|
|
|
|
if (interval>0){
|
|
gdi.popX();
|
|
gdi.dropLine(1);
|
|
gdi.addString("", 0, "Skriver sträcktider om: ");
|
|
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign|timeSeconds, (GetTickCount()-timeout)/1000);
|
|
gdi.addString("", 0, "(sekunder)");
|
|
}
|
|
else {
|
|
gdi.dropLine(1);
|
|
gdi.addString("", 0, "Skriver sträcktider när tävlingsdata ändras.");
|
|
}
|
|
|
|
gdi.popX();
|
|
}
|
|
gdi.dropLine(2);
|
|
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
gdi.fillDown();
|
|
gdi.addButton("Splits", "Inställningar...", AutomaticCB).setExtra(getId());
|
|
gdi.popX();
|
|
}
|
|
|
|
void SplitsMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast)
|
|
{
|
|
if ((interval>0 && ast==SyncTimer) || (interval==0 && ast==SyncDataUp)) {
|
|
if (!file.empty())
|
|
oe->exportIOFSplits(oEvent::IOF20, file.c_str(), true, false, classes,
|
|
leg, false, true, true, false);
|
|
}
|
|
}
|
|
|
|
void SaveMachine::status(gdioutput &gdi) {
|
|
gdi.addString("", 1, name);
|
|
if (!baseFile.empty()) {
|
|
gdi.fillRight();
|
|
gdi.pushX();
|
|
gdi.addString("", 0, L"Destination: X#" + baseFile);
|
|
|
|
if (interval>0){
|
|
gdi.popX();
|
|
gdi.dropLine(1);
|
|
gdi.addString("", 0, "Säkerhetskopierar om: ");
|
|
gdi.addTimer(gdi.getCY(), gdi.getCX(), timerIgnoreSign, (GetTickCount()-timeout)/1000);
|
|
}
|
|
|
|
gdi.popX();
|
|
}
|
|
gdi.dropLine(2);
|
|
gdi.addButton("Stop", "Stoppa automaten", AutomaticCB).setExtra(getId());
|
|
gdi.fillDown();
|
|
gdi.addButton("SaveBackup", "Inställningar...", AutomaticCB).setExtra(getId());
|
|
gdi.popX();
|
|
}
|
|
|
|
void SaveMachine::process(gdioutput &gdi, oEvent *oe, AutoSyncType ast) {
|
|
if (interval>0 && ast==SyncTimer) {
|
|
if (!baseFile.empty()) {
|
|
wstring file = baseFile + L"meos_backup_" + oe->getDate() + L"_" + itow(saveIter++) + L".xml";
|
|
oe->autoSynchronizeLists(true);
|
|
oe->save(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SaveMachine::settings(gdioutput &gdi, oEvent &oe, bool created) {
|
|
settingsTitle(gdi, "Säkerhetskopiering");
|
|
wstring time=created ? L"10:00" : getTimeMS(interval);
|
|
startCancelInterval(gdi, "StartBackup", created, IntervalMinute, time);
|
|
|
|
int cx = gdi.getCX();
|
|
gdi.addInput("BaseFile", baseFile, 32, 0, L"Mapp:");
|
|
gdi.dropLine(0.7);
|
|
gdi.addButton("BrowseFolder", "Bläddra...", AutomaticCB).setExtra(L"BaseFile");
|
|
gdi.setCX(cx);
|
|
}
|
|
|
|
void SaveMachine::saveSettings(gdioutput &gdi) {
|
|
|
|
wstring minute=gdi.getText("Interval");
|
|
int t=convertAbsoluteTimeMS(minute);
|
|
|
|
if (t<2 || t>7200) {
|
|
throw meosException("Intervallet måste anges på formen MM:SS.");
|
|
}
|
|
wstring f = gdi.getText("BaseFile");
|
|
if (f.empty()) {
|
|
throw meosException("Filnamnet får inte vara tomt");
|
|
}
|
|
|
|
if (*f.rbegin() != '\\' && *f.rbegin() != '/')
|
|
f += L"\\";
|
|
|
|
wstring sample = f + L"sample.txt";
|
|
ofstream fout(sample.c_str(), ios_base::trunc|ios_base::out);
|
|
bool bad = false;
|
|
if (fout.bad())
|
|
bad = true;
|
|
else {
|
|
fout << "foo" << endl;
|
|
fout.close();
|
|
bad = fout.bad();
|
|
_wremove(sample.c_str());
|
|
}
|
|
if (bad)
|
|
throw meosException(L"Ogiltig destination X#" + f);
|
|
|
|
baseFile = f;
|
|
interval = t;
|
|
}
|
|
|
|
void TabAuto::clearCompetitionData() {
|
|
}
|