tipplektionen/main.cpp

159 lines
5.2 KiB
C++

#include <algorithm>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <locale>
#include <random>
#include <string>
#include <vector>
#include <boost/program_options.hpp>
#include <unicode/unistr.h>
#include <unicode/ustream.h>
namespace po = boost::program_options;
int main(int argc, char *argv[])
{
icu::UnicodeString letters;
icu::UnicodeString mustHaveLetters;
int wordLengthMin{1};
int wordLengthMax{1024};
int lineLength{60};
int numLines{4};
std::string wordsFile{"/usr/share/dict/ngerman"};
bool lowercase{false};
bool startsCapital{false};
po::options_description desc("Erlaubte Optionen");
desc.add_options()("help,h", "Ausgabe der Hilfe")(
"characters,c", po::value<icu::UnicodeString>(&letters), "Erlaubte Buchstaben")(
"must-have,m", po::value<icu::UnicodeString>(&mustHaveLetters),
"Buchstaben, die im Wort vorhanden sein *müssen* (nur in Verbindung mit --characters; "
"Buchstaben müssen davon Subset sein.)")("min-length", po::value<int>(&wordLengthMin),
"Minimale Wortlänge")(
"max-length", po::value<int>(&wordLengthMax),
"Maximale Wortlänge")("line-length", po::value<int>(&lineLength), "Maximale Zeilenlänge")(
"num-lines,n", po::value<int>(&numLines), "Anzahl Zeilen")(
"dictfile,d", po::value<std::string>(&wordsFile), "Pfad zur Wörterbuchdatei")(
"lowercase,l", po::bool_switch(&lowercase),
"Ausgabe nur klein geschrieben")("starts-capital,s", po::bool_switch(&startsCapital),
"Wort muss mit einem Großbuchstaben beginnen");
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
} catch (po::error &err) {
std::cerr << "Fehler beim Verarbeiten der Optionen:\n";
std::cerr << err.what() << std::endl;
return 1;
}
if (vm.contains("help")) {
std::cout << desc << std::endl;
return 1;
}
if (mustHaveLetters.length() > 0) {
for (int i{0}; i < mustHaveLetters.length(); i++) {
auto ch = mustHaveLetters.charAt(i);
if (letters.indexOf(ch) == -1) {
std::cout
<< "Die Buchstaben von --must-have müssen ein Subset von --characters sein."
<< std::endl;
return 1;
}
}
}
std::ifstream infile(wordsFile);
std::string line;
icu::UnicodeString uline;
std::vector<icu::UnicodeString> words;
icu::UnicodeString lettersUpper = letters;
lettersUpper.toUpper();
icu::UnicodeString mustHaveLettersUpper = mustHaveLetters;
mustHaveLettersUpper.toUpper();
long counter{0};
if (!std::filesystem::exists(wordsFile)) {
std::cerr << "Datei existiert nicht: " << wordsFile << std::endl;
return 1;
}
while (std::getline(infile, line)) {
uline = icu::UnicodeString::fromUTF8(line);
int length = uline.length();
if (length < wordLengthMin || length > wordLengthMax)
continue;
if (mustHaveLetters.length() > 0) {
bool valid = true;
for (int i{0}; i < mustHaveLetters.length(); i++) {
auto ch = mustHaveLetters.charAt(i);
auto chU = mustHaveLettersUpper.charAt(i);
if (uline.indexOf(ch) == -1 && uline.indexOf(chU) == -1) {
valid = false;
break;
}
}
if (!valid)
continue;
}
if (letters.length() > 0) {
bool valid = true;
for (int i{0}; i < length; i++) {
auto ch = uline.charAt(i);
if (startsCapital && i == 0) {
if (lettersUpper.indexOf(ch) == -1) {
valid = false;
break;
}
} else if (letters.indexOf(ch) == -1 && lettersUpper.indexOf(ch) == -1) {
valid = false;
break;
}
}
if (!valid)
continue;
}
if (lowercase) {
uline.toLower();
}
words.push_back(uline);
counter++;
}
if (counter == 0) {
std::cout << "Keine Wörter mit den angegebenen Kriterien gefunden." << std::endl;
return 0;
}
std::cout << "Anzahl infrage kommender Wörter: " << counter << "\n" << std::endl;
std::random_device rdev;
std::mt19937 rng(rdev());
std::uniform_int_distribution<std::mt19937::result_type> distrib(0, words.size() - 1);
for (int i{0}; i < numLines; i++) {
icu::UnicodeString lectionLine;
while (lectionLine.length() < lineLength) {
if (lectionLine.isEmpty())
lectionLine.append(words.at(distrib(rng)));
else
lectionLine.append(" " + words.at(distrib(rng)));
}
if (lectionLine.length() > lineLength) {
lectionLine.retainBetween(0, lectionLine.lastIndexOf(" ") + 1);
lectionLine.trim();
}
std::cout << lectionLine << std::endl;
}
}