Skip to content

Commit

Permalink
Work on call REGEX
Browse files Browse the repository at this point in the history
  • Loading branch information
ea4k committed Nov 17, 2024
1 parent 133f5d6 commit 4b4c170
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 202 deletions.
12 changes: 5 additions & 7 deletions src/Changelog
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@

TODo: Test MainWindowInputOthers::setEntityAndPrefix
TODO: Improve the REGEX in callsign.cpp
TODO: Review the KLog first start. Reading cty.dat is terribly slow.
TODO: Working in void MainWindowInputOthers::setEntityAndPrefix
TODo: Test MainWindowInputOthers::setEntityAndPrefix
TODO-Bug: EA8, EA9 fails for subdivisions, it is detected as EA
TODO-Bug: CT9 is detected as Portugal but subdivision is properly detected

TODO-Bug: XE Mexico subdivisions are not properly detected

TODO-Bug: Query fails due to "continent" row not existing in entity table - dataproxy::getContinentShortNameFromEntity
Make sure the table entity is updated or checked.

TODO: Improve the REGEX in callsign.cpp
TODO: Review the KLog first start. Reading cty.dat is terribly slow.


TODO-Bug: Add QSOs from wsjtx does not work. Failure close to int QSO::toDB(int _qsoId) Maybe related to QSO dupe (it was already fixed)
WIP: Subdivisions only works with the main prefix. It is needed to find the prefix (EB, EC for EA and so on)
Expand Down
224 changes: 65 additions & 159 deletions src/callsign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,17 @@
#include "callsign.h"

Callsign::Callsign(const QString &callsign, QObject *parent) : QObject{parent},
fullCallsign(callsign.toUpper()), areaNumber(0), valid(false), prefValid(false)
fullCall(callsign.toUpper()), homeAreaNumber(0), valid(false), prefValid(false)
{
//qDebug() << Q_FUNC_INFO << ": " << callsign;
hostAreaNumberExist = false;
homeAreaNumberExist = false;

QRegularExpression callsignRE = callsignRegEx();
QRegularExpressionMatch match = callsignRE.match(fullCallsign);
QRegularExpressionMatch match = callsignRE.match(fullCall);

QRegularExpression prefnRE = prefixRegEx();
QRegularExpressionMatch matchPrefix = prefnRE.match(fullCallsign);
QRegularExpressionMatch matchPrefix = prefnRE.match(fullCall);
/*
QRegularExpression re("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$");
Expand All @@ -46,38 +48,53 @@ Callsign::Callsign(const QString &callsign, QObject *parent) : QObject{parent},
}
*/
//QTest::newRow("fullcall") << "fullcall" << "hostfullcall" << "hostfullpref" << "hostpref" << "hostareanumber" << "homefullcall" << "homefullpref" << "homepref" << "homeareanumber" << "homesuffix" << "additionalsuffix" << true;
/*
QString fullCall; // KB1/EA4K/QRP
QString hostFullCall; // KB1/EA4K
QString hostFullPref; // KB1
QString hostPref; // KB
int hostAreaNumber; // 1
QString homeFullCall; // EA4K
QString homeFullPref; // EA4
QString homePref; // EA
int homeAreaNumber; // 4
QString homeSuffix; // K
QString additionalSuffix; // QRP
bool valid; // The entered strig is a correct callsign
*/
if ( match.hasMatch() )
{
//it is a valid callsign
valid = true;
hostPrefixWithDelimiter = match.captured("pref");
hostPrefix = match.captured("hostprefix");
base = match.captured(3);
basePrefix = match.captured(4);
basePrefixNumber = match.captured(5);
suffixWithDelimiter = match.captured(7);
suffix = match.captured(8);
fullCall = match.captured ("fullcall");
hostFullCall = match.captured("hostfullcall");
hostFullPref = match.captured("hostfullpref");
hostPref = match.captured("hostpref");
hostAreaNumber = match.captured("hostareanumber").toInt(&hostAreaNumberExist);

homeFullCall = match.captured("homefullcall");
homeFullPref = match.captured("homefullpref");
homePref = match.captured("homepref");
homeAreaNumber = match.captured("homeareanumber").toInt(&homeAreaNumberExist);
homeSuffix = match.captured("homesuffix");

additionalSuffix = match.captured("additionalsuffix");
}
else if (matchPrefix.hasMatch())
{
prefValid = true;

//qDebug() << Q_FUNC_INFO << " - match1: " << matchPrefix.captured(1);
//qDebug() << Q_FUNC_INFO << " - match2: " << matchPrefix.captured(2);
//qDebug() << Q_FUNC_INFO << " - match3: " << matchPrefix.captured(3);
//qDebug() << Q_FUNC_INFO << " - match4: " << matchPrefix.captured(4);
//qDebug() << Q_FUNC_INFO << " - match5: " << matchPrefix.captured(5);
//qDebug() << Q_FUNC_INFO << " - match6: " << matchPrefix.captured(6);
//qDebug() << Q_FUNC_INFO << " - match7: " << matchPrefix.captured(7);
hostPrefix = matchPrefix.captured(1); // Full prefix
hostPrefixWithoutAreaNumber = matchPrefix.captured(4); // The prefix without the area number
areaNumber = matchPrefix.captured(7).toInt(); // Just the area number (optional)
hostPref = matchPrefix.captured("homeprefix");
hostFullPref = matchPrefix.captured("homefullprefix"); // The prefix without the area number
homeAreaNumber = matchPrefix.captured("homeareanumber").toInt(&homeAreaNumberExist); // Just the area number (optional)
}
else
{
//it is an invalid callsign
fullCallsign = QString();
fullCall = QString();
}
}

Expand All @@ -90,173 +107,62 @@ QRegularExpression Callsign::callsignRegEx()

QRegularExpression Callsign::prefixRegEx()
{
// Returns a REGEX that matches a hamradio prefix
return QRegularExpression(prefixRegExString(), QRegularExpression::CaseInsensitiveOption);
}

QString Callsign::callsignRegExString()
{
{ // This suffix regex matches QRP, MM... but also prefixes for remote operations.
// Suffix: ((?<suffix>QRP|MM)|((?<prefix>[A-Z0-9]{1,2})(?<areanumber>[0-9]+)?))

// Base callsign
// ^(?<basecall>(?<baseprefixwithnumber>(?<baseprefix>[A-Z][0-9]|[A-Z]|[A-Z]{1,2}|[0-9][A-Z]|E)(?<areanumber>[0-9]+))(?<basesuffix>[A-Z]+))

// Host prefix /must end in /

return QString("^(?<fullcall>(?<pref>[A-Z0-9]{1,2}[0-9]?\\/)?(?<fullhomepref>(?<hostpref>[A-Z][0-9]|[A-Z]{1,2}|[0-9][A-Z])(?<areanumber>[0-9]|[0-9]+))(?<suffix>[A-Z]+))([\/](?<additionalsuffix>[A-Z0-9]+))?");
//^(?<fullcall>(?<hostfullcall>((?<hostpref>[A-Z0-9]{1,2}(?<hostareanumber>[0-9]|[0-9]+)?)\/)?(?<fullhomepref>(?<homepref>[A-Z][0-9]|[A-Z]{1,2}|[0-9][A-Z])(?<homeareanumber>[0-9]|[0-9]+))(?<basesuffix>[A-Z]+))(\/(?<additionalsuffix>[A-Z0-9]+))?)
return QString("^(?<fullcall>((?<hostfullcall>(?<hostfullpref>(?<hostpref>[A-Z0-9]{1,2})(?<hostareanumber>[0-9]|[0-9]+)?)\\/)?(?<homefullcall>(?<homefullpref>(?<homepref>[A-Z][0-9]|[A-Z]{1,2}|[0-9][A-Z])(?<homeareanumber>[0-9]|[0-9]+))(?<homesuffix>[A-Z]+)))(\\/(?<additionalsuffix>[A-Z0-9]+))?)");
}

QString Callsign::prefixRegExString()
{
//qDebug() << Q_FUNC_INFO;
// Matches prefix: "^([A-Z0-9]+[\/])?([A-Z][0-9]|[A-Z]{1,2}|[0-9][A-Z])([0-9]|[0-9]+)([A-Z]+)([\/][A-Z0-9]+)?"
// E73 prefix is not correctly matched, it is matched as EA400 so simple prefix is not OK

return QString("^((([A-Z])|([A-Z]{1,2})|([0-9][A-Z])|([A-Z][0-9]))([0-9]*))$");
}
// Matches prefix: ^(?<homefullpref>(?<homepref>[A-Z]{1,2}|F|G|I|K|M|N|R|U|W|[A-Z][0-9]|[0-9][A-Z]|)(?<homeareanumber>[0-9]+)?)

QString Callsign::getCallsign()
{
return fullCallsign;
return QString("^(?<homefullpref>(?<homepref>[A-Z]{1,2}|F|G|I|K|M|N|R|U|W|[A-Z][0-9]|[0-9][A-Z]|)(?<homeareanumber>[0-9]+)?)");
}

QString Callsign::getHostPrefix()
{
return hostPrefix;
}

int Callsign::getAreaNumber()
{
if (prefValid)
return areaNumber;
else
return -1;
}

QString Callsign::getHostPrefixWithoutNumber()
QString Callsign::getCallsign()
{
if (prefValid)
return hostPrefixWithoutAreaNumber;
else
return QString();
return fullCall;
}

QString Callsign::getHostPrefixWithDelimiter()
{
return hostPrefixWithDelimiter;
}

QString Callsign::getBase()
{
return base;
}
QString Callsign::getHostFullPrefix(){return hostFullPref;}
int Callsign::getHostAreaNuber(){return hostAreaNumber;}

QString Callsign::getBasePrefix()
{
return basePrefix;
}
QString Callsign::getHomePrefix(){return homePref;}
QString Callsign::getHomeFullPrefix(){return homeFullPref;}
QString Callsign::getHomeSuffix(){return homeSuffix;}
int Callsign::getHomeAreaNuber(){return homeAreaNumber;}

QString Callsign::getBasePrefixNumber()
QString Callsign::getAdditionalSuffix(){ return additionalSuffix;}
QString Callsign::getHostPrefix(){return hostPref;}
{
return basePrefixNumber;
return hostPref;
}

QString Callsign::getSuffix()
int Callsign::getAreaNuber()
{
return suffix;
}

QString Callsign::getSuffixWithDelimiter()
{
return suffixWithDelimiter;
if (hostAreaNumberExist)
return hostAreaNumber;
if (homeAreaNumberExist)
return homeAreaNumber;
else
return -1;
}

QString Callsign::getWPXPrefix()
{
if ( !isValid() )
return QString();

// defined here
// https://www.cqwpx.com/rules.htm

// inspired here
// https://git.fkurz.net/dj1yfk/yfklog/src/branch/develop/yfksubs.pl#L605


/*********************
* ONLY BASE CALLSIGN
*********************/
if ( getBase() != QString()
&& getHostPrefix() == QString()
&& getSuffix() == QString() )
{
// only callsign
// return callsign prefix + prefix number
// OL80ABC -> OL80
// OK1ABC -> OK1
return getBasePrefix() + getBasePrefixNumber();
}

/*********************
* HOST PREFIX PRESENT
*********************/
if ( getHostPrefix() != QString() )
{
// callsign has a Host prefix SP/OK1XXX
// we do not look at the suffix and assign automatically HostPrefix + '0'

if ( getHostPrefix().back().isDigit() )
return getHostPrefix();

return getHostPrefix() + QString("0");
}

/****************
* SUFFIX PRESENT
****************/
if ( getSuffix().length() == 1) // some countries add single numbers as suffix to designate a call area, e.g. /4
{
bool isNumber = false;
(void)suffix.toInt(&isNumber);
if ( isNumber )
{
// callsign suffix is a number
// VE7ABC/2 -> VE2
return getBasePrefix() + getSuffix();
}

// callsign suffix is not a number
// OK1ABC/P -> OK1
return getBasePrefix() + getBasePrefixNumber();
}

/***************************
* SUFFIX PRESENT LENGTH > 1
***************************/
if ( secondarySpecialSuffixes.contains(getSuffix()) )
{
// QRP, MM etc.
// OK1ABC/AM -> OK1
return getBasePrefix() + getBasePrefixNumber();
}

// valid prefix should contain a number in the last position - check it
// and prefix is not just a number
// N8ABC/KH9 -> KH9

bool isNumber = false;
(void)getSuffix().toInt(&isNumber);

if ( isNumber )
{
// suffix contains 2 and more numbers - ignore it
return getBasePrefix() + getBasePrefixNumber();
}

// suffix is combination letters and digits and last position is a number
if ( getSuffix().back().isDigit() )
return getSuffix();

// prefix does not contain a number - add "0"
return getSuffix() + QString("0");
}

bool Callsign::isValid()
{
Expand Down
49 changes: 29 additions & 20 deletions src/callsign.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,18 @@ class Callsign : public QObject
static QStringList secondarySpecialSuffixes;

QString getCallsign();
QString getHostPrefix(); // The complete prefix (simple + area number if exists)
QString getHostPrefixWithDelimiter();
QString getBase();
QString getBasePrefix();
QString getBasePrefixNumber();
QString getSuffix();
QString getSuffixWithDelimiter();
QString getWPXPrefix();
QString getHostPrefixWithoutNumber(); // The prefix without the area number
int getAreaNumber(); // Just the prefix area number
int getAreaNuber(); // Get host area number (host if exists or home if host does note xist)

QString getHostPrefix(); // The Host prefix without area number
QString getHostFullPrefix(); // The complete host prefix (simple + area number if exists)
int getHostAreaNuber(); // Get host area number

QString getHomePrefix(); // The Home prefix without area number
QString getHomeFullPrefix(); // The complete home prefix (simple + area number if exists)
QString getHomeSuffix(); // The suffix of the base call
int getHomeAreaNuber(); // Get the home area number

QString getAdditionalSuffix(); // Additional suffixes like /P, /QRP, /MM, ...

bool isValid(); // True if it is a full callsign
bool isValidPrefix(); // True if it is a prefix, but not a call
Expand All @@ -67,16 +69,23 @@ class Callsign : public QObject
static QString prefixRegExString();
static QRegularExpression prefixRegEx();

QString fullCallsign;
QString hostPrefix;
QString hostPrefixWithoutAreaNumber;
QString hostPrefixWithDelimiter;
QString base;
QString basePrefix;
QString basePrefixNumber;
QString suffix;
QString suffixWithDelimiter;
int areaNumber;
// KB1/EA4K/QRP
QString fullCall; // KB1/EA4K/QRP
QString hostFullCall; // KB1/EA4K
QString hostFullPref; // KB1
QString hostPref; // KB
int hostAreaNumber; // 1
bool hostAreaNumberExist;

QString homeFullCall; // EA4K
QString homeFullPref; // EA4
QString homePref; // EA
int homeAreaNumber; // 4
bool homeAreaNumberExist;
QString homeSuffix; // K

QString additionalSuffix; // QRP

bool valid; // The entered strig is a correct callsign
bool prefValid; // The entered strig is a correct prefix
};
Expand Down
Loading

0 comments on commit 4b4c170

Please sign in to comment.