MeOS version 3.6.1109
This commit is contained in:
parent
06a6c4ff67
commit
7a99f0a4cd
@ -900,6 +900,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
wstring firstStart = gdi.getText("FirstStart");
|
||||
wstring minInterval = gdi.getText("MinInterval");
|
||||
wstring vacances = gdi.getText("Vacances");
|
||||
setDefaultVacant(vacances);
|
||||
|
||||
clearPage(gdi, false);
|
||||
gdi.addString("", boldLarge, "Lotta flera klasser");
|
||||
@ -1044,13 +1045,14 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
gdi.addInput("FirstStart", oe->getAbsTime(3600), 10, 0, L"Första (ordinarie) start:");
|
||||
gdi.addInput("MinInterval", L"2:00", 10, 0, L"Minsta startintervall:");
|
||||
gdi.fillDown();
|
||||
gdi.addInput("Vacances", L"5%", 10, 0, L"Andel vakanser:");
|
||||
gdi.addInput("Vacances", getDefaultVacant(), 10, 0, L"Andel vakanser:");
|
||||
gdi.popX();
|
||||
|
||||
createDrawMethod(gdi);
|
||||
|
||||
gdi.fillDown();
|
||||
gdi.addCheckbox("LateBefore", "Efteranmälda före ordinarie");
|
||||
gdi.addCheckbox("AllowNeighbours", "Tillåt samma bana inom basintervall", 0, oe->getPropertyInt("DrawInterlace", 1) != 0);
|
||||
gdi.dropLine();
|
||||
|
||||
gdi.popX();
|
||||
@ -1180,8 +1182,11 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
return 0;
|
||||
wstring minInterval = gdi.getText("MinInterval");
|
||||
wstring vacances = gdi.getText("Vacances");
|
||||
bool lateBefore = false;
|
||||
//bool pairwise = gdi.isChecked("Pairwise");
|
||||
setDefaultVacant(vacances);
|
||||
bool lateBefore = gdi.isChecked("LateBefore");
|
||||
bool allowNeighbourSameCourse = gdi.isChecked("AllowNeighbours");
|
||||
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
|
||||
|
||||
int pairSize = 1;
|
||||
if (gdi.hasField("PairSize")) {
|
||||
pairSize = gdi.getSelectedItem("PairSize").first;
|
||||
@ -1201,7 +1206,7 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
clearPage(gdi, true);
|
||||
oe->automaticDrawAll(gdi, firstStart, minInterval, vacances,
|
||||
lateBefore, method, pairSize);
|
||||
lateBefore, allowNeighbourSameCourse, method, pairSize);
|
||||
oe->addAutoBib();
|
||||
gdi.scrollToBottom();
|
||||
gdi.addButton("Cancel", "Återgå", ClassesCB);
|
||||
@ -1263,10 +1268,19 @@ int TabClass::classCB(gdioutput &gdi, int type, void *data)
|
||||
int origin = bi.getExtraInt();
|
||||
wstring firstStart = oe->getAbsTime(3600);
|
||||
wstring minInterval = L"2:00";
|
||||
wstring vacances = L"5%";
|
||||
wstring vacances = getDefaultVacant();
|
||||
if (gdi.hasField("Vacances")) {
|
||||
vacances = gdi.getText("Vacances");
|
||||
setDefaultVacant(vacances);
|
||||
}
|
||||
|
||||
int maxNumControl = 1;
|
||||
int pairSize = 1;
|
||||
|
||||
if (gdi.hasField("AllowNeighbours")) {
|
||||
bool allowNeighbourSameCourse = gdi.isChecked("AllowNeighbours");
|
||||
oe->setProperty("DrawInterlace", allowNeighbourSameCourse ? 1 : 0);
|
||||
}
|
||||
//bool pairwise = false;
|
||||
int by = 0;
|
||||
int bx = gdi.getCX();
|
||||
@ -4387,6 +4401,7 @@ void TabClass::readDrawInfo(gdioutput &gdi, DrawInfo &drawInfoOut) {
|
||||
|
||||
int maxVacancy = gdi.getTextNo("VacancesMax");
|
||||
int minVacancy = gdi.getTextNo("VacancesMin");
|
||||
setDefaultVacant(gdi.getText("Vacances"));
|
||||
double vacancyFactor = 0.01*_wtof(gdi.getText("Vacances").c_str());
|
||||
double extraFactor = 0.01*_wtof(gdi.getText("Extra").c_str());
|
||||
|
||||
@ -4661,7 +4676,7 @@ void TabClass::loadBasicDrawSetup(gdioutput &gdi, int &bx, int &by, const wstrin
|
||||
gdi.popX();
|
||||
gdi.dropLine(4);
|
||||
gdi.fillDown();
|
||||
gdi.addCheckbox("AllowNeighbours", "Tillåt samma bana inom basintervall", 0, oe->getPropertyInt("DrawInterlace", 1) == 0);
|
||||
gdi.addCheckbox("AllowNeighbours", "Tillåt samma bana inom basintervall", 0, oe->getPropertyInt("DrawInterlace", 1) != 0);
|
||||
gdi.addCheckbox("CoursesTogether", "Lotta klasser med samma bana gemensamt", 0, false);
|
||||
|
||||
gdi.dropLine(0.5);
|
||||
@ -4680,8 +4695,10 @@ void TabClass::loadBasicDrawSetup(gdioutput &gdi, int &bx, int &by, const wstrin
|
||||
gdi.fillRight();
|
||||
gdi.popX();
|
||||
gdi.addInput("Vacances", vacances, 6, 0, L"Andel vakanser:");
|
||||
gdi.addInput("VacancesMin", L"1", 6, 0, L"Min. vakanser (per klass):");
|
||||
gdi.addInput("VacancesMax", L"10", 6, 0, L"Max. vakanser (per klass):");
|
||||
bool zeroVac = _wtoi(vacances.c_str()) == 0;
|
||||
|
||||
gdi.addInput("VacancesMin", zeroVac ? L"0" : L"1", 6, 0, L"Min. vakanser (per klass):");
|
||||
gdi.addInput("VacancesMax", zeroVac ? L"0" : L"10", 6, 0, L"Max. vakanser (per klass):");
|
||||
gdi.addInput("Extra", L"0%", 6, 0, L"Förväntad andel efteranmälda:");
|
||||
|
||||
gdi.dropLine(4);
|
||||
@ -4749,3 +4766,17 @@ void TabClass::loadReadyToDistribute(gdioutput &gdi, int &bx, int &by) {
|
||||
|
||||
gdi.refresh();
|
||||
}
|
||||
|
||||
wstring TabClass::getDefaultVacant() {
|
||||
int dvac = oe->getPropertyInt("VacantPercent", -1);
|
||||
if (dvac >= 0 && dvac <= 100)
|
||||
return itow(dvac) + L" %";
|
||||
else
|
||||
return L"5 %";
|
||||
}
|
||||
|
||||
void TabClass::setDefaultVacant(const wstring &v) {
|
||||
int val = _wtoi(v.c_str());
|
||||
if (val >= 0 && val <= 100)
|
||||
oe->setProperty("VacantPercent", val);
|
||||
}
|
||||
|
||||
@ -156,6 +156,9 @@ class TabClass :
|
||||
int maxNumControl, const wstring& minInterval, const wstring& vacances, const set<int> &clsId);
|
||||
|
||||
void loadReadyToDistribute(gdioutput &gdi, int &bx, int &by);
|
||||
|
||||
wstring getDefaultVacant();
|
||||
void setDefaultVacant(const wstring &val);
|
||||
public:
|
||||
|
||||
void clearCompetitionData();
|
||||
|
||||
@ -1545,7 +1545,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
|
||||
switch (startType) {
|
||||
case SMCommon:
|
||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0", L"0", false, oEvent::DrawMethod::Random, 1);
|
||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"0", L"0", false, false, oEvent::DrawMethod::Random, 1);
|
||||
drawn = true;
|
||||
break;
|
||||
|
||||
@ -1570,7 +1570,7 @@ int TabCompetition::competitionCB(gdioutput &gdi, int type, void *data)
|
||||
}
|
||||
}
|
||||
if (!skip)
|
||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00", L"2", true, oEvent::DrawMethod::MeOS, 1);
|
||||
oe->automaticDrawAll(gdi, formatTimeHMS(firstStart), L"2:00", L"2", true, false, oEvent::DrawMethod::MeOS, 1);
|
||||
drawn = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1686,7 +1686,7 @@ bool Table::inputChange(gdioutput &gdi, HWND hdt)
|
||||
|
||||
int Table::getColumn(int x, bool limit) const
|
||||
{
|
||||
if (columns.empty())
|
||||
if (columns.empty() || xpos.empty())
|
||||
return -1;
|
||||
|
||||
if (x<xpos[0]) {
|
||||
|
||||
@ -840,7 +840,7 @@ SI X är redan inläst. Ska den läsas in igen? = SI X is already read out. Read
|
||||
SI på = SI on
|
||||
SI-dubbletter: %d = SI duplicates: %d
|
||||
SOFT-avgift = SOFT fee
|
||||
SOFT-lottning = Swedish draw method
|
||||
SOFT-lottning = Swedish legacy draw method
|
||||
Saknad starttid = Missing Start Time
|
||||
Sammanställning = Summary
|
||||
Sammanställning, ekonomi = Summary, economy
|
||||
|
||||
@ -179,8 +179,7 @@ void gdioutput::constructor(double _scale)
|
||||
|
||||
void gdioutput::setFont(int size, const wstring &font)
|
||||
{
|
||||
//setEncoding(enc);
|
||||
double s = 1 + double(size)*0.25;// 1 + size * sqrt(double(size))*0.2;
|
||||
double s = 1 + double(size)*0.25;
|
||||
initCommon(s, font);
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
//V35: abcdef
|
||||
//V36: abcdef
|
||||
int getMeosBuild() {
|
||||
string revision("$Rev: 915 $");
|
||||
string revision("$Rev: 935 $");
|
||||
return 174 + atoi(revision.substr(5, string::npos).c_str());
|
||||
}
|
||||
|
||||
@ -42,12 +42,12 @@ int getMeosBuild() {
|
||||
//V33: abcdefghij
|
||||
//V34: abcdfge
|
||||
wstring getMeosDate() {
|
||||
wstring date(L"$Date: 2019-07-30 07:05:51 +0200 (ti, 30 jul 2019) $");
|
||||
wstring date(L"$Date: 2019-10-05 21:53:12 +0200 (lö, 05 okt 2019) $");
|
||||
return date.substr(7,10);
|
||||
}
|
||||
|
||||
wstring getBuildType() {
|
||||
return L"Update 2"; // No parantheses (...)
|
||||
return L"Update 3"; // No parantheses (...)
|
||||
}
|
||||
|
||||
wstring getMajorVersion() {
|
||||
@ -135,6 +135,13 @@ void getSupporters(vector<wstring> &supp, vector<wstring> &developSupp)
|
||||
supp.emplace_back(L"JWOC 2019");
|
||||
developSupp.emplace_back(L"OK Nackhe");
|
||||
supp.emplace_back(L"OK Rodhen");
|
||||
|
||||
supp.emplace_back(L"HEYRIES");
|
||||
developSupp.emplace_back(L"SongTao Wang / Henan Zhixing Exploration Sports Culture Co., Ltd.");
|
||||
developSupp.emplace_back(L"Australian and Oceania Orienteering Championships 2019");
|
||||
supp.emplace_back(L"Järfälla OK");
|
||||
supp.emplace_back(L"TJ Slávia Farmaceut Bratislava");
|
||||
supp.emplace_back(L"OK Tyr, Karlstad");
|
||||
supp.emplace_back(L"Magnus Thornell, Surahammars SOK");
|
||||
|
||||
reverse(supp.begin(), supp.end());
|
||||
}
|
||||
|
||||
@ -71,9 +71,7 @@ protected:
|
||||
mutable int tMapsUsed = -1;
|
||||
mutable int tMapsUsedNoVacant = -1;
|
||||
|
||||
// Get an identity sum based on controls
|
||||
int getIdSum(int nControls);
|
||||
|
||||
|
||||
/// Add an control without update
|
||||
pControl doAddControl(int Id);
|
||||
|
||||
@ -95,6 +93,9 @@ protected:
|
||||
|
||||
public:
|
||||
|
||||
// Get an identity sum based on controls
|
||||
int getIdSum(int nControls);
|
||||
|
||||
void getClasses(vector<pClass> &usageClass) const;
|
||||
|
||||
void remove();
|
||||
|
||||
@ -799,10 +799,12 @@ bool oDataContainer::isModified(const oDataInfo &di,
|
||||
return memcmp(vd, vdOld, 8) != 0;
|
||||
}
|
||||
}
|
||||
else if (di.Type == oDTString){
|
||||
char * vd=(char *)(data)+di.Index;
|
||||
char * vdOld=(char *)(oldData)+di.Index;
|
||||
return strcmp(vd, vdOld) != 0;
|
||||
else if (di.Type == oDTString) {
|
||||
LPBYTE vdB = LPBYTE(data) + di.Index;
|
||||
LPBYTE vdOldB = LPBYTE(oldData) + di.Index;
|
||||
wchar_t * vd=(wchar_t *)vdB;
|
||||
wchar_t * vdOld=(wchar_t *)vdOldB;
|
||||
return wcscmp(vd, vdOld) != 0;
|
||||
}
|
||||
else if (di.Type == oDTStringDynamic){
|
||||
const wstring &newS = (*strptr)[0][di.Index];
|
||||
|
||||
@ -2604,7 +2604,6 @@ int oEvent::getRelativeTime(const string &date, const string &absoluteTime, cons
|
||||
else return -1;
|
||||
}
|
||||
|
||||
|
||||
int oEvent::getRelativeTime(const wstring &m) const {
|
||||
int dayIndex = 0;
|
||||
for (size_t k = 0; k + 1 < m.length(); k++) {
|
||||
@ -2947,12 +2946,13 @@ void oEvent::generateVacancyList(gdioutput &gdi, GUICALLBACK cb)
|
||||
oRunnerList::iterator it;
|
||||
|
||||
// BIB, START, NAME, CLUB, SI
|
||||
int dx[5]={0, 0, 70, 150};
|
||||
int dx[5]={0, 0, gdi.scaleLength(70), gdi.scaleLength(150)};
|
||||
|
||||
bool withbib=hasBib(true, false);
|
||||
int i;
|
||||
|
||||
if (withbib) for (i=1;i<4;i++) dx[i]+=40;
|
||||
const int bibLen = gdi.scaleLength(40);
|
||||
if (withbib) for (i = 1; i < 4; i++) dx[i] += bibLen;
|
||||
|
||||
int y=gdi.getCY();
|
||||
int x=gdi.getCX();
|
||||
@ -2984,7 +2984,7 @@ void oEvent::generateVacancyList(gdioutput &gdi, GUICALLBACK cb)
|
||||
|
||||
if (nRunner>=RunnersPerCol) {
|
||||
y = yStart;
|
||||
x += dx[3]+5;
|
||||
x += dx[3]+gdi.scaleLength(5);
|
||||
nRunner = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -588,7 +588,7 @@ public:
|
||||
// Automatic draw of all classes
|
||||
void automaticDrawAll(gdioutput &gdi, const wstring &firstStart,
|
||||
const wstring &minIntervall, const wstring &vacances,
|
||||
bool lateBefore, DrawMethod method, int pairSize);
|
||||
bool lateBefore, bool allowNeighbourSameCourse, DrawMethod method, int pairSize);
|
||||
|
||||
// Restore a backup by renamning the file to .meos
|
||||
void restoreBackup();
|
||||
@ -773,10 +773,6 @@ public:
|
||||
/** Use the current computer time to convert the specified time to a long time, if long times are used. */
|
||||
int convertToFullTime(int inTime);
|
||||
|
||||
/** Internal version of start order optimizer */
|
||||
void optimizeStartOrder(vector< vector<pair<int, int> > > &StartField, DrawInfo &drawInfo,
|
||||
vector<ClassInfo> &cInfo, int useNControls, int alteration);
|
||||
|
||||
struct ResultEvent {
|
||||
ResultEvent() {}
|
||||
ResultEvent(pRunner r, int time, int control, RunnerStatus status):
|
||||
|
||||
@ -421,6 +421,328 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DrawOptimAlgo {
|
||||
private:
|
||||
oEvent * oe;
|
||||
vector<pClass> Classes;
|
||||
vector<pRunner> Runners;
|
||||
|
||||
int maxNRunner = 0;
|
||||
int maxGroup = 0;
|
||||
int maxCourse = 0;
|
||||
int bestEndPos = 0;
|
||||
|
||||
map<int, ClassInfo> otherClasses;
|
||||
|
||||
int bestEndPosGlobal = 0;
|
||||
|
||||
static int optimalLayout(int interval, vector< pair<int, int> > &classes) {
|
||||
sort(classes.begin(), classes.end());
|
||||
|
||||
vector<int> chaining(interval, 0);
|
||||
|
||||
for (int k = int(classes.size()) - 1; k >= 0; k--) {
|
||||
int ix = 0;
|
||||
// Find free position
|
||||
for (int i = 1; i<interval; i++) {
|
||||
if (chaining[i] < chaining[ix])
|
||||
ix = i;
|
||||
}
|
||||
int nr = classes[k].first;
|
||||
if (chaining[ix] > 0)
|
||||
nr += classes[k].second;
|
||||
|
||||
chaining[ix] += 1 + interval * (nr - 1);
|
||||
}
|
||||
|
||||
int last = chaining[0];
|
||||
for (int i = 1; i<interval; i++) {
|
||||
last = max(chaining[i], last);
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
void computeBestStartDepth(DrawInfo &di, vector<ClassInfo> &cInfo, int useNControls, int alteration) {
|
||||
//OutputDebugString((L"Use NC:" + itow(useNControls)).c_str());
|
||||
if (di.firstStart <= 0)
|
||||
di.firstStart = 0;
|
||||
|
||||
otherClasses.clear();
|
||||
cInfo.clear();
|
||||
map<int, int> runnerPerGroup;
|
||||
map<int, int> runnerPerCourse;
|
||||
int nRunnersTot = 0;
|
||||
for (auto c_it : Classes) {
|
||||
bool drawClass = di.classes.count(c_it->getId()) > 0;
|
||||
ClassInfo *cPtr = 0;
|
||||
|
||||
if (!drawClass) {
|
||||
otherClasses[c_it->getId()] = ClassInfo(&*c_it);
|
||||
cPtr = &otherClasses[c_it->getId()];
|
||||
}
|
||||
else
|
||||
cPtr = &di.classes[c_it->getId()];
|
||||
|
||||
ClassInfo &ci = *cPtr;
|
||||
pCourse pc = c_it->getCourse();
|
||||
|
||||
if (pc && useNControls < 1000) {
|
||||
if (useNControls > 0 && pc->getNumControls() > 0)
|
||||
ci.unique = 1000000 + pc->getIdSum(useNControls);
|
||||
else
|
||||
ci.unique = 10000 + pc->getId();
|
||||
|
||||
ci.courseId = pc->getId();
|
||||
}
|
||||
else
|
||||
ci.unique = ci.classId;
|
||||
|
||||
if (!drawClass)
|
||||
continue;
|
||||
|
||||
int nr = c_it->getNumRunners(true, true, true);
|
||||
if (ci.nVacant == -1 || !ci.nVacantSpecified || di.changedVacancyInfo) {
|
||||
// Auto initialize
|
||||
int nVacancies = int(nr * di.vacancyFactor + 0.5);
|
||||
nVacancies = max(nVacancies, di.minVacancy);
|
||||
nVacancies = min(nVacancies, di.maxVacancy);
|
||||
nVacancies = max(nVacancies, 0);
|
||||
|
||||
if (di.vacancyFactor == 0)
|
||||
nVacancies = 0;
|
||||
|
||||
ci.nVacant = nVacancies;
|
||||
ci.nVacantSpecified = false;
|
||||
}
|
||||
|
||||
if (!ci.nExtraSpecified || di.changedExtraInfo) {
|
||||
// Auto initialize
|
||||
ci.nExtra = max(int(nr * di.extraFactor + 0.5), 1);
|
||||
|
||||
if (di.extraFactor == 0)
|
||||
ci.nExtra = 0;
|
||||
ci.nExtraSpecified = false;
|
||||
}
|
||||
|
||||
ci.nRunners = nr + ci.nVacant;
|
||||
|
||||
if (ci.nRunners > 0) {
|
||||
nRunnersTot += ci.nRunners + ci.nExtra;
|
||||
cInfo.push_back(ci);
|
||||
runnerPerGroup[ci.unique] += ci.nRunners + ci.nExtra;
|
||||
runnerPerCourse[ci.courseId] += ci.nRunners + ci.nExtra;
|
||||
}
|
||||
}
|
||||
|
||||
maxGroup = 0;
|
||||
maxCourse = 0;
|
||||
maxNRunner = 0;
|
||||
int a = 1 + (alteration % 7);
|
||||
int b = (alteration % 3);
|
||||
int c = alteration % 5;
|
||||
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
maxNRunner = max(maxNRunner, cInfo[k].nRunners);
|
||||
cInfo[k].nRunnersGroup = runnerPerGroup[cInfo[k].unique];
|
||||
cInfo[k].nRunnersCourse = runnerPerCourse[cInfo[k].courseId];
|
||||
maxGroup = max(maxGroup, cInfo[k].nRunnersGroup);
|
||||
maxCourse = max(maxCourse, cInfo[k].nRunnersCourse);
|
||||
cInfo[k].sortFactor = cInfo[k].nRunners * a + cInfo[k].nRunnersGroup * b + cInfo[k].nRunnersCourse * c;
|
||||
}
|
||||
|
||||
/*for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
auto pc = oe->getClass(cInfo[k].classId);
|
||||
auto c = pc->getCourse();
|
||||
wstring cc;
|
||||
for (int i = 0; i < 3; i++)
|
||||
cc += itow(c->getControl(i)->getId()) + L",";
|
||||
wstring w = pc->getName() + L"; " + cc + L"; " + itow(cInfo[k].unique) + L"; " + itow(cInfo[k].nRunners) + L"\n";
|
||||
OutputDebugString(w.c_str());
|
||||
}*/
|
||||
|
||||
di.numDistinctInit = runnerPerGroup.size();
|
||||
di.numRunnerSameInitMax = maxGroup;
|
||||
di.numRunnerSameCourseMax = maxCourse;
|
||||
// Calculate the theoretical best end position to use.
|
||||
bestEndPos = 0;
|
||||
|
||||
for (map<int, int>::iterator it = runnerPerGroup.begin(); it != runnerPerGroup.end(); ++it) {
|
||||
vector< pair<int, int> > classes;
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].unique == it->first)
|
||||
classes.push_back(make_pair(cInfo[k].nRunners, cInfo[k].nExtra));
|
||||
}
|
||||
int optTime = optimalLayout(di.minClassInterval / di.baseInterval, classes);
|
||||
bestEndPos = max(optTime, bestEndPos);
|
||||
}
|
||||
|
||||
if (nRunnersTot > 0)
|
||||
bestEndPos = max(bestEndPos, nRunnersTot / di.nFields);
|
||||
|
||||
if (!di.allowNeighbourSameCourse)
|
||||
bestEndPos = max(bestEndPos, maxCourse * 2 - 1);
|
||||
else
|
||||
bestEndPos = max(bestEndPos, maxCourse);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
DrawOptimAlgo(oEvent *oe) : oe(oe) {
|
||||
oe->getClasses(Classes, false);
|
||||
oe->getRunners(-1, -1, Runners);
|
||||
}
|
||||
|
||||
void optimizeStartOrder(vector< vector<pair<int, int> > > &StartField, DrawInfo &di,
|
||||
vector<ClassInfo> &cInfo, int useNControls, int alteration) {
|
||||
|
||||
if (bestEndPosGlobal == 0) {
|
||||
bestEndPosGlobal = 100000;
|
||||
for (int i = 1; i <= di.maxCommonControl && i<=10; i++) {
|
||||
int ncc = i;
|
||||
if (i >= 10)
|
||||
ncc = 0;
|
||||
computeBestStartDepth(di, cInfo, ncc, 0);
|
||||
bestEndPosGlobal = min(bestEndPos, bestEndPosGlobal);
|
||||
}
|
||||
|
||||
di.minimalStartDepth = bestEndPosGlobal * di.baseInterval;
|
||||
}
|
||||
|
||||
computeBestStartDepth(di, cInfo, useNControls, alteration);
|
||||
|
||||
ClassInfo::sSortOrder = 0;
|
||||
sort(cInfo.begin(), cInfo.end());
|
||||
|
||||
int maxSize = di.minClassInterval * maxNRunner;
|
||||
|
||||
// Special case for constant time start
|
||||
if (di.baseInterval == 0) {
|
||||
di.baseInterval = 1;
|
||||
di.minClassInterval = 0;
|
||||
}
|
||||
|
||||
// Calculate an estimated maximal class intervall
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
int quotient = maxSize / (cInfo[k].nRunners*di.baseInterval);
|
||||
|
||||
if (quotient*di.baseInterval > di.maxClassInterval)
|
||||
quotient = di.maxClassInterval / di.baseInterval;
|
||||
|
||||
if (cInfo[k].nRunnersGroup >= maxGroup)
|
||||
quotient = di.minClassInterval / di.baseInterval;
|
||||
|
||||
if (!cInfo[k].hasFixedTime)
|
||||
cInfo[k].interval = quotient;
|
||||
}
|
||||
|
||||
for (int m = 0; m < di.nFields; m++)
|
||||
StartField[m].resize(3000);
|
||||
|
||||
int alternator = 0;
|
||||
|
||||
// Fill up with non-drawn classes
|
||||
for (auto &it : Runners) {
|
||||
int st = it->getStartTime();
|
||||
int relSt = st - di.firstStart;
|
||||
int relPos = relSt / di.baseInterval;
|
||||
|
||||
if (st > 0 && relSt >= 0 && relPos < 3000 && (relSt%di.baseInterval) == 0) {
|
||||
if (otherClasses.count(it->getClassId(false)) == 0)
|
||||
continue;
|
||||
pClass cls = it->getClassRef(true);
|
||||
if (cls) {
|
||||
if (!di.startName.empty() && cls->getStart() != di.startName)
|
||||
continue;
|
||||
|
||||
if (cls->hasFreeStart())
|
||||
continue;
|
||||
}
|
||||
|
||||
ClassInfo &ci = otherClasses[it->getClassId(false)];
|
||||
int k = 0;
|
||||
while (true) {
|
||||
if (k == StartField.size()) {
|
||||
StartField.push_back(vector< pair<int, int> >());
|
||||
StartField.back().resize(3000);
|
||||
}
|
||||
if (StartField[k][relPos].first == 0) {
|
||||
StartField[k][relPos].first = ci.unique;
|
||||
StartField[k][relPos].second = ci.courseId;
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill up classes with fixed starttime
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime) {
|
||||
insertStart(StartField, di.nFields, cInfo[k]);
|
||||
}
|
||||
}
|
||||
|
||||
if (di.minClassInterval == 0) {
|
||||
// Set fixed start time
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime)
|
||||
continue;
|
||||
cInfo[k].firstStart = di.firstStart;
|
||||
cInfo[k].interval = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Do the distribution
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime)
|
||||
continue;
|
||||
|
||||
int minPos = 1000000;
|
||||
int minEndPos = 1000000;
|
||||
int minInterval = cInfo[k].interval;
|
||||
|
||||
for (int i = di.minClassInterval / di.baseInterval; i <= cInfo[k].interval; i++) {
|
||||
|
||||
int startpos = alternator % max(1, (bestEndPos - cInfo[k].nRunners * i) / 3);
|
||||
startpos = 0;
|
||||
int ipos = startpos;
|
||||
int t = 0;
|
||||
|
||||
while (!isFree(di, StartField, di.nFields, ipos, i, cInfo[k])) {
|
||||
t++;
|
||||
|
||||
// Algorithm to randomize start position
|
||||
// First startpos -> bestEndTime, then 0 -> startpos, then remaining
|
||||
if (t < (bestEndPos - startpos))
|
||||
ipos = startpos + t;
|
||||
else {
|
||||
ipos = t - (bestEndPos - startpos);
|
||||
if (ipos >= startpos)
|
||||
ipos = t;
|
||||
}
|
||||
}
|
||||
|
||||
int endPos = ipos + i * cInfo[k].nRunners;
|
||||
if (endPos < minEndPos || endPos < bestEndPos) {
|
||||
minEndPos = endPos;
|
||||
minPos = ipos;
|
||||
minInterval = i;
|
||||
}
|
||||
}
|
||||
|
||||
cInfo[k].firstStart = minPos;
|
||||
cInfo[k].interval = minInterval;
|
||||
cInfo[k].overShoot = max(minEndPos - bestEndPosGlobal, 0);
|
||||
insertStart(StartField, di.nFields, cInfo[k]);
|
||||
|
||||
alternator += alteration;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void oEvent::optimizeStartOrder(gdioutput &gdi, DrawInfo &di, vector<ClassInfo> &cInfo)
|
||||
{
|
||||
if (Classes.size()==0)
|
||||
@ -439,12 +761,15 @@ void oEvent::optimizeStartOrder(gdioutput &gdi, DrawInfo &di, vector<ClassInfo>
|
||||
int nCtrl = 1;//max(1, di.maxCommonControl-2);
|
||||
const int maxControlDiff = di.maxCommonControl < 1000 ? di.maxCommonControl : 10;
|
||||
bool checkOnlyClass = di.maxCommonControl == 1000;
|
||||
|
||||
DrawOptimAlgo drawOptim(this);
|
||||
|
||||
while (!found) {
|
||||
|
||||
StartParam optInner;
|
||||
for (int alt = 0; alt <= 20 && !found; alt++) {
|
||||
vector< vector<pair<int, int> > > startField(di.nFields);
|
||||
optimizeStartOrder(startField, di, cInfo, nCtrl, alt);
|
||||
drawOptim.optimizeStartOrder(startField, di, cInfo, nCtrl, alt);
|
||||
|
||||
int overShoot = 0;
|
||||
int overSum = 0;
|
||||
@ -495,7 +820,7 @@ void oEvent::optimizeStartOrder(gdioutput &gdi, DrawInfo &di, vector<ClassInfo>
|
||||
}
|
||||
|
||||
vector< vector<pair<int, int> > > startField(di.nFields);
|
||||
optimizeStartOrder(startField, di, cInfo, opt.nControls, opt.alternator);
|
||||
drawOptim.optimizeStartOrder(startField, di, cInfo, opt.nControls, opt.alternator);
|
||||
|
||||
gdi.addString("", 0, "Identifierar X unika inledningar på banorna.#" + itos(di.numDistinctInit));
|
||||
gdi.addString("", 0, "Största gruppen med samma inledning har X platser.#" + itos(di.numRunnerSameInitMax));
|
||||
@ -545,33 +870,6 @@ void oEvent::optimizeStartOrder(gdioutput &gdi, DrawInfo &di, vector<ClassInfo>
|
||||
gdi.dropLine();
|
||||
}
|
||||
|
||||
int optimalLayout(int interval, vector< pair<int, int> > &classes) {
|
||||
sort(classes.begin(), classes.end());
|
||||
|
||||
vector<int> chaining(interval, 0);
|
||||
|
||||
for (int k = int(classes.size())-1 ; k >= 0; k--) {
|
||||
int ix = 0;
|
||||
// Find free position
|
||||
for (int i = 1; i<interval; i++) {
|
||||
if (chaining[i] < chaining[ix])
|
||||
ix = i;
|
||||
}
|
||||
int nr = classes[k].first;
|
||||
if (chaining[ix] > 0)
|
||||
nr += classes[k].second;
|
||||
|
||||
chaining[ix] += 1 + interval*(nr-1);
|
||||
}
|
||||
|
||||
int last = chaining[0];
|
||||
for (int i = 1; i<interval; i++) {
|
||||
last = max(chaining[i], last);
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
void oEvent::loadDrawSettings(const set<int> &classes, DrawInfo &drawInfo, vector<ClassInfo> &cInfo) const {
|
||||
drawInfo.firstStart = 3600 * 22;
|
||||
drawInfo.minClassInterval = 3600;
|
||||
@ -656,250 +954,6 @@ void oEvent::loadDrawSettings(const set<int> &classes, DrawInfo &drawInfo, vecto
|
||||
cInfo[k].nRunnersCourse = runnerPerCourse[cInfo[k].courseId];
|
||||
}
|
||||
}
|
||||
|
||||
void oEvent::optimizeStartOrder(vector< vector<pair<int, int> > > &StartField, DrawInfo &di,
|
||||
vector<ClassInfo> &cInfo, int useNControls, int alteration)
|
||||
{
|
||||
|
||||
if (di.firstStart<=0)
|
||||
di.firstStart = 0;
|
||||
|
||||
if (di.minClassInterval < di.baseInterval) {
|
||||
throw meosException("Startintervallet får inte vara kortare än basintervallet.");
|
||||
}
|
||||
|
||||
map<int, ClassInfo> otherClasses;
|
||||
cInfo.clear();
|
||||
oClassList::iterator c_it;
|
||||
map<int, int> runnerPerGroup;
|
||||
map<int, int> runnerPerCourse;
|
||||
int nRunnersTot = 0;
|
||||
for (c_it=Classes.begin(); c_it != Classes.end(); ++c_it) {
|
||||
bool drawClass = di.classes.count(c_it->getId())>0;
|
||||
ClassInfo *cPtr = 0;
|
||||
|
||||
if (!drawClass) {
|
||||
otherClasses[c_it->getId()] = ClassInfo(&*c_it);
|
||||
cPtr = &otherClasses[c_it->getId()];
|
||||
}
|
||||
else
|
||||
cPtr = &di.classes[c_it->getId()];
|
||||
|
||||
ClassInfo &ci = *cPtr;
|
||||
pCourse pc = c_it->getCourse();
|
||||
|
||||
if (pc && useNControls < 1000) {
|
||||
if (useNControls>0 && pc->nControls>0)
|
||||
ci.unique = 1000000 + pc->getIdSum(useNControls);
|
||||
else
|
||||
ci.unique = 10000 + pc->getId();
|
||||
|
||||
ci.courseId = pc->getId();
|
||||
}
|
||||
else
|
||||
ci.unique = ci.classId;
|
||||
|
||||
if (!drawClass)
|
||||
continue;
|
||||
|
||||
int nr = c_it->getNumRunners(true, true, true);
|
||||
if (ci.nVacant == -1 || !ci.nVacantSpecified || di.changedVacancyInfo) {
|
||||
// Auto initialize
|
||||
int nVacancies = int(nr * di.vacancyFactor + 0.5);
|
||||
nVacancies = max(nVacancies, di.minVacancy);
|
||||
nVacancies = min(nVacancies, di.maxVacancy);
|
||||
nVacancies = max(nVacancies, 0);
|
||||
|
||||
if (di.vacancyFactor == 0)
|
||||
nVacancies = 0;
|
||||
|
||||
ci.nVacant = nVacancies;
|
||||
ci.nVacantSpecified = false;
|
||||
}
|
||||
|
||||
if (!ci.nExtraSpecified || di.changedExtraInfo) {
|
||||
// Auto initialize
|
||||
ci.nExtra = max(int(nr * di.extraFactor + 0.5), 1);
|
||||
|
||||
if (di.extraFactor == 0)
|
||||
ci.nExtra = 0;
|
||||
ci.nExtraSpecified = false;
|
||||
}
|
||||
|
||||
ci.nRunners = nr + ci.nVacant;
|
||||
|
||||
if (ci.nRunners>0) {
|
||||
nRunnersTot += ci.nRunners + ci.nExtra;
|
||||
cInfo.push_back(ci);
|
||||
runnerPerGroup[ci.unique] += ci.nRunners + ci.nExtra;
|
||||
runnerPerCourse[ci.courseId] += ci.nRunners + ci.nExtra;
|
||||
}
|
||||
}
|
||||
|
||||
int maxGroup = 0;
|
||||
int maxCourse = 0;
|
||||
int maxNRunner = 0;
|
||||
int a = 1 + (alteration % 7);
|
||||
int b = (alteration % 3);
|
||||
int c = alteration % 5;
|
||||
|
||||
for (size_t k = 0; k<cInfo.size(); k++) {
|
||||
maxNRunner = max(maxNRunner, cInfo[k].nRunners);
|
||||
cInfo[k].nRunnersGroup = runnerPerGroup[cInfo[k].unique];
|
||||
cInfo[k].nRunnersCourse = runnerPerCourse[cInfo[k].courseId];
|
||||
maxGroup = max(maxGroup, cInfo[k].nRunnersGroup);
|
||||
maxCourse = max(maxCourse, cInfo[k].nRunnersCourse);
|
||||
cInfo[k].sortFactor = cInfo[k].nRunners * a + cInfo[k].nRunnersGroup * b + cInfo[k].nRunnersCourse * c;
|
||||
}
|
||||
|
||||
di.numDistinctInit = runnerPerGroup.size();
|
||||
di.numRunnerSameInitMax = maxGroup;
|
||||
di.numRunnerSameCourseMax = maxCourse;
|
||||
// Calculate the theoretical best end position to use.
|
||||
int bestEndPos = 0;
|
||||
|
||||
for (map<int, int>::iterator it = runnerPerGroup.begin(); it != runnerPerGroup.end(); ++it) {
|
||||
vector< pair<int, int> > classes;
|
||||
for (size_t k = 0; k<cInfo.size(); k++) {
|
||||
if (cInfo[k].unique == it->first)
|
||||
classes.push_back(make_pair(cInfo[k].nRunners, cInfo[k].nExtra));
|
||||
}
|
||||
int optTime = optimalLayout(di.minClassInterval/di.baseInterval, classes);
|
||||
bestEndPos = max(optTime, bestEndPos);
|
||||
}
|
||||
|
||||
if (nRunnersTot > 0)
|
||||
bestEndPos = max(bestEndPos, nRunnersTot / di.nFields);
|
||||
|
||||
bestEndPos = max(bestEndPos, maxCourse * 2);
|
||||
|
||||
di.minimalStartDepth = bestEndPos * di.baseInterval;
|
||||
|
||||
ClassInfo::sSortOrder = 0;
|
||||
sort(cInfo.begin(), cInfo.end());
|
||||
|
||||
int maxSize = di.minClassInterval * maxNRunner;
|
||||
|
||||
// Special case for constant time start
|
||||
if (di.baseInterval==0) {
|
||||
di.baseInterval = 1;
|
||||
di.minClassInterval = 0;
|
||||
}
|
||||
|
||||
// Calculate an estimated maximal class intervall
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
int quotient = maxSize/(cInfo[k].nRunners*di.baseInterval);
|
||||
|
||||
if (quotient*di.baseInterval > di.maxClassInterval)
|
||||
quotient=di.maxClassInterval/di.baseInterval;
|
||||
|
||||
if (cInfo[k].nRunnersGroup >= maxGroup)
|
||||
quotient = di.minClassInterval / di.baseInterval;
|
||||
|
||||
if (!cInfo[k].hasFixedTime)
|
||||
cInfo[k].interval = quotient;
|
||||
}
|
||||
|
||||
for(int m=0;m < di.nFields;m++)
|
||||
StartField[m].resize(3000);
|
||||
|
||||
int alternator = 0;
|
||||
|
||||
// Fill up with non-drawn classes
|
||||
for (oRunnerList::iterator it = Runners.begin(); it!=Runners.end(); ++it) {
|
||||
int st = it->getStartTime();
|
||||
int relSt = st-di.firstStart;
|
||||
int relPos = relSt / di.baseInterval;
|
||||
|
||||
if (st>0 && relSt>=0 && relPos<3000 && (relSt%di.baseInterval) == 0) {
|
||||
if (otherClasses.count(it->getClassId(false))==0)
|
||||
continue;
|
||||
|
||||
if (!di.startName.empty() && it->Class && it->Class->getStart()!=di.startName)
|
||||
continue;
|
||||
|
||||
ClassInfo &ci = otherClasses[it->getClassId(false)];
|
||||
int k = 0;
|
||||
while(true) {
|
||||
if (k==StartField.size()) {
|
||||
StartField.push_back(vector< pair<int, int> >());
|
||||
StartField.back().resize(3000);
|
||||
}
|
||||
if (StartField[k][relPos].first==0) {
|
||||
StartField[k][relPos].first = ci.unique;
|
||||
StartField[k][relPos].second = ci.courseId;
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill up classes with fixed starttime
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime) {
|
||||
insertStart(StartField, di.nFields, cInfo[k]);
|
||||
}
|
||||
}
|
||||
|
||||
if (di.minClassInterval == 0) {
|
||||
// Set fixed start time
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime)
|
||||
continue;
|
||||
cInfo[k].firstStart = di.firstStart;
|
||||
cInfo[k].interval = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Do the distribution
|
||||
for (size_t k = 0; k < cInfo.size(); k++) {
|
||||
if (cInfo[k].hasFixedTime)
|
||||
continue;
|
||||
|
||||
int minPos = 1000000;
|
||||
int minEndPos = 1000000;
|
||||
int minInterval=cInfo[k].interval;
|
||||
|
||||
for (int i = di.minClassInterval/di.baseInterval; i<=cInfo[k].interval; i++) {
|
||||
|
||||
int startpos = alternator % max(1, (bestEndPos - cInfo[k].nRunners * i)/3);
|
||||
startpos = 0;
|
||||
int ipos = startpos;
|
||||
int t = 0;
|
||||
|
||||
while( !isFree(di, StartField, di.nFields, ipos, i, cInfo[k]) ) {
|
||||
t++;
|
||||
|
||||
// Algorithm to randomize start position
|
||||
// First startpos -> bestEndTime, then 0 -> startpos, then remaining
|
||||
if (t<(bestEndPos-startpos))
|
||||
ipos = startpos + t;
|
||||
else {
|
||||
ipos = t - (bestEndPos-startpos);
|
||||
if (ipos>=startpos)
|
||||
ipos = t;
|
||||
}
|
||||
}
|
||||
|
||||
int endPos = ipos + i*cInfo[k].nRunners;
|
||||
if (endPos < minEndPos || endPos < bestEndPos) {
|
||||
minEndPos = endPos;
|
||||
minPos = ipos;
|
||||
minInterval = i;
|
||||
}
|
||||
}
|
||||
|
||||
cInfo[k].firstStart = minPos;
|
||||
cInfo[k].interval = minInterval;
|
||||
cInfo[k].overShoot = max(minEndPos - bestEndPos, 0);
|
||||
insertStart(StartField, di.nFields, cInfo[k]);
|
||||
|
||||
alternator += alteration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void oEvent::drawRemaining(DrawMethod method, bool placeAfter)
|
||||
{
|
||||
DrawType drawType = placeAfter ? DrawType::RemainingAfter : DrawType::RemainingBefore;
|
||||
@ -1271,7 +1325,7 @@ void oEvent::drawListClumped(int ClassID, int FirstStart, int Interval, int Vaca
|
||||
|
||||
void oEvent::automaticDrawAll(gdioutput &gdi, const wstring &firstStart,
|
||||
const wstring &minIntervall, const wstring &vacances,
|
||||
bool lateBefore, DrawMethod method, int pairSize)
|
||||
bool lateBefore, bool allowNeighbourSameCourse, DrawMethod method, int pairSize)
|
||||
{
|
||||
gdi.refresh();
|
||||
const int leg = 0;
|
||||
@ -1403,6 +1457,7 @@ void oEvent::automaticDrawAll(gdioutput &gdi, const wstring &firstStart,
|
||||
di.minVacancy = 1;
|
||||
di.maxVacancy = 100;
|
||||
di.vacancyFactor = vacancy;
|
||||
di.allowNeighbourSameCourse = allowNeighbourSameCourse;
|
||||
|
||||
di.startName = start;
|
||||
|
||||
|
||||
@ -3136,8 +3136,13 @@ bool oRunner::apply(bool sync, pRunner src, bool setTmpOnly) {
|
||||
tLeg = -1;
|
||||
tLegEquClass = 0;
|
||||
tUseStartPunch=true;
|
||||
if (tInTeam)
|
||||
if (tInTeam) {
|
||||
tInTeam->apply(sync, this, setTmpOnly);
|
||||
if (Class && Class->isQualificationFinalBaseClass()) {
|
||||
if (tLeg > 0 && Class == getClassRef(true))
|
||||
tNeedNoCard = true; // Not qualified
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Class && Class->hasMultiCourse()) {
|
||||
pClass pc=Class;
|
||||
|
||||
@ -142,6 +142,12 @@ void pdfwriter::selectFont(HPDF_Page page, const PDFFontSet &fs, int format, flo
|
||||
}
|
||||
}
|
||||
|
||||
const float fontFromGdiScale(double gdiScale) {
|
||||
double f = max(1.0, min(gdiScale, 3.0))-1.0;
|
||||
double s = 1.05 + 0.75*f;
|
||||
return float(s);
|
||||
}
|
||||
|
||||
void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
const wstring &file,
|
||||
const wstring &pageTitleW,
|
||||
@ -206,7 +212,9 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
float w = HPDF_Page_GetWidth(page);
|
||||
float h = HPDF_Page_GetHeight(page);
|
||||
float scale = (w / maxX) * 0.95f;
|
||||
float fontScale = 1.5f;
|
||||
|
||||
double gdiScale = gdi.getScale();
|
||||
const float fontScale = fontFromGdiScale(gdiScale);
|
||||
|
||||
vector<RenderedPage> pages;
|
||||
PageInfo pageInfo;
|
||||
@ -243,33 +251,33 @@ void pdfwriter::generatePDF(const gdioutput &gdi,
|
||||
if (fonts.count(info[k].ti.font) == 0) {
|
||||
FontInfo fi;
|
||||
gdi.getFontInfo(info[k].ti, fi);
|
||||
float fontScale;
|
||||
float fontScaleLoc;
|
||||
wstring tmpFile;
|
||||
fonts[info[k].ti.font] = fs; //Default fallback
|
||||
PDFFontSet &f = fonts[info[k].ti.font];
|
||||
|
||||
HPDF_Font font = getPDFFont(fi.normal, float(gdi.getScale()), tmpFile, fontScale);
|
||||
HPDF_Font font = getPDFFont(fi.normal, float(gdi.getScale()), tmpFile, fontScaleLoc);
|
||||
if (!tmpFile.empty())
|
||||
tmpFiles.push_back(tmpFile);
|
||||
if (font) {
|
||||
f.font = font;
|
||||
f.fontScale = fontScale;
|
||||
f.fontScale = fontScaleLoc;
|
||||
}
|
||||
|
||||
font = getPDFFont(fi.italic, float(gdi.getScale()), tmpFile, fontScale);
|
||||
font = getPDFFont(fi.italic, float(gdi.getScale()), tmpFile, fontScaleLoc);
|
||||
if (!tmpFile.empty())
|
||||
tmpFiles.push_back(tmpFile);
|
||||
if (font) {
|
||||
f.fontItalic = font;
|
||||
f.fontScaleItalic = fontScale;
|
||||
f.fontScaleItalic = fontScaleLoc;
|
||||
}
|
||||
|
||||
font = getPDFFont(fi.bold, (float)gdi.getScale(), tmpFile, fontScale);
|
||||
font = getPDFFont(fi.bold, (float)gdi.getScale(), tmpFile, fontScaleLoc);
|
||||
if (!tmpFile.empty())
|
||||
tmpFiles.push_back(tmpFile);
|
||||
if (font) {
|
||||
f.fontBold = font;
|
||||
f.fontScaleBold = fontScale;
|
||||
f.fontScaleBold = fontScaleLoc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -835,7 +835,7 @@ SI X är redan inläst. Ska den läsas in igen? = SI X är redan inläst. Ska de
|
||||
SI på = SI på
|
||||
SI-dubbletter: %d = SI-dubbletter: %d
|
||||
SOFT-avgift = SOFT-avgift
|
||||
SOFT-lottning = SOFT-lottning
|
||||
SOFT-lottning = Äldre SOFT-lottning
|
||||
Saknad starttid = Saknad starttid
|
||||
Sammanställning = Sammanställning
|
||||
Sammanställning, ekonomi = Sammanställning, ekonomi
|
||||
|
||||
Loading…
Reference in New Issue
Block a user