Smaller dictionary. Realtime text computation

This commit is contained in:
Jordan Sherer
2018-10-06 01:43:47 -04:00
parent 0e82edc9ea
commit b2e623a488
7 changed files with 523002 additions and 1047204 deletions
+50 -28
View File
@@ -54,34 +54,19 @@ QList<CodewordPair> JSC::compress(QString text){
foreach(QString w, text.split(" ", QString::SkipEmptyParts)){
bool ok = false;
auto index = lookup(w, &ok);
if(ok){
// cool, we found the word...
out.append({ codeword(index, true, b, s, c), (quint32)w.length() + 1 /* for the space that follows */ });
} else {
// hmm. no dice. let's go for a prefix match
while(!w.isEmpty()){
bool hasPrefix = false;
auto d = w.toLatin1().data();
for(quint32 i = 0; i < JSC::size; i++){
quint32 len = JSC::list[i].size;
if(strncmp(d, JSC::list[i].str, len) == 0){
w = QString(w.mid(len));
// this does both prefix and full match lookup
auto index = lookup(w, &ok);
if(!ok){
break;
}
auto t = JSC::map[index];
w = QString(w.mid(t.size));
auto index = JSC::list[i].index;
bool isLast = w.isEmpty();
out.append({ codeword(index, isLast, b, s, c), len + (isLast ? 1 : 0) /* for the space that follows */});
hasPrefix = true;
break;
}
}
if(!hasPrefix){
// no match...SOL
break;
}
}
out.append({ codeword(index, isLast, b, s, c), (quint32)t.size + (isLast ? 1 : 0) /* for the space that follows */});
}
}
@@ -150,10 +135,47 @@ quint32 JSC::lookup(QString w, bool * ok){
}
quint32 JSC::lookup(char const* b, bool *ok){
for(quint32 i = 0; i < JSC::size; i++){
if(strcmp(b, JSC::map[i].str) == 0){
quint32 index = 0;
quint32 count = 0;
bool found = false;
// first find prefix match to jump into the list faster
for(quint32 i = 0; i < JSC::prefixSize; i++){
// skip obvious non-prefixes...
if(b[0] != JSC::prefix[i].str[0]){
continue;
}
// ok, we found one... let's end early for single char strings.
if(JSC::prefix[i].size == 1){
if(ok) *ok = true;
return i;
return JSC::list[JSC::prefix[i].index].index;
}
// otherwise, keep track of the first index in the list and the number of elements
index = JSC::prefix[i].index;
count = JSC::prefix[i].size;
found = true;
break;
}
// no prefix found... no lookup
if(!found){
if(ok) *ok = false;
return 0;
}
// now that we have the first index in the list, let's just iterate through the list, comparing words along the way
for(quint32 i = index; i < index + count; i++){
// if we're no longer a prefix match, end.
if(b[0] != JSC::list[i].str[0]){
break;
}
quint32 len = JSC::list[i].size;
if(strncmp(b, JSC::list[i].str, len) == 0){
if(ok) *ok = true;
return JSC::list[i].index;
}
}
+6 -3
View File
@@ -35,9 +35,12 @@ public:
static quint32 lookup(QString w, bool *ok);
static quint32 lookup(char const* b, bool *ok);
static const quint32 size = 524288;
static const Tuple map[524288];
static const Tuple list[524288];
static const quint32 size = 262144;
static const Tuple map[262144];
static const Tuple list[262144];
static const quint32 prefixSize = 68;
static const Tuple prefix[68];
};
#endif // JSC_H
+262198 -524271
View File
File diff suppressed because it is too large Load Diff
+260711 -522855
View File
File diff suppressed because it is too large Load Diff
+30 -43
View File
@@ -549,6 +549,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_i3bit {0},
m_manual {&m_network_manager},
m_txFrameCount {0},
m_txTextDirty {false},
m_previousFreq {0}
{
ui->setupUi(this);
@@ -6162,7 +6163,7 @@ bool MainWindow::prepareNextMessageFrame()
ui->nextFreeTextMsg->clear();
// TODO: jsherer - this button thing is duplicated in two places :(
ui->startTxButton->setText(QString("Send"));
//ui->startTxButton->setText(QString("Send"));
return false;
} else {
@@ -6179,7 +6180,7 @@ bool MainWindow::prepareNextMessageFrame()
}
// TODO: jsherer - this button thing is duplicated in two places :(
ui->startTxButton->setText(QString("Sending (%1/%2)").arg(sent).arg(count));
//ui->startTxButton->setText(QString("Sending (%1/%2)").arg(sent).arg(count));
if(ui->beaconButton->isChecked()){
// bump beacon
@@ -8735,57 +8736,20 @@ void MainWindow::updateButtonDisplay(){
ui->queryButton->setText(emptyCallsign ? "Directed" : QString("Directed to %1").arg(selectedCallsign));
ui->startTxButton->setDisabled(isTransmitting || emptyText || invalidSelcal);
#if 0
// update transmit button
if(isTransmitting){
int count = m_txFrameCount;
int sent = count - m_txFrameQueue.count();
ui->startTxButton->setText(m_tune ? "Tuning" : QString("Sending (%1/%2)").arg(sent).arg(count));
ui->startTxButton->setEnabled(false);
} else {
if(ui->extFreeTextMsgEdit->toPlainText().isEmpty()){
m_txFrameCountEstimate = 0;
}
ui->startTxButton->setText(m_txFrameCountEstimate <= 0 ? QString("Send") : QString("Send (%1)").arg(m_txFrameCountEstimate));
ui->startTxButton->setEnabled(m_txFrameCountEstimate > 0 && ensureSelcalCallsignSelected(false));
}
if(m_txTextDirty){
// debounce frame and word count
if(m_txTextDirtyDebounce.isActive()){
m_txTextDirtyDebounce.stop();
}
m_txTextDirtyDebounce.start(150);
#endif
#if 0
auto text = ui->extFreeTextMsgEdit->toPlainText();
bool hasText = !text.isEmpty();
// update the estimate immediately if we know that the text box is empty...
if(hasText){
countMessageFrames(text);
} else {
updateFrameCountEstimate(0);
}
#endif
#if 0
// schedule word count update
if(hasText && m_txTextDirty && (m_txTextDirtyLastText != ui->extFreeTextMsgEdit->toPlainText() || m_txTextDirtyLastSelectedCall != selectedCallsign)){
if(m_txTextDirtyDebounce.isActive()){
m_txTextDirtyDebounce.stop();
}
m_txTextDirtyDebounce.start(100);
m_txTextDirty = false;
}
#endif
}
#define USE_SYNC_FRAME_COUNT 1
void MainWindow::refreshTextDisplay(){
auto text = ui->extFreeTextMsgEdit->toPlainText();
m_txTextDirtyLastText = text;
#if USE_SYNC_FRAME_COUNT
auto frames = buildMessageFrames(text);
@@ -8798,9 +8762,18 @@ void MainWindow::refreshTextDisplay(){
textList.append(dt.message());
}
updateTextStatsDisplay(textList.join(""), m_txFrameCountEstimate);
auto transmitText = textList.join("");
auto count = frames.length();
// ugh...i hate these globals
m_txTextDirtyLastSelectedCall = callsignSelected(true);
m_txTextDirtyLastText = text;
m_txFrameCountEstimate = count;
m_txTextDirty = false;
updateTextStatsDisplay(transmitText, count);
updateTxButtonDisplay();
m_txFrameCountEstimate = frames.length();
#else
// prepare selected callsign for directed message
QString selectedCall = callsignSelected();
@@ -8832,6 +8805,7 @@ void MainWindow::refreshTextDisplay(){
updateFrameCountEstimate(frames.length());
updateTextStatsDisplay(textList.join(""), frames.length());
m_txTextDirty = false;
});
t->start();
@@ -8851,6 +8825,19 @@ void MainWindow::updateTextStatsDisplay(QString text, int count){
}
}
void MainWindow::updateTxButtonDisplay(){
// update transmit button
if(m_tune || m_transmitting || m_txFrameCount > 0){
int count = m_txFrameCount;
int sent = count - m_txFrameQueue.count();
ui->startTxButton->setText(m_tune ? "Tuning" : QString("Sending (%1/%2)").arg(sent).arg(count));
ui->startTxButton->setEnabled(false);
} else {
ui->startTxButton->setText(m_txFrameCountEstimate <= 0 ? QString("Send") : QString("Send (%1)").arg(m_txFrameCountEstimate));
ui->startTxButton->setEnabled(m_txFrameCountEstimate > 0 && ensureSelcalCallsignSelected(false));
}
}
QString MainWindow::callsignSelected(bool useInputText){
if(!ui->tableWidgetCalls->selectedItems().isEmpty()){
auto selectedCalls = ui->tableWidgetCalls->selectedItems();
+1
View File
@@ -885,6 +885,7 @@ private:
void updateButtonDisplay();
void updateFrameCountEstimate(int count);
void updateTextStatsDisplay(QString text, int count);
void updateTxButtonDisplay();
bool isMyCallIncluded(QString const &text);
bool isAllCallIncluded(QString const &text);
QString callsignSelected(bool useInputText=false);
+3 -1
View File
@@ -75,7 +75,9 @@ SOURCES += \
messagereplydialog.cpp \
keyeater.cpp \
DriftingDateTime.cpp \
jsc.cpp
jsc.cpp \
jsc_list.cpp \
jsc_map.cpp
HEADERS += qt_helpers.hpp \
pimpl_h.hpp pimpl_impl.hpp \