/************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2017 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 . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "stdafx.h" #include #include "methodeditor.h" #include "generalresult.h" #include "gdioutput.h" #include "meosexception.h" #include "gdistructures.h" #include "meos_util.h" #include "localizer.h" #include "gdifonts.h" #include "oEvent.h" #include "tabbase.h" #include "CommDlg.h" #include "random.h" #include "metalist.h" MethodEditor::MethodEditor(oEvent *oe_) { oe = oe_; inputNumber = 0; currentResult = 0; currentIndex = -1; dirtyInt = false; wasLoadedBuiltIn = false; } MethodEditor::~MethodEditor() { setCurrentResult(0, L""); } void MethodEditor::setCurrentResult(DynamicResult *lst, const wstring &fileSrc) { delete currentResult; currentResult = lst; fileNameSource = fileSrc; } int methodCB(gdioutput *gdi, int type, void *data) { void *clz = gdi->getData("MethodEditorClz"); MethodEditor *le = (MethodEditor *)clz; BaseInfo *bi = (BaseInfo *)data; if (le) return le->methodCb(*gdi, type, *bi); throw meosException("Unexpected error"); } void MethodEditor::show(gdioutput &gdi) { oe->loadGeneralResults(true); gdi.setRestorePoint("BeginMethodEdit"); gdi.pushX(); gdi.setCX(gdi.getCX() + gdi.scaleLength(6)); if (currentResult) gdi.addString("", boldLarge, makeDash(L"Result Module - X#") + currentResult->getName(true)); else gdi.addString("", boldLarge, "Edit Result Modules"); gdi.setOnClearCb(methodCB); gdi.setData("MethodEditorClz", this); gdi.dropLine(0.5); gdi.fillRight(); gdi.addButton("OpenFile", "Importera från fil", methodCB); gdi.addButton("OpenInside", "Öppna", methodCB); if (currentResult) { gdi.addButton("SaveFile", "Exportera till fil...", methodCB); gdi.addButton("SaveInside", "Spara", methodCB); gdi.addButton("Remove", "Ta bort", methodCB); makeDirty(gdi, NoTouch); } gdi.addButton("NewRules", "New Result Module", methodCB); gdi.addButton("Close", "Stäng", methodCB); #ifdef _DEBUG gdi.addButton("WriteDoc", "#WriteDoc", methodCB); #endif gdi.popX(); gdi.dropLine(2); gdi.fillDown(); if (currentResult) { gdi.dropLine(0.5); if (currentResult->getTag().empty()) currentResult->setTag(uniqueTag("result")); gdi.addInput("Name", currentResult->getName(false), 20, methodCB, L"Name of result module:"); string tag = currentResult->getTag(); vector listIx; oe->getListContainer().getListsByResultModule(tag, listIx); string udtag = DynamicResult::undecorateTag(tag); gdi.addInput("Tag", gdi.widen(udtag), 20, methodCB, L"Result module identifier:"); if (!listIx.empty()) { gdi.disableInput("Tag"); gdi.getBaseInfo("Tag").setExtra(1); wstring lists = oe->getListContainer().getList(listIx.front()).getListName(); if (listIx.size() > 1) lists += L", ..."; gdi.addString("", 0, L"Resultatmodulen används i X.#" + lists); } wstring desc = currentResult->getDescription(); if (wasLoadedBuiltIn) desc = lang.tl(desc); gdi.addInputBox("Desc", 300, 70, desc, methodCB, L"Description:"); gdi.dropLine(); gdi.fillRight(); gdi.addSelection("Method", 200, 200, methodCB, L"Edit rule for:"); vector< pair > mt; currentResult->getMethodTypes(mt); for (size_t k = 0; k < mt.size(); k++) gdi.addItem("Method", lang.tl(mt[k].second), mt[k].first); gdi.dropLine(); gdi.addButton("SaveSource", "Save changes", methodCB); gdi.addButton("CancelSource", "Cancel", methodCB); gdi.addButton("TestRule", "Test Result Module", methodCB); gdi.disableInput("SaveSource"); gdi.disableInput("CancelSource"); gdi.dropLine(2); gdi.popX(); gdi.fillDown(); gdi.setRestorePoint("TestRule"); } gdi.refresh(); } bool MethodEditor::checkTag(const string &tag, bool throwError) const { vector< pair > > tagNameList; oe->getGeneralResults(false, tagNameList, false); for (size_t k = 0; k < tag.length(); k++) { char c = tag[k]; if (c == '-' || c == '_' || c == '%') continue; if (!isalnum(c)) { if (throwError) throw meosException("Invalid character in tag X.#" + tag); else return false; } } if (tag.empty()) { if (throwError) throw meosException("Empty tag is invalid"); else return false; } for (size_t k = 0; k < tagNameList.size(); k++) { if (_strcmpi(tagNameList[k].second.first.c_str(), tag.c_str()) == 0) { if (throwError) throw meosException("The tag X is in use.#" + tag); else return false; } } return true; } string MethodEditor::uniqueTag(const string &tag) const { vector< pair > > tagNameList; oe->getGeneralResults(false, tagNameList, false); set tags; for (size_t k = 0; k < tagNameList.size(); k++) tags.insert(tagNameList[k].second.first); int a = GetRandomNumber(65536); srand(GetTickCount()); int b = rand() % 65536; char un[64]; sprintf_s(un, "-%04X-%04X-", a, b); int iter = 0; while (tags.count(tag + un + itos(++iter))); return tag + un + itos(iter); } int MethodEditor::methodCb(gdioutput &gdi, int type, BaseInfo &data) { if (type == GUI_BUTTON) { ButtonInfo bi = dynamic_cast(data); if (bi.id == "Cancel") { gdi.restore("EditList"); gdi.enableInput("EditList"); } else if (bi.id == "CloseWindow") { gdi.closeWindow(); } else if (bi.id == "WriteDoc") { ofstream fout("methoddoc.txt"); DynamicResult dr; dr.declareSymbols(DynamicResult::MRScore, true); vector< pair > symbs; dr.getSymbols(symbs); fout << "#head{" << gdi.toUTF8(lang.tl("Deltagare")) << "}\n#table{2}" << endl; for (size_t k = 0; k < symbs.size(); k++) { wstring name, desc; dr.getSymbolInfo(symbs[k].second, name, desc); fout << "{#mono{" << gdi.toUTF8(name) << "}}{" << gdi.toUTF8(lang.tl(desc)) << "}" << endl; } dr.declareSymbols(DynamicResult::MTScore, true); dr.getSymbols(symbs); fout << "#head{" << gdi.toUTF8(lang.tl("Lag")) << "}\n#table{2}" << endl; for (size_t k = 0; k < symbs.size(); k++) { wstring name, desc; dr.getSymbolInfo(symbs[k].second, name, desc); fout << "{#mono{" << gdi.toUTF8(name) << "}}{" << gdi.toUTF8(lang.tl(desc)) << "}" << endl; } } else if (bi.id == "NewRules") { if (!checkSave(gdi)) return 0; gdi.clearPage(false); gdi.setData("MethodEditorClz", this); gdi.addString("", boldLarge, "New Set of Result Rules"); setCurrentResult(new DynamicResult(), L""); wasLoadedBuiltIn = false; currentResult->setName(lang.tl("Result Calculation")); currentIndex = -1; makeDirty(gdi, ClearDirty); show(gdi); gdi.setInputStatus("Remove", resultIsInstalled()); } else if (bi.id == "SaveFile") { if (!currentResult) return 0; checkChangedSave(gdi); wstring fileName; int ix = 0; vector< pair > ext; ext.push_back(make_pair(L"xml-data", L"*.rules")); fileName = gdi.browseForSave(ext, L"rules", ix); if (fileName.empty()) return 0; saveSettings(gdi); wstring path = fileNameSource.empty() ? getInternalPath(currentResult->getTag()) : fileNameSource; currentResult->save(path); fileNameSource = path; oe->loadGeneralResults(true); makeDirty(gdi, ClearDirty); currentResult->save(fileName); //savedFileName = fileName; return 1; } else if (bi.id == "SaveInside") { if (!currentResult) return 0; saveSettings(gdi); checkChangedSave(gdi); wstring path = fileNameSource.empty() ? getInternalPath(currentResult->getTag()) : fileNameSource; currentResult->save(path); fileNameSource = path; int nl = oe->getListContainer().getNumLists(); string utag = DynamicResult::undecorateTag(currentResult->getTag()); bool doUpdate = false; for (int j = 0; j < nl && !doUpdate; j++) { if (!oe->getListContainer().isExternal(j)) continue; const string &mtag = oe->getListContainer().getList(j).getResultModule(); if (mtag.empty() || currentResult->getTag() == mtag) continue; if (utag == DynamicResult::undecorateTag(mtag)) { doUpdate = gdi.ask(L"Vill du uppdatera resultatlistorna i den öppande tävlingen?"); break; } } oe->synchronize(false); oe->getListContainer().updateResultModule(*currentResult, doUpdate); oe->loadGeneralResults(true); oe->synchronize(true); makeDirty(gdi, ClearDirty); gdi.setInputStatus("Remove", resultIsInstalled()); return 1; } else if (bi.id == "Remove") { if (!currentResult) return 0; if (gdi.ask(L"Vill du ta bort 'X'?#" + currentResult->getName(true))) { wstring path = fileNameSource;//getInternalPath(currentResult->getTag()); wstring rm = path + L".removed"; DeleteFile(rm.c_str()); _wrename(path.c_str(), rm.c_str()); oe->loadGeneralResults(true); makeDirty(gdi, ClearDirty); setCurrentResult(0, L""); gdi.clearPage(false); show(gdi); } return 1; } else if (bi.id == "OpenFile") { if (!checkSave(gdi)) return 0; vector< pair > ext; ext.push_back(make_pair(L"xml-data", L"*.rules")); wstring fileName = gdi.browseForOpen(ext, L"rules"); if (fileName.empty()) return 0; DynamicResult *tmp = new DynamicResult(); try { tmp->load(fileName); } catch(...) { delete tmp; throw; } wasLoadedBuiltIn = false; setCurrentResult(tmp, L""); currentIndex = -1; gdi.clearPage(false); //savedFileName = fileName; makeDirty(gdi, ClearDirty); show(gdi); } else if (bi.id == "OpenInside") { if (!checkSave(gdi)) return 0; gdi.clearPage(true); gdi.setOnClearCb(methodCB); gdi.setData("MethodEditorClz", this); gdi.pushX(); vector< pair > lists; //oe->getListContainer().getLists(lists); vector< pair > > tagNameList; oe->getGeneralResults(true, tagNameList, true); for (size_t k = 0; k < tagNameList.size(); k++) { string tag = tagNameList[k].second.first; string utag = DynamicResult::undecorateTag(tag); vector listIx; oe->getListContainer().getListsByResultModule(tag, listIx); wstring n = tagNameList[k].second.second + L" (" + gdi.widen(utag) + L")"; if (listIx.size() > 0) { n += L" *"; } lists.push_back(make_pair(n, tagNameList[k].first)); } sort(lists.begin(), lists.end()); gdi.fillRight(); gdi.addSelection("OpenList", 350, 400, methodCB, L"Choose result module:", L"Rader markerade med (*) kommer från en lista i tävlingen."); gdi.addItem("OpenList", lists); gdi.autoGrow("OpenList"); gdi.selectFirstItem("OpenList"); gdi.dropLine(); gdi.addButton("DoOpen", "Öppna", methodCB); gdi.addButton("DoOpenCopy", "Open a Copy", methodCB); if (!lists.empty()) { wstring srcFile; bool ro = dynamic_cast(oe->getGeneralResult(tagNameList.front().second.first, srcFile)).isReadOnly(); gdi.setInputStatus("DoOpen", !ro); } else { gdi.disableInput("DoOpen"); gdi.disableInput("DoOpenCopy"); } gdi.addButton("CancelReload", "Avbryt", methodCB); gdi.dropLine(4); gdi.popX(); } else if (bi.id == "DoOpen" || bi.id == "DoOpenCopy") { ListBoxInfo lbi; DynamicResult *dr = 0; if (gdi.getSelectedItem("OpenList", lbi)) { vector< pair > > tagNameList; oe->getGeneralResults(true, tagNameList, false); size_t ix = -1; for (size_t k = 0; k < tagNameList.size(); k++) { if (tagNameList[k].first == lbi.data) { ix = k; break; } } if (ix < tagNameList.size()) { wstring srcFile; DynamicResult &drIn = dynamic_cast(oe->getGeneralResult(tagNameList[ix].second.first, srcFile)); wasLoadedBuiltIn = drIn.isReadOnly(); dr = new DynamicResult(drIn); if (bi.id == "DoOpenCopy") { dr->setTag(uniqueTag("result")); dr->setName(lang.tl("Copy of ") + dr->getName(false)); setCurrentResult(dr, L""); } else setCurrentResult(dr, srcFile); } if (bi.id == "DoOpen") makeDirty(gdi, ClearDirty); else makeDirty(gdi, MakeDirty); gdi.clearPage(false); show(gdi); if (dr) dr->compile(true); } } else if (bi.id == "CancelReload") { gdi.clearPage(false); show(gdi); } else if (bi.id == "Close") { if (!checkSave(gdi)) return 0; setCurrentResult(0, L""); makeDirty(gdi, ClearDirty); currentIndex = -1; gdi.getTabs().get(TListTab)->loadPage(gdi); return 0; } else if (bi.id == "SaveSource") { DynamicResult::DynamicMethods dm = DynamicResult::DynamicMethods(bi.getExtraInt()); string src = gdi.narrow(gdi.getText("Source")); currentResult->setMethodSource(dm, src); gdi.setText("Source", gdi.widen(src)); } else if (bi.id == "CancelSource") { checkChangedSave(gdi); gdi.restore("NoSourceEdit", true); gdi.selectItemByData("Method", -1); gdi.disableInput("SaveSource"); gdi.disableInput("CancelSource"); } else if (bi.id == "TestRule") { checkChangedSave(gdi); gdi.restore("TestRule", false); gdi.setRestorePoint("TestRule"); gdi.disableInput("SaveSource"); gdi.disableInput("CancelSource"); gdi.selectItemByData("Method", -1); int y = gdi.getCY(); vector r; vector t; oe->getRunners(0, 0, r, true); oe->getTeams(0, t, true); vector rr; vector tr; for (size_t k = 0; k < r.size(); k++) { if (r[k]->getStatus() != StatusUnknown) rr.push_back(r[k]); } for (size_t k = 0; k < t.size(); k++) { if (t[k]->getStatus() != StatusUnknown) tr.push_back(t[k]); else { for (int j = 0; j < t[k]->getNumRunners(); j++) { if (t[k]->getRunner(j) && t[k]->getRunner(j)->getStatus() != StatusUnknown) { tr.push_back(t[k]); break; } } } } gdi.fillDown(); if (tr.size() + rr.size() == 0) { gdi.addString("", 1, "Tävlingen innehåller inga resultat").setColor(colorRed); } else gdi.addString("", 1, "Applying rules to the current competition"); gdi.dropLine(0.5); int xp = gdi.getCX(); int yp = gdi.getCY(); int diff = gdi.scaleLength(3); const int w[5] = {200, 70, 70, 70, 85}; set errors; currentResult->prepareCalculations(*oe, tr.size()>0, inputNumber); for (size_t k = 0; k < rr.size(); k++) { int txp = xp; int wi = 0; gdi.addStringUT(yp, txp, 0, rr[k]->getCompleteIdentification(), w[wi]-diff); txp += w[wi++]; currentResult->prepareCalculations(*rr[k]); int rt = 0, pt = 0; RunnerStatus st = StatusUnknown; { wstring err; wstring str; try { st = currentResult->deduceStatus(*rr[k]); str = oe->formatStatus(st); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); RECT rc = ti.textRect; gdi.addToolTip("", err, 0, &rc); } txp += w[wi++]; } { wstring err; wstring str; try { rt = currentResult->deduceTime(*rr[k], rr[k]->getStartTime()); str = formatTime(rt); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } { wstring err; wstring str; try { pt = currentResult->deducePoints(*rr[k]); str = itow(pt); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } { wstring err; wstring str; try { int score = currentResult->score(*rr[k], st, rt, pt, false); str = itow(score); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } rr[k]->setTempResultZero(oAbstractRunner::TempResult(st, rr[k]->getStartTime(), rt, pt)); gdi.addString("Debug", yp, txp, 0, "Debug...", 0, methodCB).setColor(colorGreen).setExtra(rr[k]->getId()); yp += gdi.getLineHeight(); } yp += gdi.getLineHeight(); if (tr.size() > 0) { gdi.addString("", yp, xp, 1, "Lag"); yp += gdi.getLineHeight(); } else { } for (size_t k = 0; k < tr.size(); k++) { int txp = xp; int wi = 0; gdi.addStringUT(yp, txp, 0, tr[k]->getName(), w[wi]-diff); txp += w[wi++]; currentResult->prepareCalculations(*tr[k]); int rt = 0, pt = 0; RunnerStatus st = StatusUnknown; { wstring err; wstring str; try { st = currentResult->deduceStatus(*tr[k]); str = oe->formatStatus(st); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } { wstring err; wstring str; try { rt = currentResult->deduceTime(*tr[k]); str = formatTime(rt); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } { wstring err; wstring str; try { pt = currentResult->deducePoints(*tr[k]); str = itow(pt); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } { wstring err; wstring str; try { int score = currentResult->score(*tr[k], st, rt, pt); str = itow(score); } catch (meosException &ex) { err = ex.wwhat(); errors.insert(ex.wwhat()); str = L"Error"; } TextInfo &ti = gdi.addStringUT(yp, txp, 0, str, w[wi]-diff); if (!err.empty()) { ti.setColor(colorRed); gdi.addToolTip("", err, 0, &ti.textRect); } txp += w[wi++]; } gdi.addString("Debug", yp, txp, 0, "Debug...", 0, methodCB).setColor(colorGreen).setExtra(-tr[k]->getId()); yp += gdi.getLineHeight(); } gdi.scrollTo(0, y); gdi.refresh(); } } else if (type == GUI_LISTBOX) { ListBoxInfo &lbi = dynamic_cast(data); if (lbi.id == "Method") { checkChangedSave(gdi); DynamicResult::DynamicMethods m = DynamicResult::DynamicMethods(lbi.data); const string &src = currentResult->getMethodSource(m); gdi.enableInput("SaveSource"); gdi.enableInput("CancelSource"); gdi.getBaseInfo("SaveSource").setExtra(lbi.data); if (!gdi.hasField("Source")) { gdi.fillRight(); gdi.restore("TestRule", false); gdi.pushX(); gdi.setRestorePoint("NoSourceEdit"); gdi.addInputBox("Source", 450, 300, gdi.widen(src), methodCB, L"Source code:").setFont(gdi, monoText); gdi.fillDown(); gdi.setCX(gdi.getCX() + gdi.getLineHeight()); gdi.addListBox("Symbols", 450, 300-20, methodCB, L"Available symbols:"); gdi.setTabStops("Symbols", 180); gdi.addString("SymbInfo", gdi.getCY(), gdi.getCX(), 0, "", 350, 0); gdi.popX(); gdi.setCY(gdi.getHeight()); gdi.dropLine(); gdi.scrollToBottom(); } else { gdi.setText("Source", gdi.widen(src)); } currentResult->declareSymbols(m, true); vector< pair > symb; currentResult->getSymbols(symb); gdi.addItem("Symbols", symb); } else if (lbi.id == "Symbols") { wstring name, desc; currentResult->getSymbolInfo(lbi.data, name, desc); gdi.setText("SymbInfo", name + L":" + lang.tl(desc) + L".", true); } else if (lbi.id == "OpenList") { vector< pair > > tagNameList; oe->getGeneralResults(true, tagNameList, false); size_t ix = -1; for (size_t k = 0; k < tagNameList.size(); k++) { if (tagNameList[k].first == lbi.data) { ix = k; break; } } wstring srcFile; if (ix < tagNameList.size()) { bool ro = dynamic_cast(oe->getGeneralResult(tagNameList[ix].second.first, srcFile)).isReadOnly(); gdi.setInputStatus("DoOpen", !ro); } else gdi.setInputStatus("DoOpen", true); } } else if (type == GUI_LISTBOXSELECT) { ListBoxInfo &lbi = dynamic_cast(data); if (lbi.id == "Symbols") { wstring name, desc; currentResult->getSymbolInfo(lbi.data, name, desc); gdi.replaceSelection("Source", name); } } else if (type==GUI_CLEAR) { return checkSave(gdi); } else if (type == GUI_INPUT) { InputInfo &ii = dynamic_cast(data); if (ii.changed()) makeDirty(gdi, MakeDirty); } else if (type == GUI_LINK) { TextInfo &ti = dynamic_cast(data); if (ti.id == "Debug") { int id = ti.getExtraInt(); if (id > 0) { debug(gdi, id, false); } else if (id < 0) { debug(gdi, -id, true); } } } return 0; } void MethodEditor::saveSettings(gdioutput &gdi) { wstring name = gdi.getText("Name"); string tag; const bool updateTag = gdi.getBaseInfo("Tag").getExtraInt() == 0; if (updateTag) tag = gdi.narrow(gdi.getText("Tag")); else tag = currentResult->getTag(); wstring desc = gdi.getText("Desc"); if (_strcmpi(currentResult->getTag().c_str(), tag.c_str()) != 0) { checkTag(tag, true); wstring oldPath = fileNameSource.empty() ? getInternalPath(currentResult->getTag()) : fileNameSource; wstring path = getInternalPath(tag); _wrename(oldPath.c_str(), path.c_str()); fileNameSource = path; } currentResult->setTag(tag); currentResult->setName(name); currentResult->setDescription(desc); gdi.setText("Name", name); gdi.setText("Tag", gdi.widen(tag)); gdi.setText("Desc", desc); } void MethodEditor::checkUnsaved(gdioutput &gdi) { /*if (gdi.hasData("IsEditing")) { if (gdi.isInputChanged("")) { gdi.setData("NoRedraw", 1); gdi.sendCtrlMessage("Apply"); } } if (gdi.hasData("IsEditingList")) { if (gdi.isInputChanged("")) { gdi.setData("NoRedraw", 1); gdi.sendCtrlMessage("ApplyListProp"); } }*/ } void MethodEditor::makeDirty(gdioutput &gdi, DirtyFlag inside) { if (inside == MakeDirty) dirtyInt = true; else if (inside == ClearDirty) dirtyInt = false; if (gdi.hasField("SaveInside")) { gdi.setInputStatus("SaveInside", dirtyInt); gdi.setInputStatus("Remove", resultIsInstalled()); } } bool MethodEditor::checkSave(gdioutput &gdi) { if (dirtyInt) { gdioutput::AskAnswer answer = gdi.askCancel(L"Vill du spara ändringar?"); if (answer == gdioutput::AnswerCancel) return false; if (answer == gdioutput::AnswerYes) { gdi.sendCtrlMessage("SaveInside"); } makeDirty(gdi, ClearDirty); } return true; } void MethodEditor::checkChangedSave(gdioutput &gdi) { if (gdi.hasField("Source")) { gdi.getText("Source"); if (dynamic_cast(gdi.getBaseInfo("Source")).changed() && gdi.ask(L"Save changes in rule code?")) { DynamicResult::DynamicMethods dm = DynamicResult::DynamicMethods(gdi.getExtraInt("SaveSource")); string src = gdi.narrow(gdi.getText("Source")); currentResult->setMethodSource(dm, src); gdi.setText("Source", gdi.widen(src)); } } } extern gdioutput *gdi_main; wstring MethodEditor::getInternalPath(const string &tag) { string udTag = DynamicResult::undecorateTag(tag); wstring resFile; if (udTag == tag) resFile = gdi_main->widen(tag) + L".rules"; else resFile = L"imp_" + gdi_main->widen(udTag) + L".rules"; wchar_t path[260]; getUserFile(path, resFile.c_str()); return path; } bool MethodEditor::resultIsInstalled() const { if (!currentResult || fileNameSource.empty()) return false; string tag = currentResult->getTag(); vector listIx; oe->getListContainer().getListsByResultModule(tag, listIx); if (!listIx.empty()) return false; // Used in a list in this competition //string path = getInternalPath(currentResult->getTag()); return fileExist(fileNameSource.c_str()); } void MethodEditor::debug(gdioutput &gdi_in, int id, bool isTeam) { oAbstractRunner *art = 0; if (isTeam) art = oe->getTeam(id); else art = oe->getRunner(id, 0); if (!art || !currentResult) throw meosException("Internal error"); gdioutput *gdi_new = getExtraWindow("debug", true); wstring title = lang.tl(L"Debug X for Y#" + currentResult->getName(false) + L"#" + art->getName()); if (!gdi_new) gdi_new = createExtraWindow("debug", title, gdi_in.scaleLength(500) ); else gdi_new->setWindowTitle(title); gdi_new->clearPage(false); gdi_new->setData("MethodEditorClz", this); gdioutput &gdi = *gdi_new; currentResult->prepareCalculations(*oe, isTeam, inputNumber); gdi_new->addString("", fontMediumPlus, "Debug Output"); if (!isTeam) { oRunner &r = *pRunner(art); currentResult->prepareCalculations(r); int rt = 0, pt = 0; RunnerStatus st = StatusUnknown; gdi.dropLine(); try { st = currentResult->deduceStatus(r); currentResult->debugDumpVariables(gdi, true); gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st)).setColor(colorGreen); } catch (meosException &ex) { currentResult->debugDumpVariables(gdi, true); wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Status Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceRStatus)) currentResult->debugDumpVariables(gdi, false); try { rt = currentResult->deduceTime(r, r.getStartTime()); gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen); } catch (meosException &ex) { wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceRTime)) currentResult->debugDumpVariables(gdi, false); try { pt = currentResult->deducePoints(r); gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen); } catch (meosException &ex) { wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Points Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceRPoints)) currentResult->debugDumpVariables(gdi, true); try { int score = currentResult->score(r, st, rt, pt, false); gdi.addStringUT(1, "ComputedScore: " + itos(score)).setColor(colorGreen); } catch (meosException &ex) { currentResult->debugDumpVariables(gdi, true); wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Score Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MRScore)) currentResult->debugDumpVariables(gdi, false); } else { oTeam &t = *pTeam(art); currentResult->prepareCalculations(t); int rt = 0, pt = 0; RunnerStatus st = StatusUnknown; gdi.dropLine(); try { st = currentResult->deduceStatus(t); currentResult->debugDumpVariables(gdi, true); gdi.addStringUT(1, L"ComputedStatus: " + oe->formatStatus(st)).setColor(colorGreen); } catch (meosException &ex) { currentResult->debugDumpVariables(gdi, true); wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Status Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceTStatus)) currentResult->debugDumpVariables(gdi, false); try { rt = currentResult->deduceTime(t); gdi.addStringUT(1, L"ComputedTime: " + formatTime(rt)).setColor(colorGreen); } catch (meosException &ex) { wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Time Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceRTime)) currentResult->debugDumpVariables(gdi, false); try { pt = currentResult->deducePoints(t); gdi.addStringUT(1, "ComputedPoints: " + itos(pt)).setColor(colorGreen); } catch (meosException &ex) { wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Points Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MDeduceTPoints)) currentResult->debugDumpVariables(gdi, true); try { int score = currentResult->score(t, st, rt, pt); gdi.addStringUT(1, "ComputedScore:" + itos(score)).setColor(colorGreen); } catch (meosException &ex) { currentResult->debugDumpVariables(gdi, true); wstring err = lang.tl(ex.wwhat()); gdi.addString("", 0, L"Status Calculation Failed: X#" + err).setColor(colorRed); } if (currentResult->hasMethod(DynamicResult::MTScore)) currentResult->debugDumpVariables(gdi, false); } gdi.addButton("CloseWindow", "Stäng", methodCB); gdi.refresh(); }