mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 21:40:52 -05:00 
			
		
		
		
	Parse "dx-call-1 RR73; dx-call-2 <de-call> +nn" messages in regular modes
This commit is contained in:
		
							parent
							
								
									c0a5bad58a
								
							
						
					
					
						commit
						488c42b8a2
					
				@ -11,7 +11,32 @@ extern "C" {
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  QRegularExpression words_re {R"(^(?:(?<word1>(?:CQ|DE|QRZ)(?:\s?DX|\s(?:[A-Z]{1,4}|\d{3}))|[A-Z0-9/]+|\.{3})\s)(?:(?<word2>[A-Z0-9/]+)(?:\s(?<word3>[-+A-Z0-9]+)(?:\s(?<word4>(?:OOO|(?!RR73)[A-R]{2}[0-9]{2})))?)?)?)"};
 | 
			
		||||
  QRegularExpression tokens_re {R"(
 | 
			
		||||
^
 | 
			
		||||
  (?:(?<dual>[A-Z0-9/]+)\sRR73;\s)?
 | 
			
		||||
  (?:
 | 
			
		||||
    (?<word1>
 | 
			
		||||
      (?:CQ|DE|QRZ)
 | 
			
		||||
      (?:\s?DX|\s
 | 
			
		||||
        (?:[A-Z]{1,4}|\d{3})
 | 
			
		||||
      )
 | 
			
		||||
      | [A-Z0-9/]+
 | 
			
		||||
      |\.{3}
 | 
			
		||||
    )\s
 | 
			
		||||
  )
 | 
			
		||||
  (?:
 | 
			
		||||
    (?<word2>[A-Z0-9/]+)
 | 
			
		||||
    (?:\s
 | 
			
		||||
      (?<word3>[-+A-Z0-9]+)
 | 
			
		||||
      (?:\s
 | 
			
		||||
        (?<word4>
 | 
			
		||||
          (?:OOO | (?!RR73)[A-R]{2}[0-9]{2})
 | 
			
		||||
        )
 | 
			
		||||
      )?
 | 
			
		||||
    )?
 | 
			
		||||
  )?
 | 
			
		||||
)"
 | 
			
		||||
                               , QRegularExpression::ExtendedPatternSyntaxOption};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DecodedText::DecodedText (QString const& the_string)
 | 
			
		||||
@ -60,7 +85,9 @@ QStringList DecodedText::messageWords () const
 | 
			
		||||
    // extract up to the first four message words
 | 
			
		||||
    QString t=message_;
 | 
			
		||||
    if(t.left(4)=="TU; ") t=message_.mid(4,-1);
 | 
			
		||||
    return words_re.match(t).capturedTexts();
 | 
			
		||||
    auto res = tokens_re.match(t).capturedTexts();
 | 
			
		||||
    qDebug () << "captured texts:" << res;
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
  // simple word split for free text messages
 | 
			
		||||
  auto words = message_.split (' ', SkipEmptyParts);
 | 
			
		||||
@ -128,31 +155,37 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
 | 
			
		||||
  if (message_.size () < 1) return false;
 | 
			
		||||
 | 
			
		||||
  QStringList const& w = message_.split(" ", SkipEmptyParts);
 | 
			
		||||
  if (w.size ()
 | 
			
		||||
      && is_standard_ && (w[0] == myBaseCall
 | 
			
		||||
                          || w[0].endsWith ("/" + myBaseCall)
 | 
			
		||||
                          || w[0].startsWith (myBaseCall + "/")
 | 
			
		||||
                          || (w.size () > 1 && !dxBaseCall.isEmpty ()
 | 
			
		||||
                              && (w[1] == dxBaseCall
 | 
			
		||||
                                  || w[1].endsWith ("/" + dxBaseCall)
 | 
			
		||||
                                  || w[1].startsWith (dxBaseCall + "/")))))
 | 
			
		||||
  int offset {0};
 | 
			
		||||
  if (w.size () > 2)
 | 
			
		||||
    {
 | 
			
		||||
      QString tt="";
 | 
			
		||||
      if(w.size() > 2) tt=w[2];
 | 
			
		||||
      bool ok;
 | 
			
		||||
      auto i1=tt.toInt(&ok);
 | 
			
		||||
      if (ok and i1>=-50 and i1<50)
 | 
			
		||||
      if ("RR73;" == w[1] && w.size () > 3)
 | 
			
		||||
        {
 | 
			
		||||
          report = tt;
 | 
			
		||||
          offset = 2;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
      if (is_standard_ && (w[offset] == myBaseCall
 | 
			
		||||
                           || w[offset].endsWith ("/" + myBaseCall)
 | 
			
		||||
                           || w[offset].startsWith (myBaseCall + "/")
 | 
			
		||||
                           || (w.size () > offset + 1 && !dxBaseCall.isEmpty ()
 | 
			
		||||
                               && (w[offset + 1] == dxBaseCall
 | 
			
		||||
                                   || w[offset + 1].endsWith ("/" + dxBaseCall)
 | 
			
		||||
                                   || w[offset + 1].startsWith (dxBaseCall + "/")))))
 | 
			
		||||
        {
 | 
			
		||||
          if (tt.mid(0,1)=="R")
 | 
			
		||||
          bool ok;
 | 
			
		||||
          auto tt = w[offset + 2];
 | 
			
		||||
          auto i1=tt.toInt(&ok);
 | 
			
		||||
          if (ok and i1>=-50 and i1<50)
 | 
			
		||||
            {
 | 
			
		||||
              i1=tt.mid(1).toInt(&ok);
 | 
			
		||||
              if(ok and i1>=-50 and i1<50)
 | 
			
		||||
              report = tt;
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              if (tt.mid(0,1)=="R")
 | 
			
		||||
                {
 | 
			
		||||
                  report = tt.mid(1);
 | 
			
		||||
                  i1=tt.mid(1).toInt(&ok);
 | 
			
		||||
                  if(ok and i1>=-50 and i1<50)
 | 
			
		||||
                    {
 | 
			
		||||
                      report = tt.mid(1);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@ -163,7 +196,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
 | 
			
		||||
// get the first text word, usually the call
 | 
			
		||||
QString DecodedText::call() const
 | 
			
		||||
{
 | 
			
		||||
  return words_re.match (message_).captured ("word1");
 | 
			
		||||
  return tokens_re.match (message_).captured ("word1");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// get the second word, most likely the de call and the third word, most likely grid
 | 
			
		||||
@ -175,7 +208,7 @@ void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid) const
 | 
			
		||||
    {
 | 
			
		||||
      msg = msg.mid (p + 2);
 | 
			
		||||
    }
 | 
			
		||||
  auto const& match = words_re.match (msg);
 | 
			
		||||
  auto const& match = tokens_re.match (msg);
 | 
			
		||||
  call = match.captured ("word2");
 | 
			
		||||
  grid = match.captured ("word3");
 | 
			
		||||
  if ("R" == grid) grid = match.captured ("word4");
 | 
			
		||||
 | 
			
		||||
@ -3643,7 +3643,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
 | 
			
		||||
  auto is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size();
 | 
			
		||||
  bool is_OK=false;
 | 
			
		||||
  if(m_mode=="MSK144" and message.clean_string ().indexOf(ui->dxCallEntry->text()+" R ")>0) is_OK=true;
 | 
			
		||||
  if (message_words.size () > 2 && (message.isStandardMessage() || (is_73 or is_OK))) {
 | 
			
		||||
  if (message_words.size () > 3 && (message.isStandardMessage() || (is_73 or is_OK))) {
 | 
			
		||||
    auto df = message.frequencyOffset ();
 | 
			
		||||
    auto within_tolerance = (qAbs (ui->RxFreqSpinBox->value () - df) <= int (start_tolerance)
 | 
			
		||||
       || qAbs (ui->TxFreqSpinBox->value () - df) <= int (start_tolerance));
 | 
			
		||||
@ -3675,27 +3675,29 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
 | 
			
		||||
    if (m_auto
 | 
			
		||||
        && (m_QSOProgress==REPLYING  or (!ui->tx1->isEnabled () and m_QSOProgress==REPORT))
 | 
			
		||||
        && qAbs (ui->TxFreqSpinBox->value () - df) <= int (stop_tolerance)
 | 
			
		||||
        && message_words.at (1) != "DE"
 | 
			
		||||
        && !message_words.at (1).contains (QRegularExpression {"(^(CQ|QRZ))|" + m_baseCall})
 | 
			
		||||
        && message_words.at (2).contains (Radio::base_callsign (ui->dxCallEntry->text ()))) {
 | 
			
		||||
        && message_words.at (2) != "DE"
 | 
			
		||||
        && !message_words.at (2).contains (QRegularExpression {"(^(CQ|QRZ))|" + m_baseCall})
 | 
			
		||||
        && message_words.at (3).contains (Radio::base_callsign (ui->dxCallEntry->text ()))) {
 | 
			
		||||
      // auto stop to avoid accidental QRM
 | 
			
		||||
      ui->stopTxButton->click (); // halt any transmission
 | 
			
		||||
    } else if (m_auto             // transmit allowed
 | 
			
		||||
        && ui->cbAutoSeq->isVisible () && ui->cbAutoSeq->isEnabled () && ui->cbAutoSeq->isChecked () // auto-sequencing allowed
 | 
			
		||||
        && ((!m_bCallingCQ      // not calling CQ/QRZ
 | 
			
		||||
        && !m_sentFirst73       // not finished QSO
 | 
			
		||||
        && ((message_words.at (1).contains (m_baseCall)
 | 
			
		||||
                  // being called and not already in a QSO
 | 
			
		||||
        && (message_words.at(2).contains(Radio::base_callsign(ui->dxCallEntry->text())) or bEU_VHF))
 | 
			
		||||
                 // type 2 compound replies
 | 
			
		||||
        || (within_tolerance &&
 | 
			
		||||
            (acceptable_73 ||
 | 
			
		||||
            ("DE" == message_words.at (1) &&
 | 
			
		||||
             w2.contains(Radio::base_callsign (m_hisCall)))))))
 | 
			
		||||
            || (m_bCallingCQ && m_bAutoReply
 | 
			
		||||
                // look for type 2 compound call replies on our Tx and Rx offsets
 | 
			
		||||
                && ((within_tolerance && "DE" == message_words.at (1))
 | 
			
		||||
                    || message_words.at (1).contains (m_baseCall))))) {
 | 
			
		||||
               && ui->cbAutoSeq->isVisible () && ui->cbAutoSeq->isEnabled () && ui->cbAutoSeq->isChecked () // auto-sequencing allowed
 | 
			
		||||
               && ((!m_bCallingCQ      // not calling CQ/QRZ
 | 
			
		||||
                    && !m_sentFirst73       // not finished QSO
 | 
			
		||||
                    && ((message_words.at (2).contains (m_baseCall)
 | 
			
		||||
                         // being called and not already in a QSO
 | 
			
		||||
                         && (message_words.at(3).contains(Radio::base_callsign(ui->dxCallEntry->text()))
 | 
			
		||||
                             or bEU_VHF))
 | 
			
		||||
                        || message_words.at(1) == m_baseCall // <de-call> RR73; ...
 | 
			
		||||
                        // type 2 compound replies
 | 
			
		||||
                        || (within_tolerance &&
 | 
			
		||||
                            (acceptable_73 ||
 | 
			
		||||
                             ("DE" == message_words.at (2) &&
 | 
			
		||||
                              w2.contains(Radio::base_callsign (m_hisCall)))))))
 | 
			
		||||
                   || (m_bCallingCQ && m_bAutoReply
 | 
			
		||||
                       // look for type 2 compound call replies on our Tx and Rx offsets
 | 
			
		||||
                       && ((within_tolerance && "DE" == message_words.at (2))
 | 
			
		||||
                           || message_words.at (2).contains (m_baseCall))))) {
 | 
			
		||||
      if(SpecOp::FOX != m_config.special_op_id()) processMessage (message);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -4806,7 +4808,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
  ui->txFirstCheckBox->setChecked(m_txFirst);
 | 
			
		||||
 | 
			
		||||
  auto const& message_words = message.messageWords ();
 | 
			
		||||
  if (message_words.size () < 2) return;
 | 
			
		||||
  if (message_words.size () < 3) return;
 | 
			
		||||
 | 
			
		||||
  QString hiscall;
 | 
			
		||||
  QString hisgrid;
 | 
			
		||||
@ -4824,7 +4826,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
  QStringList w=message.clean_string ().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts);
 | 
			
		||||
  int nw=w.size();
 | 
			
		||||
  if(nw>=4) {
 | 
			
		||||
    if(message_words.size()<3) return;
 | 
			
		||||
    if(message_words.size()<4) return;
 | 
			
		||||
    int n=w.at(nw-2).toInt();
 | 
			
		||||
    if(n>=520001 and n<=592047) {
 | 
			
		||||
      hiscall=w.at(1);
 | 
			
		||||
@ -4847,7 +4849,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
 | 
			
		||||
  // ignore calls by other hounds
 | 
			
		||||
  if (SpecOp::HOUND == m_config.special_op_id()
 | 
			
		||||
      && message.messageWords ().indexOf (QRegularExpression {R"(R\+-[0-9]+)"}) >= 0)
 | 
			
		||||
      && message.messageWords ().indexOf (QRegularExpression {R"(R\+-[0-9]+)"}) >= 1)
 | 
			
		||||
    {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
@ -4926,22 +4928,22 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
      MessageBox::information_message (this, tr ("Should you switch to RTTY contest mode?"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(SpecOp::EU_VHF==m_config.special_op_id() and message_words.at(1).contains(m_baseCall) and
 | 
			
		||||
       (!message_words.at(2).contains(qso_partner_base_call)) and (!m_bDoubleClicked)) {
 | 
			
		||||
    if(SpecOp::EU_VHF==m_config.special_op_id() and message_words.at(2).contains(m_baseCall) and
 | 
			
		||||
       (!message_words.at(3).contains(qso_partner_base_call)) and (!m_bDoubleClicked)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bContestOK=(m_mode=="FT4" or m_mode=="FT8" or m_mode=="Q65" or m_mode=="MSK144");
 | 
			
		||||
    if(message_words.size () > 3   // enough fields for a normal message
 | 
			
		||||
       && (message_words.at(1).contains(m_baseCall) || "DE" == message_words.at(1))
 | 
			
		||||
       && (message_words.at(2).contains(qso_partner_base_call) or m_bDoubleClicked
 | 
			
		||||
    if(message_words.size () > 4   // enough fields for a normal message
 | 
			
		||||
       && (message_words.at(2).contains(m_baseCall) || "DE" == message_words.at(2))
 | 
			
		||||
       && (message_words.at(3).contains(qso_partner_base_call) or m_bDoubleClicked
 | 
			
		||||
           or bEU_VHF_w2 or (m_QSOProgress==CALLING))) {
 | 
			
		||||
      if(message_words.at(3).contains(grid_regexp) and SpecOp::EU_VHF!=m_config.special_op_id()) {
 | 
			
		||||
      if(message_words.at(4).contains(grid_regexp) and SpecOp::EU_VHF!=m_config.special_op_id()) {
 | 
			
		||||
        if((SpecOp::NA_VHF==m_config.special_op_id() or SpecOp::WW_DIGI==m_config.special_op_id()) and bContestOK){
 | 
			
		||||
          setTxMsg(3);
 | 
			
		||||
          m_QSOProgress=ROGER_REPORT;
 | 
			
		||||
        } else {
 | 
			
		||||
          if(m_mode=="JT65" and message_words.size()>4 and message_words.at(4)=="OOO") {
 | 
			
		||||
          if(m_mode=="JT65" and message_words.size()>5 and message_words.at(5)=="OOO") {
 | 
			
		||||
            setTxMsg(3);
 | 
			
		||||
            m_QSOProgress=ROGER_REPORT;
 | 
			
		||||
          } else {
 | 
			
		||||
@ -4981,7 +4983,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
          m_QSOProgress=ROGER_REPORT;
 | 
			
		||||
        }
 | 
			
		||||
      } else {  // no grid on end of msg
 | 
			
		||||
        auto const& word_3 = message_words.at (3);
 | 
			
		||||
        auto const& word_3 = message_words.at (4);
 | 
			
		||||
        auto word_3_as_number = word_3.toInt ();
 | 
			
		||||
        if (("RRR" == word_3
 | 
			
		||||
             || (word_3_as_number == 73 && ROGERS == m_QSOProgress)
 | 
			
		||||
@ -5103,17 +5105,29 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else if (5 == message_words.size ()
 | 
			
		||||
             && m_baseCall == message_words.at (1)) {
 | 
			
		||||
      // dual Fox style message, possibly from MSHV
 | 
			
		||||
      if (m_config.prompt_to_log() || m_config.autoLog()) {
 | 
			
		||||
        logQSOTimer.start(0);
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        cease_auto_Tx_after_QSO ();
 | 
			
		||||
      }
 | 
			
		||||
      m_ntx=6;
 | 
			
		||||
      ui->txrb6->setChecked(true);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_QSOProgress >= ROGERS
 | 
			
		||||
             && message_words.size () > 2 && message_words.at (1).contains (m_baseCall)
 | 
			
		||||
             && message_words.at (2) == "73") {
 | 
			
		||||
             && message_words.size () > 3 && message_words.at (2).contains (m_baseCall)
 | 
			
		||||
             && message_words.at (3) == "73") {
 | 
			
		||||
      // 73 back to compound call holder
 | 
			
		||||
      m_ntx=5;
 | 
			
		||||
      ui->txrb5->setChecked(true);
 | 
			
		||||
      m_QSOProgress = SIGNOFF;
 | 
			
		||||
    }
 | 
			
		||||
    else if (!(m_bAutoReply && (m_QSOProgress > CALLING))) {
 | 
			
		||||
      if ((message_words.size () > 4 && message_words.at (1).contains (m_baseCall)
 | 
			
		||||
           && message_words.at (4) == "OOO")) {
 | 
			
		||||
      if ((message_words.size () > 5 && message_words.at (2).contains (m_baseCall)
 | 
			
		||||
           && message_words.at (5) == "OOO")) {
 | 
			
		||||
        // EME short code report or MSK144/FT8 contest mode reply, send back Tx3
 | 
			
		||||
        m_ntx=3;
 | 
			
		||||
        m_QSOProgress = ROGER_REPORT;
 | 
			
		||||
@ -5136,7 +5150,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (firstcall == "DE" && message_words.size () > 3 && message_words.at (3) == "73") {
 | 
			
		||||
  else if (firstcall == "DE" && message_words.size () > 4 && message_words.at (4) == "73") {
 | 
			
		||||
    if (m_QSOProgress >= ROGERS && base_call == qso_partner_base_call && m_currentMessageType) {
 | 
			
		||||
      // 73 back to compound call holder
 | 
			
		||||
      m_ntx=5;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user