File: randomtextgenerator.cpp

package info (click to toggle)
texstudio 2.11.2%2Bdebian-1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 41,292 kB
  • ctags: 12,405
  • sloc: cpp: 93,072; xml: 10,217; ansic: 4,153; sh: 145; makefile: 56
file content (235 lines) | stat: -rw-r--r-- 7,402 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "randomtextgenerator.h"
#include "smallUsefulFunctions.h"
#include "ui_randomtextgenerator.h"
#include <QDateTime>

RandomTextGenerator::RandomTextGenerator(QWidget *parent, const QStringList &textLines):
	QDialog(parent),
	ui(new Ui::RandomTextGenerator), lines(textLines)
{
	ui->setupUi(this);
	connect(ui->generateButton, SIGNAL(clicked()), this, SLOT(generateText()));
	connect(ui->latexInput, SIGNAL(toggled(bool)), SLOT(resetWords()));
	connect(ui->punctationCheckBox, SIGNAL(toggled(bool)), SLOT(resetWords()));
	connect(ui->upperCaseCheckBox, SIGNAL(toggled(bool)), SLOT(resetWords()));
}

RandomTextGenerator::~RandomTextGenerator()
{
	delete ui;
}

void RandomTextGenerator::changeEvent(QEvent *e)
{
	switch (e->type()) {
	case QEvent::LanguageChange:
		ui->retranslateUi(this);
		break;
	default:
		break;
	}
}

int myrand(int max)
{
	return qrand() % max;
}


void RandomTextGenerator::generateText()
{
	//---------------------------reading all words and characters in words-------------------
	if (words.empty()) {
		if (lines.empty()) {
			ui->outputEdit->setText(tr("No data given"));
			return;
		}
		ui->outputEdit->setText(tr("Reading all words\n(This will take a while but only on the first generation)"));
		QApplication::processEvents();
		words.clear();
		chars.clear();
		bool upcase = ui->upperCaseCheckBox->isChecked();
		bool punctation = ui->punctationCheckBox->isChecked();
		foreach (const QString &line, lines) {
			QString outWord;
			static const QString Punctation = ".,:;!?";

			if (ui->latexInput->isChecked()) {
				int index = 0;
				int wordStartIndex = 0;
				int lastIndex = 0;
				LatexReader lr(line);
				while (lr.nextTextWord()) {
					if (upcase) outWord = outWord.toUpper();
					if (punctation) {
						for (int i = lastIndex; i < wordStartIndex; i++)
							if (Punctation.indexOf(line[i]) >= 0) {
								outWord += line[i];
							}
					}
					words << outWord;
					chars += outWord + " ";
					lastIndex = index;
				}
			} else {
				QStringList newl = line.split(punctation ? QRegExp("\\s+") : QRegExp("[~!@#$%^&*()_+{}|:\"\\<>?,./;[-= \t'+]"), QString::SkipEmptyParts);
				if (upcase) for (int i = 0; i < newl.size(); i++) newl[i] = newl[i].toUpper();
				words << newl;
			}
		}
		//lines.clear();
		if (words.empty()) {
			ui->outputEdit->setText(tr("The current document contains no words, but we need some phrases as a base to create the random text from"));
			return;
		}
	}


	//----------------------------------generating ---------------------------------------
	//like Shannon in "A Mathematical Theory of Communication" (1949)

	int order = -1;
	bool usewords = true;
	int length = ui->lengthSpinBox->value();
	if (ui->wordOrder1RadioButton->isChecked()) order = 1;
	else if (ui->wordOrder2RadioButton->isChecked()) order = 2;
	else if (ui->wordOrder3RadioButton->isChecked()) order = 3;
	else if (ui->wordOrderXRadioButton->isChecked()) order = ui->wordOrderSpinBox->value();
	else {
		usewords = false;
		if (ui->characterOrder1RadioButton->isChecked()) order = 1;
		else if (ui->characterOrder2RadioButton->isChecked()) order = 2;
		else if (ui->characterOrder3RadioButton->isChecked()) order = 3;
		else if (ui->characterOrderXRadioButton->isChecked()) order = ui->characterOrderSpinBox->value();
	}
	if (order <= 0) {
		ui->outputEdit->setText(tr("You didn't select an order!"));
		return;
	}
	ui->outputEdit->setText(tr("Generating random text..."));
	QApplication::processEvents();

	qsrand(QDateTime::currentDateTime().toTime_t()); //TODO: milliseconds

	text = "";
	QFile f;
	void (RandomTextGenerator::*newWordFound)(const QString &) = &RandomTextGenerator::newWordForText;
	if (ui->exportCheckBox->isChecked()) {
		newWordFound = &RandomTextGenerator::newWordForStream;
		f.setFileName(ui->exportFileNameLineEdit->text());
		if (!f.open(QFile::WriteOnly)) {
			txsWarning(tr("Couldn't create file %1").arg(ui->exportFileNameLineEdit->text()));
			return;
		}
		textStream.setDevice(&f);
		ui->outputEdit->setText(tr("Generating random text..."));
	}

	if (usewords) {
		//----------generate with words ------------------
		QList<int> wordsIds;
		QHash<QString, int> wordToId;
		QHash<int, QString> idToWord;
		QMultiHash<int, int> startingIndices;
		int totalIds = 0;
		for (int i = 0; i < words.size(); i++) {
			int id = wordToId.value(words[i], -1);
			if (id == -1) {
				totalIds++;
				id = totalIds;
				wordToId.insert(words[i], totalIds);
				idToWord.insert(totalIds, words[i]);
			}
			startingIndices.insertMulti(id, i);
			wordsIds << id;
		}
		QString text;
		QList<int> last = QList<int>() << wordToId.value(words[myrand(words.size())]);
		QList<int> possibleMatches;
		for (int n = 1; n < length; n++) {
			if (last.size() == order) last.removeFirst();
			possibleMatches.clear();
			if (last.size() == 0)
				last << wordsIds[myrand(wordsIds.size())];
			else {
				//search possible extensions and choose one of them at random
				QMultiHash<int, int>::iterator it = startingIndices.find(last.first());
				while (it != startingIndices.end() && it.key() == last.first()) {
					if (it.value() + last.size() >= wordsIds.size()) {
						++it;
						continue;
					}
					bool found = true;
					for (int j = 1; j < last.size(); j++)
						if (wordsIds[it.value() + j] != last[j]) {
							found = false;
							break;
						}
					if (found) possibleMatches << (it.value() + last.size());
					++it;
				}
				if (possibleMatches.empty())
					last = QList<int>() << wordsIds[myrand(wordsIds.size())];
				else
					last << wordsIds[possibleMatches[myrand(possibleMatches.size())]];
			}
			(this->*newWordFound)(idToWord.value(last.last()) + (myrand(15) == 0 ? "\n" : " "));
		}
	} else {
		//----------generate with characters--------------
		QString text;
		QString last = chars.at(myrand(chars.size()));
		for (int n = 1; n < length; n++) {
			if (last.size() == order) last.remove(0, 1);
			int position = myrand(chars.size());
			//choose a random position and search next possible extension
			//(faster than the method used by words, but statistically not so sound,
			//should work best with infinite large texts)
			int foundPos = -1;
			for (int i = position; i < chars.size() - last.size(); i++)
				if (chars.mid(i, last.size()) == last) {
					foundPos = i + last.size();
					break;
				}
			if (foundPos == -1) {
				for (int i = 0; i < position - last.size(); i++)
					if (chars.mid(i, last.size()) == last) {
						foundPos = i + last.size();
						break;
					}
				if (foundPos == -1) {
					last = "";
					foundPos = myrand(chars.size());
				}
			}
			const QChar &c = chars.at(foundPos);
			last += c;
			(this->*newWordFound)(c);
		}
	}

	if (ui->exportCheckBox->isChecked()) {
		ui->outputEdit->setText(tr("Finished generation"));
		textStream.setDevice(0);
	} else {
		ui->outputEdit->setText(text);
	}
}

void RandomTextGenerator::resetWords()
{
	words.clear();
}

void RandomTextGenerator::newWordForText(const QString &w)
{
	text += w;
	ui->outputEdit->setText(tr("Generating random text...") + "\n\n" + text);
	QApplication::processEvents();
}

void RandomTextGenerator::newWordForStream(const QString &w)
{
	textStream << w;
}