334 lines
7.9 KiB
C++
334 lines
7.9 KiB
C++
/************************************************************************
|
|
MeOS - Orienteering Software
|
|
Copyright (C) 2009-2024 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
|
|
|
|
************************************************************************/
|
|
|
|
// oPunch.cpp: implementation of the oPunch class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "oPunch.h"
|
|
#include "oEvent.h"
|
|
#include "meos_util.h"
|
|
#include "localizer.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
oPunch::oPunch(oEvent* poe) : oBase(poe) {
|
|
type = 0;
|
|
punchTime = 0;
|
|
isUsed = false;
|
|
hasBeenPlayed = false;
|
|
tMatchControlId = -1;
|
|
tRogainingIndex = 0;
|
|
anyRogainingMatchControlId = -1;
|
|
tIndex = -1;
|
|
}
|
|
|
|
oPunch::~oPunch() = default;
|
|
|
|
wstring oPunch::getInfo() const
|
|
{
|
|
return L"Stämpling "+oe->gdiBase().widen(codeString());
|
|
}
|
|
|
|
string oPunch::codeString() const
|
|
{
|
|
char bf[32];
|
|
sprintf_s(bf, 32, "%d-%d;", type, punchTime);
|
|
return bf;
|
|
}
|
|
|
|
void oPunch::appendCodeString(string &dst) const {
|
|
char ubf[16];
|
|
if (punchUnit > 0)
|
|
sprintf_s(ubf, "@%d", punchUnit);
|
|
else
|
|
ubf[0] = 0;
|
|
|
|
char ubo[16];
|
|
if (origin != 0)
|
|
sprintf_s(ubo, "#%d", origin);
|
|
else
|
|
ubo[0] = 0;
|
|
|
|
char bf[48];
|
|
if (timeConstSecond > 1 && punchTime != -1) {
|
|
if (punchTime >= 0)
|
|
sprintf_s(bf, 32, "%d-%d.%d%s%s;", type, punchTime / timeConstSecond,
|
|
punchTime % timeConstSecond, ubf, ubo);
|
|
else {
|
|
sprintf_s(bf, 32, "%d--%d.%d%s%s;", type, (-punchTime) / timeConstSecond,
|
|
(-punchTime) % timeConstSecond, ubf, ubo);
|
|
}
|
|
}
|
|
else
|
|
sprintf_s(bf, 32, "%d-%d%s%s;", type, punchTime, ubf, ubo);
|
|
|
|
dst.append(bf);
|
|
}
|
|
|
|
void oPunch::decodeString(const char *s) {
|
|
const char *typeS = s;
|
|
while (*s >= '0' && *s <= '9')
|
|
++s;
|
|
|
|
type = atoi(typeS);
|
|
|
|
if (*s == '-') {
|
|
++s;
|
|
const char *timeS = s;
|
|
while ((*s >= '0' && *s <= '9') || *s == '-')
|
|
++s;
|
|
|
|
int t = atoi(timeS);
|
|
if (timeConstSecond > 1 && *s == '.') {
|
|
++s;
|
|
int tenth = *s - '0';
|
|
while ((*s >= '0' && *s <= '9')) // Eat more decimal digits (unused)
|
|
++s;
|
|
|
|
if (tenth > 0 && tenth < 10) {
|
|
if (t >= 0 && *timeS != '-')
|
|
punchTime = timeConstSecond * t + tenth;
|
|
else
|
|
punchTime = timeConstSecond * t - tenth;
|
|
}
|
|
else
|
|
punchTime = timeConstSecond * t;
|
|
}
|
|
else if (t == -1)
|
|
punchTime = t;
|
|
else
|
|
punchTime = timeConstSecond * t;
|
|
}
|
|
else
|
|
punchTime = 0;
|
|
|
|
if (*s == '@') {
|
|
++s;
|
|
punchUnit = atoi(s);
|
|
}
|
|
else {
|
|
punchUnit = 0;
|
|
}
|
|
|
|
while (*s && *s != '#' && *s != ';') {
|
|
s++;
|
|
}
|
|
|
|
if (*s == '#') {
|
|
++s;
|
|
origin = atoi(s);
|
|
}
|
|
else {
|
|
origin = 0;
|
|
}
|
|
}
|
|
|
|
wstring oPunch::getString() const {
|
|
wchar_t bf[32];
|
|
|
|
const wchar_t *ct;
|
|
wstring time(getTime(false, SubSecond::Auto));
|
|
if (!isOriginal() && origin != 0) {
|
|
if (time.length() == 1)
|
|
time = L"\u270E";
|
|
else
|
|
time = L"\u270E" + time;
|
|
}
|
|
ct = time.c_str();
|
|
|
|
wstring typeS = getType();
|
|
const wchar_t *tp = typeS.c_str();
|
|
|
|
if (type==oPunch::PunchStart)
|
|
swprintf_s(bf, L"%s\t%s", tp, ct);
|
|
else if (type==oPunch::PunchFinish)
|
|
swprintf_s(bf, L"%s\t%s", tp, ct);
|
|
else if (type==oPunch::PunchCheck)
|
|
swprintf_s(bf, L"%s\t%s", tp, ct);
|
|
else
|
|
{
|
|
if (isUsed)
|
|
swprintf_s(bf, L"%d\t%s", type, ct);
|
|
else
|
|
swprintf_s(bf, L" %d*\t%s", type, ct);
|
|
}
|
|
|
|
return bf;
|
|
}
|
|
|
|
wstring oPunch::getSimpleString() const
|
|
{
|
|
wstring time(getTime(false, SubSecond::Auto));
|
|
|
|
if (type==oPunch::PunchStart)
|
|
return lang.tl(L"starten (X)#" + time);
|
|
else if (type==oPunch::PunchFinish)
|
|
return lang.tl(L"målet (X)#" + time);
|
|
else if (type==oPunch::PunchCheck)
|
|
return lang.tl(L"check (X)#" + time);
|
|
else
|
|
return lang.tl(L"kontroll X (Y)#" + itow(type) + L"#" + time);
|
|
}
|
|
|
|
wstring oPunch::getTime(bool adjust, SubSecond mode) const
|
|
{
|
|
if (punchTime >= 0) {
|
|
int at = getTimeInt();
|
|
if (adjust)
|
|
at += tTimeAdjust.second;
|
|
if (at > 0)
|
|
return oe->getAbsTime(at, mode);
|
|
}
|
|
return makeDash(L"-");
|
|
}
|
|
|
|
int oPunch::getTimeInt() const {
|
|
if (punchUnit > 0)
|
|
return punchTime + oe->getUnitAdjustment(oPunch::SpecialPunch(type), punchUnit);
|
|
return punchTime + tTimeAdjust.first; // Adjustment "wrong time" at control
|
|
}
|
|
|
|
int oPunch::getAdjustedTime() const
|
|
{
|
|
if (punchTime>=0)
|
|
return getTimeInt() + tTimeAdjust.second;
|
|
else return -1;
|
|
}
|
|
|
|
void oPunch::setTime(const wstring &t)
|
|
{
|
|
if (convertAbsoluteTimeHMS(t, -1) <= 0) {
|
|
setTimeInt(-1, false);
|
|
return;
|
|
}
|
|
|
|
int tt = oe->getRelativeTime(t) - tTimeAdjust.first;
|
|
if (tt < 0)
|
|
tt = 0;
|
|
else if (punchUnit > 0) {
|
|
tt -= oe->getUnitAdjustment(oPunch::SpecialPunch(type), punchUnit);
|
|
}
|
|
setTimeInt(tt, false);
|
|
}
|
|
|
|
void oPunch::setTimeInt(int tt, bool databaseUpdate) {
|
|
if (tt != punchTime) {
|
|
if (origin == 0)
|
|
origin = -1; // Manual change
|
|
punchTime = tt;
|
|
if (!databaseUpdate)
|
|
updateChanged();
|
|
}
|
|
}
|
|
|
|
void oPunch::setPunchUnit(int unit) {
|
|
if (unit != punchUnit) {
|
|
punchUnit = unit;
|
|
updateChanged();
|
|
}
|
|
}
|
|
|
|
oDataContainer &oPunch::getDataBuffers(pvoid &data, pvoid &olddata, pvectorstr &strData) const {
|
|
throw std::exception("Unsupported");
|
|
}
|
|
|
|
wstring oPunch::getRunningTime(int startTime) const
|
|
{
|
|
int t = getAdjustedTime();
|
|
if (startTime>0 && t>0 && t>startTime)
|
|
return formatTime(t-startTime);
|
|
else
|
|
return makeDash(L"-");
|
|
}
|
|
|
|
void oPunch::remove()
|
|
{
|
|
// Not implemented
|
|
}
|
|
|
|
bool oPunch::canRemove() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
const wstring &oPunch::getType() const {
|
|
return getType(type);
|
|
}
|
|
|
|
const wstring &oPunch::getType(int t) {
|
|
if (t==oPunch::PunchStart)
|
|
return lang.tl("Start");
|
|
else if (t==oPunch::PunchFinish)
|
|
return lang.tl("Mål");
|
|
else if (t==oPunch::PunchCheck)
|
|
return lang.tl("Check");
|
|
else if (t>10 && t<10000) {
|
|
return itow(t);
|
|
}
|
|
return _EmptyWString;
|
|
}
|
|
|
|
void oPunch::changedObject() {
|
|
// Does nothing
|
|
}
|
|
|
|
namespace {
|
|
constexpr uint64_t origin_key = 1300602071;
|
|
}
|
|
|
|
int oPunch::computeOrigin(int time, int code) {
|
|
if (time <= 0 || code <= 0)
|
|
return false;
|
|
static_assert(timeConstHour == 36000);
|
|
time = time % (36000 * 24 * 7);
|
|
code = code % 29;
|
|
uint64_t xcode = (time * 29 + code) * 7;
|
|
assert(xcode > 0 && xcode < 1300000000);
|
|
return (xcode*53458ul) % origin_key;
|
|
}
|
|
|
|
bool oPunch::isOriginal() const {
|
|
if (origin <= 0)
|
|
return false;
|
|
return computeOrigin(oe->getZeroTimeNum() + punchTime, type) == origin;
|
|
}
|
|
|
|
int oPunch::getOriginalTime() const {
|
|
if (origin <= 0)
|
|
return 0;
|
|
|
|
constexpr uint64_t inv = 91551603;
|
|
int xcode = int((inv * uint64_t(origin)) % origin_key);
|
|
if (xcode % 7 != 0)
|
|
return 0;
|
|
|
|
int pt = ((xcode/7)-type%29) / 29;
|
|
|
|
if (punchUnit > 0)
|
|
return pt + oe->getUnitAdjustment(oPunch::SpecialPunch(type), punchUnit);
|
|
return pt + tTimeAdjust.first; // Adjustment "wrong time" at control
|
|
}
|