Exemple #1
0
/*
 * calculates the pca for the static code features or dynamic setup features
 */
size_t PcaSeparateExt::calcSpecializedPca(double toBeCovered, bool dynamic) {
	Array<double> in;
	Array<int64> ids;

	if(dynamic) {
		if(dynamicQuery.size() == 0)
			genDefaultDynamicQuery();
		readDatabase(in, ids, dynamicFeatures.size(), dynamicQuery);
	} else {
		if(query.size() == 0)
			genDefaultQuery();
		readDatabase(in, ids, staticFeatures.size(), query);
	}

	AffineLinearMap model(in.cols(), in.cols());
	Array<double> eigenvalues;

	genPCAmodel(model, in, eigenvalues);

	double sum = 0, partSum = 0;

	for(size_t i = 0; i < eigenvalues.nelem(); ++i) {
		sum += eigenvalues(i);
	}

	size_t nPCs = 0;
	toBeCovered /= 100.0;
	for(size_t i = 0; i < model.getOutputDimension(); ++i) {
		partSum += eigenvalues(i);
		if(partSum / sum > toBeCovered) {
			nPCs = i+1;
			break;
		}
	}


	AffineLinearMap reductionModel(in.cols(), nPCs);

	genPCAmodel(reductionModel, in);

//	(reductionModel.getOutputDimension(), dynamic ? dynamicFeatures.size() : staticFeatures.size());

	LOG(INFO) << reductionModel.getOutputDimension() << " PCs cover " << (partSum/sum)*100.0 << "% of the static feature's total variance\n";

 	Array<double> out = genPCs(reductionModel, in);

// 	std::cout << "REsult: " << trans << std::endl;
//	std::cout << "AFTER " << eigenvalues << std::endl;
//    std::cout << "modeld " << out << std::endl;

 	if(dynamic)
 		writeToSetup(out, ids);
 	else
 		writeToCode(out, ids);

    return out.cols();

}
Exemple #2
0
int main(int argc, char *argv[])
{
	char *iim, *idb, * oim;
	ObjectDB newobjs, known;
	Image im;

	if (argc != 4) {
		fprintf(stderr, "usage: %s <input labeled image> <input database> <output image>", argv[0]);
	}

	iim=argv[1];
	idb=argv[2];
	oim=argv[3];

	readImage(&im, iim);
	readDatabase(&known, idb); /* get the database of known objects */
	makeODB(&newobjs, getColors(&im)); /* create the database for the input image */
	getObjects(&im, &newobjs); /* fill the database for the input image */
	filterObjects(&im, &newobjs, &known); /* find known objects in the database and throw away those unknown */
	drawLines(&im, &newobjs); /* draw lines in the input image */
	writeImage(&im, oim); /* write the output image */

	free(newobjs.objs);
	free(known.objs);
	free(im.data);

	return 0;
}
Exemple #3
0
/*
 * Reads data form the database according to the current query, tests all patterns with the current model
 * and returns the error according to the error function
 */
double Trainer::evaluateDatabase(ErrorFunction& errFct) throw(MachineLearningException) {
	try {
		if(model.iterativeTraining() && nFeatures() != model.getInputDimension()) {
			std::cerr << "Number of features: " << nFeatures() << "\nModel input size: " << model.getInputDimension() << std::endl;
			throw MachineLearningException("Number of selected features is not equal to the model's input size");
		}

		Array<double> in, target;

		readDatabase(in, target);

		return errFct.error(model.getModel(), in, target);
	} catch(Kompex::SQLiteException& sqle) {
		const std::string err = "\nSQL query for evaluation data failed\n" ;
		LOG(ERROR) << err << std::endl;
		sqle.Show();
		throw ml::MachineLearningException(err);
	}catch (std::exception &exception) {
		const std::string err = "\nQuery for data failed\n" ;
		LOG(ERROR) << err << exception.what() << std::endl;
		throw ml::MachineLearningException(err);
	}
	return -1.0;

}
Exemple #4
0
/*
 * calculates the principal components of static features based on the given query and stores them in the database
 */
double PcaSeparateExt::calcSpecializedPca(size_t nInFeatures, size_t nOutFeatures, bool dynamic) {
	Array<double> in;
	Array<int64> ids;

	if(dynamic) {
		if(dynamicQuery.size() == 0)
			genDefaultDynamicQuery();
		readDatabase(in, ids, dynamicFeatures.size(), dynamicQuery);
	} else {
		if(query.size() == 0)
			genDefaultQuery();
		readDatabase(in, ids, staticFeatures.size(), query);
	}

	AffineLinearMap model(nInFeatures, nOutFeatures);
	Array<double> eigenvalues;

	genPCAmodel(model, in, eigenvalues);

	// calculate the percentage of covered variance
	double sum = 0, partSum = 0;
	size_t i = 0;
	for(; i < nOutFeatures; ++i)
		partSum += eigenvalues(i);
	sum = partSum;
	for(; i < eigenvalues.nelem(); ++i)
		sum += eigenvalues(i);
	double covered = (partSum / sum) * 100.0;
	LOG(INFO) << nOutFeatures << " PCs cover " << covered << "% of the " << (dynamic ? "dynamic" : "static") << " feature's total variance\n";

 	Array<double> out = genPCs(model, in);

// 	std::cout << "REsult: " << trans << std::endl;
//	std::cout << "AFTER " << eigenvalues << std::endl;
//    std::cout << "modeld " << out << std::endl;

 	if(dynamic)
 		writeToSetup(out, ids);
 	else
 		writeToCode(out, ids);

	return covered;

}
void PwDatabaseV3::load(const QByteArray& dbFileData, const QString& password, const QByteArray& keyFileData) {
    if (!buildCompositeKey(getPasswordBytes(password), keyFileData, combinedKey)) {
        emit dbLoadError(tr("Cryptographic library error", "Generic error message from a cryptographic library"), COMPOSITE_KEY_ERROR);
        return;
    }

    if (readDatabase(dbFileData)) {
        emit dbUnlocked();
    } else {
        // This is needed to clean up at higher abstraction levels
        emit dbLocked();
    }
}
Database* KeePass2Reader::readDatabase(const QString& filename, const CompositeKey& key)
{
    QFile file(filename);
    if (!file.open(QFile::ReadOnly)) {
        raiseError(file.errorString());
        return nullptr;
    }

    QScopedPointer<Database> db(readDatabase(&file, key));

    if (file.error() != QFile::NoError) {
        raiseError(file.errorString());
        return nullptr;
    }

    return db.take();
}
bool DatabaseConfigElementLoader::readConfig()
{
    QString filepath = ":/database/dbconfig.xml";
    qDebug() << "Loading SQL code from config file" << filepath;
    QFile file(filepath);

    if (!file.exists())
    {
        errorMessage = QObject::QObject::tr("Could not open the dbconfig.xml file. "
                            "This file is installed with the digikam application "
                            "and is absolutely required to run digikam. "
                            "Please check your installation.");
        return false;
    }

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        errorMessage = QObject::tr("Could not open dbconfig.xml file <filename>%1</filename>").arg(filepath);
        return false;
    }

    QDomDocument doc("DBConfig");

    if (!doc.setContent(&file))
    {
        file.close();
        errorMessage = QObject::tr("The XML in the dbconfig.xml file <filename>%1</filename> "
                                   "is invalid and cannot be read.").arg(filepath);
        return false;
    }

    file.close();

    QDomElement element = doc.namedItem("databaseconfig").toElement();

    if (element.isNull())
    {
        errorMessage = QObject::tr("The XML in the dbconfig.xml file <filename>%1</filename> "
                            "is missing the required element <icode>%2</icode>").arg(filepath).arg(element.tagName());
        return false;
    }

    QDomElement versionElement = element.namedItem("version").toElement();
    int version = 0;

    qDebug() << versionElement.isNull() << versionElement.text() << versionElement.text().toInt() << dbconfig_xml_version;
    if (!versionElement.isNull())
    {
        version = versionElement.text().toInt();
    }

    if (version < dbconfig_xml_version)
    {
        errorMessage = QObject::tr("An old version of the dbconfig.xml file <filename>%1</filename> "
                            "is found. Please ensure that the version released "
                            "with the running version of digiKam is installed. ").arg(filepath);
        return false;
    }

    QDomElement databaseElement =  element.firstChildElement("database");

    for ( ; !databaseElement.isNull();  databaseElement=databaseElement.nextSiblingElement("database"))
    {
        DatabaseConfigElement l_DBCfgElement = readDatabase(databaseElement);
        databaseConfigs.insert(l_DBCfgElement.databaseID, l_DBCfgElement);
    }

#ifdef DATABASEPARAMETERS_DEBUG
    qDebug() << "Found entries: " << databaseConfigs.size();
    foreach(const DatabaseConfigElement& configElement, databaseConfigs )
    {
        qDebug() << "DatabaseID: " << configElement.databaseID;
        qDebug() << "HostName: " << configElement.hostName;
        qDebug() << "DatabaseName: " << configElement.databaseName;
        qDebug() << "UserName: "******"Password: "******"Port: " << configElement.port;
        qDebug() << "ConnectOptions: " << configElement.connectOptions;
        qDebug() << "Database Server CMD: " << configElement.dbServerCmd;
        qDebug() << "Database Init CMD: " << configElement.dbInitCmd;

        /*
        qDebug() << "Statements:";

        foreach(const QString actionKey, configElement.sqlStatements.keys())
        {
            QList<databaseActionElement> l_DBActionElement = configElement.sqlStatements[actionKey].dBActionElements;
            qDebug() << "DBAction [" << actionKey << "] has [" << l_DBActionElement.size() << "] actions";
            foreach(const databaseActionElement statement, l_DBActionElement)
            {
                qDebug() << "\tMode ["<< statement.mode <<"] Value ["<< statement.statement <<"]";
            }
        }
        */
    }
Exemple #8
0
int main(int argc, char **argv){
	if( argc != 4 ){
		printf( "Must specify a Database File, book order file, and a category names. \n Feel Free to refer to the readme for usage.\n" );
		_exit( 1 );	// crash and burn
	}
	FILE *fp;

	if( (fp = fopen(argv[1], "r") ) == NULL ) {
		printf("fopen didn't work in %s line %d.\n", __FILE__ , __LINE__ );
		printf("Please Enter Valid Database File \n");
		_exit(1); // crash and burn
	}
	else if( (fp = fopen(argv[2], "r") ) == NULL ) {
		printf("fopen didn't work in %s line %d.\n", __FILE__ , __LINE__ );
		printf("Please Enter Valid Book Order File \n");
		_exit(1); // crash and burn
	}
	else if( (fp = fopen(argv[3], "r") ) == NULL ) {
		printf("fopen didn't work in %s line %d.\n", __FILE__ , __LINE__ );
		printf("Please Enter Valid Category File \n");
		_exit(1); // crash and burn
	}
	/* Done with error checking. */
	fp = fopen(argv[1], "r");
	int fSize;
	fseek(fp, 0L, SEEK_END);
	fSize = ftell(fp);
	fseek(fp, 0 , SEEK_SET);
	if(fSize == 0){
		printf("The database file is empty, cannot procceed \n");
		_exit(1);
	}
	customerList = readDatabase(fp);
	if( (error = fclose( fp ) ) > 0 ){
		printf("fclose died in %s line %d: %s \n", __FILE__ , __LINE__ , strerror(error));
		_exit(1); // crash and burn
	}
	totalProfit = 0;
	/*
	   this gives us the full set of orders that we can
	   then separate into the array of smaller queues based on the category.
	 */
	fp = fopen(argv[3], "r");
	fseek(fp, 0L, SEEK_END);
	fSize = ftell(fp);
	fseek(fp , 0 , SEEK_SET);
	if(fSize == 0){
		printf("The category file is empty, cannot procceed \n");
		_exit(1);
	}
	numcats = readCategories(fp);
	categoryList = (category*)malloc(sizeof(category)*numcats);
	fillCategory(fp);
	if(( error = fclose( fp ) )> 0 ){
		printf("fclose stuck it's nose where it didn't belong in %s line %d: %s\n", __FILE__ , __LINE__ , strerror( error ) );
		_exit(1); // crash and burn
	}
	fp = fopen(argv[2], "r");
	pthread_t	tid;
	if ((error = pthread_create( &tid, NULL , readBookOrders , fp ))){
		printf( "pthread_create() sparked the flames of revolution in %s line %d: %s\n", __FILE__ , __LINE__ , strerror( error ) );
		_exit( 1 );	// crash and burn
	}
	createThreads();
	/*create the consumer threads to wait for the producer,
	  force a join on the producer after we create the consumers
	  that way all threads are guaranteed to finish.
	 */
	if ((error = pthread_join(tid, NULL))) {
		printf( "pthread_join()ed the dark side in %s line %d: %s \n", __FILE__, __LINE__, strerror( error ) );
		_exit(1);	// crash and burn
	}

	if( (error = fclose(fp) ) > 0 ) {
		printf("fclose was beaten down by the mob in %s line %d: %s \n", __FILE__ , __LINE__ , strerror( error ) );
		_exit(1); // crash and burn
	}
	finalReport();
	free(categoryList);
	printf("Total Revenue Gained: \x1b[32m$\x1b[0m%.2lf\n", totalProfit);
	return 0; //success
}
int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);
	a.setApplicationName("KJVDiff");
	a.setApplicationVersion(QString("%1.%2.%3").arg(VERSION/10000).arg((VERSION/100)%100).arg(VERSION%100));

#if QT_VERSION < 0x050000
	QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
#endif

	g_strTranslationsPath = QFileInfo(QCoreApplication::applicationDirPath(), g_constrTranslationsPath).absoluteFilePath();
	g_strTranslationFilenamePrefix = QString::fromUtf8(g_constrTranslationFilenamePrefix);

	// Load translations and set main application based on our locale:
	CTranslatorList::instance()->setApplicationLanguage();

	int nDescriptor1 = -1;
	int nDescriptor2 = -1;
	QString strFilePathname1;
	QString strFilePathname2;
	int nArgsFound = 0;
	TBibleDescriptor bblDescriptor1;
	TBibleDescriptor bblDescriptor2;
	bool bUnknownOption = false;
	bool bIgnoreWordsOfJesus = false;
	bool bIgnoreDivineNames = false;
	bool bIgnoreTransChange = false;
	bool bIgnorePilcrows = false;
	bool bExactPilcrows = false;
	bool bIgnoreLemmas = false;
	bool bIgnoreHebrewPs119 = false;
	bool bIgnoreRendering = false;
	bool bIgnoreVerseText = false;
	bool bCaseInsensitive = false;
	bool bAccentInsensitive = false;
	bool bHyphenInsensitive = false;
	bool bUseAbbrevRefs = false;
	bool bUseConcordanceWords = false;
	bool bPunctuationOnly = false;
	bool bIgnoreEmptyVerses = false;
	bool bAllDiffs = true;
	bool bTextDiffs = false;
	bool bWordDiffs = false;

	for (int ndx = 1; ndx < argc; ++ndx) {
		QString strArg = QString::fromUtf8(argv[ndx]);
		if (!strArg.startsWith("-")) {
			++nArgsFound;
			if (nArgsFound == 1) {
				nDescriptor1 = strArg.toInt();
				strFilePathname1 = strArg;
			} else if (nArgsFound == 2) {
				nDescriptor2 = strArg.toInt();
				strFilePathname2 = strArg;
			}
		} else if (strArg.compare("-j") == 0) {
			bIgnoreWordsOfJesus = true;
		} else if (strArg.compare("-d") == 0) {
			bIgnoreDivineNames = true;
		} else if (strArg.compare("-t") == 0) {
			bIgnoreTransChange = true;
		} else if (strArg.compare("-p") == 0) {
			bIgnorePilcrows = true;
		} else if (strArg.compare("-e") == 0) {
			bExactPilcrows = true;
		} else if (strArg.compare("-l") == 0) {
			bIgnoreLemmas = true;
		} else if (strArg.compare("-s") == 0) {
			bIgnoreHebrewPs119 = true;
		} else if (strArg.compare("-r") == 0) {
			bIgnoreRendering = true;
		} else if (strArg.compare("-v") == 0) {
			bIgnoreVerseText = true;
		} else if (strArg.compare("-c") == 0) {
			bCaseInsensitive = true;
		} else if (strArg.compare("-a") == 0) {
			bAccentInsensitive = true;
		} else if (strArg.compare("-h") == 0) {
			bHyphenInsensitive = true;
		} else if (strArg.compare("-b") == 0) {
			bUseAbbrevRefs = true;
		} else if (strArg.compare("-n") == 0) {
			bUseConcordanceWords = true;
		} else if (strArg.compare("-o") == 0) {
			bPunctuationOnly = true;
		} else if (strArg.compare("-i") == 0) {
			bIgnoreEmptyVerses = true;
		} else if (strArg.compare("-m") == 0) {
			bAllDiffs = false;
			bTextDiffs = true;
		} else if (strArg.compare("-w") == 0) {
			bAllDiffs = false;
			bWordDiffs = true;
		} else {
			bUnknownOption = true;
		}
	}

	if ((nArgsFound != 2) || (bUnknownOption)) {
		std::cerr << QString("%1 Version %2\n\n").arg(a.applicationName()).arg(a.applicationVersion()).toUtf8().data();
		std::cerr << QString("Usage: %1 [options] <File/UUID-Index-1> <File/UUID-Index-2>\n\n").arg(a.applicationName()).toUtf8().data();
		std::cerr << QString("Reads the specified databases and does a comparison for pertinent differences\n").toUtf8().data();
		std::cerr << QString("    and outputs the diff results...\n").toUtf8().data();
		std::cerr << QString("\n").toUtf8().data();
		std::cerr << QString("Databases may be specified by either a file pathname and/or UUID-Index\n").toUtf8().data();
		std::cerr << QString("\n").toUtf8().data();
		std::cerr << QString("Options are:\n").toUtf8().data();
		std::cerr << QString("------------\n").toUtf8().data();
		std::cerr << QString("  -j  =  Ignore Words of Jesus\n").toUtf8().data();
		std::cerr << QString("  -d  =  Ignore Divine Names Markup\n").toUtf8().data();
		std::cerr << QString("  -t  =  Ignore Translation Change/Added Markup\n").toUtf8().data();
		std::cerr << QString("  -p  =  Ignore Pilcrows\n").toUtf8().data();
		std::cerr << QString("  -e  =  Match Exact Pilcrows (ignored if -p is set)\n").toUtf8().data();
		std::cerr << QString("  -l  =  Ignore Lemma Tags\n").toUtf8().data();
		std::cerr << QString("  -s  =  Ignore Psalm 119 Hebrew Letter Tags\n").toUtf8().data();
		std::cerr << QString("  -r  =  Ignore rendering differences of punctuation, spaces, etc\n").toUtf8().data();
		std::cerr << QString("  -v  =  Ignore verse text diffs (Verses where words are different)\n").toUtf8().data();
		std::cerr << QString("  -c  =  Case-Insensitive (i.e. Discard case rather than compare them)\n").toUtf8().data();
		std::cerr << QString("  -a  =  Accent-Insensitive (i.e. Discard accents rather than compare them)\n").toUtf8().data();
		std::cerr << QString("  -h  =  Hyphen-Insensitive (i.e. Discard hyphens rather than compare them)\n").toUtf8().data();
		std::cerr << QString("  -b  =  Use Abbreviated Book names when outputting references\n").toUtf8().data();
		std::cerr << QString("  -n  =  Use Concordance Word List instead of General Word List (Word Diffs Only)\n").toUtf8().data();
		std::cerr << QString("  -o  =  Punctuation Only (Primarily for comparing foreign text database layout)\n").toUtf8().data();
		std::cerr << QString("  -i  =  Ignore empty verses (i.e. non-existant verses)\n").toUtf8().data();
		std::cerr << QString("\n").toUtf8().data();
		std::cerr << QString("Diffs to run:\n").toUtf8().data();
		std::cerr << QString("  -m  =  Text Markup Diffs\n").toUtf8().data();
		std::cerr << QString("  -w  =  Word List Diffs\n").toUtf8().data();
		std::cerr << QString("  (By default All Diffs are run, unless one or more specific diffs is specified)\n\n").toUtf8().data();
		std::cerr << QString("UUID-Index Values:\n").toUtf8().data();
		for (unsigned int ndx = 1; ndx < bibleDescriptorCount(); ++ndx) {
			const TBibleDescriptor &bblDesc(bibleDescriptor(static_cast<BIBLE_DESCRIPTOR_ENUM>(ndx)));
			std::cerr << QString("    %1 = %2\n").arg(ndx).arg(bblDesc.m_strDBDesc).toUtf8().data();
		}
		std::cerr << "\n";
		return -1;
	}

	if ((nDescriptor1 > 0) && (static_cast<unsigned int>(nDescriptor1) < bibleDescriptorCount())) {
		bblDescriptor1 = bibleDescriptor(static_cast<BIBLE_DESCRIPTOR_ENUM>(nDescriptor1));
	} else {
		if (nDescriptor1 != 0) {
			std::cerr << QString::fromUtf8("Unknown UUID-Index: %1\n").arg(nDescriptor1).toUtf8().data();
			return -1;
		}
	}

	if ((nDescriptor2 > 0) && (static_cast<unsigned int>(nDescriptor2) < bibleDescriptorCount())) {
		bblDescriptor2 = bibleDescriptor(static_cast<BIBLE_DESCRIPTOR_ENUM>(nDescriptor2));
	} else {
		if (nDescriptor2 != 0) {
			std::cerr << QString::fromUtf8("Unknown UUID-Index: %1\n").arg(nDescriptor2).toUtf8().data();
			return -1;
		}
	}

	// ------------------------------------------------------------------------

	int nReadStatus;

	if (nDescriptor1 != 0) {
		nReadStatus = readDatabase(bblDescriptor1, true);
	} else {
		nReadStatus = readDatabaseByFilename(strFilePathname1, true);
	}
	if (nReadStatus != 0) return nReadStatus;

	if (nDescriptor2 != 0) {
		nReadStatus = readDatabase(bblDescriptor2, false);
	} else {
		nReadStatus = readDatabaseByFilename(strFilePathname2, false);
	}
	if (nReadStatus != 0) return nReadStatus;

	assert(TBibleDatabaseList::instance()->size() == 2);
	CBibleDatabasePtr pBible1 = TBibleDatabaseList::instance()->at(0);
	CBibleDatabasePtr pBible2 = TBibleDatabaseList::instance()->at(1);

	// ------------------------------------------------------------------------

	const CBibleEntry &bblEntry1(pBible1->bibleEntry());
	const CBibleEntry &bblEntry2(pBible2->bibleEntry());

	unsigned int nChkTst = qMin(bblEntry1.m_nNumTst, bblEntry2.m_nNumTst);
	if (bblEntry1.m_nNumTst != bblEntry2.m_nNumTst) {
		std::cout << QString("Number of Testaments don't match!  %1 <=> %2\nComparing only %3 Testaments\n").arg(bblEntry1.m_nNumTst).arg(bblEntry2.m_nNumTst).arg(nChkTst).toUtf8().data();
	}

	CVerseTextRichifierTags vtfTags;
	vtfTags.setAddRichPs119HebrewPrefix(false);
	if (!bIgnoreTransChange) {
		vtfTags.setTransChangeAddedTags("[", "]");
	} else {
		vtfTags.setTransChangeAddedTags(QString(), QString());
	}
	if (!bIgnoreWordsOfJesus) {
		vtfTags.setWordsOfJesusTags("<", ">");
	} else {
		vtfTags.setWordsOfJesusTags(QString(), QString());
	}
	if (!bIgnoreDivineNames) {
		vtfTags.setDivineNameTags("/", "\\");
	} else {
		vtfTags.setDivineNameTags(QString(), QString());
	}
	vtfTags.setShowPilcrowMarkers(false);

	bool bOutputedTextDiffs = false;

	if (bAllDiffs || bTextDiffs) {
		unsigned int nChkBk = qMax(bblEntry1.m_nNumBk, bblEntry2.m_nNumBk);
		for (unsigned int nBk = 1; nBk <= nChkBk; ++nBk) {
			CRelIndex ndxBook = CRelIndex(nBk, 0, 0, 0);
			const CBookEntry *pBook1 = pBible1->bookEntry(nBk);
			const CBookEntry *pBook2 = pBible2->bookEntry(nBk);
			if ((pBook1 == NULL) || (pBook2 == NULL)) {
				assert((pBook1 != NULL) || (pBook2 != NULL));		// Must have one or the other!
				std::cout << "\nBook: ";
				std::cout << ((pBook1 != NULL) ? passageReference(pBible1, bUseAbbrevRefs, ndxBook, true).toUtf8().data() : "<<missing>>");
				std::cout << " : ";
				std::cout << ((pBook2 != NULL) ? passageReference(pBible2, bUseAbbrevRefs, ndxBook, true).toUtf8().data() : "<<missing>>");
				std::cout << "\n\n";
				continue;
			}
			unsigned int nChp1 = ((pBook1->m_bHaveColophon) ? 0 : 1);
			unsigned int nChp2 = ((pBook2->m_bHaveColophon) ? 0 : 1);
			nChp1 = nChp2 = qMin(nChp1, nChp2);
			for (/* Initializers Above */; ((nChp1 <= pBook1->m_nNumChp) || (nChp2 <= pBook2->m_nNumChp)); ++nChp1, ++nChp2) {
				CRelIndex ndxChapter1 = CRelIndex(nBk, nChp1, 0, 0);
				CRelIndex ndxChapter2 = CRelIndex(nBk, nChp2, 0, 0);
				const CChapterEntry *pChapter1 = ((nChp1 != 0) ? pBible1->chapterEntry(ndxChapter1) : NULL);
				const CChapterEntry *pChapter2 = ((nChp2 != 0) ? pBible2->chapterEntry(ndxChapter2) : NULL);
				if ((nChp1 != 0) || (nChp2 != 0)) {
					assert((pChapter1 != NULL) || (pChapter2 != NULL));		// Must have one or the other!
					if ((pChapter1 == NULL) || (pChapter2 == NULL)) {
						std::cout << "\nChapter: ";
						std::cout << ((pChapter1 != NULL) ? passageReference(pBible1, bUseAbbrevRefs, ndxChapter1, true).toUtf8().data() : "<<missing>>");
						std::cout << " : ";
						std::cout << ((pChapter2 != NULL) ? passageReference(pBible2, bUseAbbrevRefs, ndxChapter2, true).toUtf8().data() : "<<missing>>");
						std::cout << "\n\n";
						continue;
					}
				}
				unsigned int nVerseCount1 = ((pChapter1 != NULL) ? pChapter1->m_nNumVrs : 0);
				unsigned int nVerseCount2 = ((pChapter2 != NULL) ? pChapter2->m_nNumVrs : 0);
				unsigned int nVrs1 = ((pChapter1 != NULL) ? (pChapter1->m_bHaveSuperscription ? 0 : 1) : 0);
				unsigned int nVrs2 = ((pChapter2 != NULL) ? (pChapter2->m_bHaveSuperscription ? 0 : 1) : 0);
				nVrs1 = nVrs2 = qMin(nVrs1, nVrs2);
				for (/* Initializers Above */; ((nVrs1 <= nVerseCount1) || (nVrs2 <= nVerseCount2)); ++nVrs1, ++nVrs2) {
					CRelIndex ndxVerse1 = CRelIndex(nBk, nChp1, nVrs1, ((nChp1 == 0) || (nVrs1 == 0)) ? 1 : 0);		// Use Word == 1 to drive toward Colophon/Superscription
					CRelIndex ndxVerse2 = CRelIndex(nBk, nChp2, nVrs2, ((nChp2 == 0) || (nVrs2 == 0)) ? 1 : 0);
					const CVerseEntry *pVerse1 = pBible1->verseEntry(ndxVerse1);
					const CVerseEntry *pVerse2 = pBible2->verseEntry(ndxVerse2);
					assert((pVerse1 != NULL) || (pVerse2 != NULL));		// Must have one or the other!
					QString strRef1 = ((pVerse1 != NULL) ? passageReference(pBible1, bUseAbbrevRefs, ndxVerse1, true) : QString("<<missing>>"));
					QString strRef2 = ((pVerse2 != NULL) ? passageReference(pBible2, bUseAbbrevRefs, ndxVerse2, true) : QString("<<missing>>"));
					QString strDiffText = QString("%1 : %2\n").arg(strRef1).arg(strRef2);
					bool bHaveBothVerses = ((pVerse1 != NULL) && (pVerse2 != NULL) && (pVerse1->m_nNumWrd != 0) && (pVerse2->m_nNumWrd != 0));

					bool bHaveDiff = !bHaveBothVerses && !bIgnoreEmptyVerses;
					if ((bHaveBothVerses) && (!bPunctuationOnly) &&
						(pVerse1->m_nNumWrd != pVerse2->m_nNumWrd)) {
						strDiffText += QString("    WordCount: %1 <=> %2\n").arg(pVerse1->m_nNumWrd).arg(pVerse2->m_nNumWrd);
						bHaveDiff = true;
					}
					if ((!bIgnorePilcrows) &&
						(bHaveBothVerses) &&
						(pVerse1->m_nPilcrow != pVerse2->m_nPilcrow)) {
						if ((bExactPilcrows) ||
							(!(((pVerse1->m_nPilcrow == CVerseEntry::PTE_NONE) && (pVerse2->m_nPilcrow == CVerseEntry::PTE_EXTRA)) ||
							   ((pVerse1->m_nPilcrow == CVerseEntry::PTE_EXTRA) && (pVerse2->m_nPilcrow == CVerseEntry::PTE_NONE)) ||
							   ((pVerse1->m_nPilcrow == CVerseEntry::PTE_MARKER) && (pVerse2->m_nPilcrow == CVerseEntry::PTE_MARKER_ADDED)) ||
							   ((pVerse1->m_nPilcrow == CVerseEntry::PTE_MARKER_ADDED) && (pVerse2->m_nPilcrow == CVerseEntry::PTE_MARKER))))) {
							strDiffText += QString("    Pilcrows: %1 <=> %2\n").arg(pVerse1->m_nPilcrow).arg(pVerse2->m_nPilcrow);
							bHaveDiff = true;
						}
					}
					QString strTemplate1 = ((pVerse1 != NULL) ? pVerse1->m_strTemplate : QString());
					QString strTemplate2 = ((pVerse2 != NULL) ? pVerse2->m_strTemplate : QString());
					bool bHaveTextDiff = false;
					if (bIgnoreDivineNames) {
						strTemplate1.remove(QRegExp("[Dd]"));
						strTemplate2.remove(QRegExp("[Dd]"));
					}
					if (bIgnoreTransChange) {
						strTemplate1.remove(QRegExp("[Tt]"));
						strTemplate2.remove(QRegExp("[Tt]"));
					}
					if (bIgnoreWordsOfJesus) {
						strTemplate1.remove(QRegExp("[Jj]"));
						strTemplate2.remove(QRegExp("[Jj]"));
					}
					if (bIgnoreLemmas) {
						strTemplate1.remove(QRegExp("[Ll]"));
						strTemplate2.remove(QRegExp("[Ll]"));
					}
					if (bIgnoreHebrewPs119) {
						strTemplate1.remove(QRegExp("[M]"));
						strTemplate2.remove(QRegExp("[M]"));
					}
					if (bIgnoreVerseText || bPunctuationOnly) {
						// Leave the "w" in place so that rendering checks will work correctly!
						// strTemplate1.remove(QRegExp("[w]"));
						// strTemplate2.remove(QRegExp("[w]"));
					} else if ((!bIgnoreEmptyVerses) ||
							   (bIgnoreEmptyVerses && !strTemplate1.isEmpty() && !strTemplate2.isEmpty())) {
						CVerseEntry veNewVerseWords1((pVerse1 != NULL) ? *pVerse1 : CVerseEntry());
						QString strWordTemplate1;
						for (unsigned int nWrd = 0; nWrd < veNewVerseWords1.m_nNumWrd; ++nWrd) {
							if (nWrd != 0) {
								strWordTemplate1 += " w";
							} else {
								strWordTemplate1 += "w";
							}
						}
						veNewVerseWords1.m_strTemplate = strWordTemplate1;

						CVerseEntry veNewVerseWords2((pVerse2 != NULL) ? *pVerse2 : CVerseEntry());
						QString strWordTemplate2;
						for (unsigned int nWrd = 0; nWrd < veNewVerseWords2.m_nNumWrd; ++nWrd) {
							if (nWrd != 0) {
								strWordTemplate2 += " w";
							} else {
								strWordTemplate2 += "w";
							}
						}
						veNewVerseWords2.m_strTemplate = strWordTemplate2;

						QString strVerseText1 = CVerseTextRichifier::parse(ndxVerse1, pBible1.data(), &veNewVerseWords1, vtfTags);
						QString strVerseText2 = CVerseTextRichifier::parse(ndxVerse2, pBible2.data(), &veNewVerseWords2, vtfTags);
						if (bAccentInsensitive) {
							strVerseText1 = CSearchStringListModel::decompose(strVerseText1, bHyphenInsensitive);
							strVerseText2 = CSearchStringListModel::decompose(strVerseText2, bHyphenInsensitive);
						} else {
							strVerseText1 = CSearchStringListModel::deApostrHyphen(strVerseText1, bHyphenInsensitive);
							strVerseText2 = CSearchStringListModel::deApostrHyphen(strVerseText2, bHyphenInsensitive);
						}
						if (bCaseInsensitive) {
							strVerseText1 = strVerseText1.toLower();
							strVerseText2 = strVerseText2.toLower();
						}
						if (strVerseText1 != strVerseText2) bHaveTextDiff = true;
					}
					if (bIgnoreRendering) {
						strTemplate1.remove(QRegExp("[^DdTtJjLlMw]"));
						strTemplate2.remove(QRegExp("[^DdTtJjLlMw]"));
					}
					CVerseEntry veNewVerse1((pVerse1 != NULL) ? *pVerse1 : CVerseEntry());
					veNewVerse1.m_strTemplate = strTemplate1;
					CVerseEntry veNewVerse2((pVerse2 != NULL) ? *pVerse2 : CVerseEntry());
					veNewVerse2.m_strTemplate = strTemplate2;
					// Do PunctuationOnly reduction here so that we leave the full rendering spec in the NewVerse objects so we don't assert on rendering the words
					if (bPunctuationOnly) {
//						strTemplate1.remove(QRegExp("[^\\.\\,\\?\\!\\-\\:\\;]"));
//						strTemplate2.remove(QRegExp("[^\\.\\,\\?\\!\\-\\:\\;]"));
						// Special case for comparing the King James Française by ignoring commas too:
						strTemplate1.remove(QRegExp("[^\\.\\?\\!\\-\\:\\;]"));
						strTemplate2.remove(QRegExp("[^\\.\\?\\!\\-\\:\\;]"));
					}
					if ((bIgnoreEmptyVerses) &&
						(strTemplate1.isEmpty() || strTemplate2.isEmpty())) {
						strTemplate1.clear();
						strTemplate2.clear();
					}
					// Note: deApostrHyphen is used here so that hyphen and apostrophy differences in the rendering markup (like the weird extra hyphen
					//			that exists in Exodus 32:32 doesn't trigger unsubstantiated diffs):
					if (CSearchStringListModel::deApostrHyphen(strTemplate1, false) != CSearchStringListModel::deApostrHyphen(strTemplate2, false)) {
						if (pVerse1 != NULL) {
							if (pVerse1->m_strTemplate != strTemplate1) {
								strDiffText += QString("    Template1: \"%1\" <= \"%2\"\n").arg(strTemplate1).arg(pVerse1->m_strTemplate);
							} else {
								strDiffText += QString("    Template1: \"%1\"\n").arg(strTemplate1);
							}
						}
						if (pVerse2 != NULL) {
							if (pVerse2->m_strTemplate != strTemplate2) {
								strDiffText += QString("    Template2: \"%1\" <= \"%2\"\n").arg(strTemplate2).arg(pVerse2->m_strTemplate);
							} else {
								strDiffText += QString("    Template2: \"%1\"\n").arg(strTemplate2);
							}
						}
						if (pVerse1 != NULL) {
							strDiffText += QString("    Text1: %1\n").arg(CVerseTextRichifier::parse(ndxVerse1, pBible1.data(), &veNewVerse1, vtfTags)).toUtf8().data();
						}
						if (pVerse2 != NULL) {
							strDiffText += QString("    Text2: %1\n").arg(CVerseTextRichifier::parse(ndxVerse2, pBible2.data(), &veNewVerse2, vtfTags)).toUtf8().data();
						}
						bHaveDiff = true;
					} else if (bHaveTextDiff) {
						if (pVerse1 != NULL) {
							strDiffText += QString("    Text1: %1\n").arg(CVerseTextRichifier::parse(ndxVerse1, pBible1.data(), &veNewVerse1, vtfTags)).toUtf8().data();
						}
						if (pVerse2 != NULL) {
							strDiffText += QString("    Text2: %1\n").arg(CVerseTextRichifier::parse(ndxVerse2, pBible2.data(), &veNewVerse2, vtfTags)).toUtf8().data();
						}
						bHaveDiff = true;
					}
					if (bHaveDiff) {
						std::cout << QString("%1%2\n").arg(bOutputedTextDiffs ? QString("--------------------\n") : QString()).arg(strDiffText).toUtf8().data();
						bOutputedTextDiffs = true;
					}
				}
			}
		}
	}

	if (bAllDiffs || bWordDiffs) {
#define COLUMN_SPACE 2
		int nMaxWordSize = 0;
		for (TConcordanceList::const_iterator itr = pBible1->concordanceWordList().constBegin(); itr != pBible1->concordanceWordList().constEnd(); ++itr) {
			nMaxWordSize = qMax(nMaxWordSize, itr->word().size());
		}

		QString strWordDiffOutput;

		if (bUseConcordanceWords) {
			TWordDiffEntryList lstWordDiffs1;
			lstWordDiffs1.reserve(pBible1->concordanceWordList().size());
			for (TConcordanceList::const_iterator itr = pBible1->concordanceWordList().constBegin(); itr != pBible1->concordanceWordList().constEnd(); ++itr) {
				QString strWord = itr->word();
				if (bAccentInsensitive) {
					strWord = CSearchStringListModel::decompose(strWord, bHyphenInsensitive);
				} else {
					strWord = CSearchStringListModel::deApostrHyphen(strWord, bHyphenInsensitive);
				}
				if (bCaseInsensitive) {
					strWord = strWord.toLower();
				}
				lstWordDiffs1.append(strWord);
			}
			qSort(lstWordDiffs1.begin(), lstWordDiffs1.end(), TWordDiffEntryListSortPredicate::ascendingLessThanWordCaseInsensitive);
			TWordDiffEntryList_removeDuplicates(lstWordDiffs1);

			TWordDiffEntryList lstWordDiffs2;
			lstWordDiffs2.reserve(pBible2->concordanceWordList().size());
			for (TConcordanceList::const_iterator itr = pBible2->concordanceWordList().constBegin(); itr != pBible2->concordanceWordList().constEnd(); ++itr) {
				QString strWord = itr->word();
				if (bAccentInsensitive) {
					strWord = CSearchStringListModel::decompose(strWord, bHyphenInsensitive);
				} else {
					strWord = CSearchStringListModel::deApostrHyphen(strWord, bHyphenInsensitive);
				}
				if (bCaseInsensitive) {
					strWord = strWord.toLower();
				}
				lstWordDiffs2.append(strWord);
			}
			qSort(lstWordDiffs2.begin(), lstWordDiffs2.end(), TWordDiffEntryListSortPredicate::ascendingLessThanWordCaseInsensitive);
			TWordDiffEntryList_removeDuplicates(lstWordDiffs2);

			TWordDiffEntryList::const_iterator itrWordEntry1 = lstWordDiffs1.constBegin();
			TWordDiffEntryList::const_iterator itrWordEntry2 = lstWordDiffs2.constBegin();
			while ((itrWordEntry1 != lstWordDiffs1.constEnd()) || (itrWordEntry2 != lstWordDiffs2.constEnd())) {
				bool bEOL1 = (itrWordEntry1 == lstWordDiffs1.constEnd());
				bool bEOL2 = (itrWordEntry2 == lstWordDiffs2.constEnd());
				QString strKeyWord1 = (!bEOL1 ? (itrWordEntry1->decomposedWord()) : QString());
				QString strKeyWord2 = (!bEOL2 ? (itrWordEntry2->decomposedWord()) : QString());
				QString strLookAhead1 = ((!bEOL1 && ((itrWordEntry1+1) != lstWordDiffs1.constEnd())) ? (itrWordEntry1+1)->decomposedWord() : QString());
				QString strLookAhead2 = ((!bEOL2 && ((itrWordEntry2+1) != lstWordDiffs2.constEnd())) ? (itrWordEntry2+1)->decomposedWord() : QString());

				int nComp = strKeyWord1.compare(strKeyWord2);
				if (nComp == 0) {
					assert(!strKeyWord1.isEmpty() && !strKeyWord2.isEmpty());
					if (itrWordEntry1->word() != itrWordEntry2->word()) {
						strWordDiffOutput += itrWordEntry1->word() + QString(" ").repeated(COLUMN_SPACE + nMaxWordSize - itrWordEntry1->word().size()) + itrWordEntry2->word() + "\n";
					}
					if ((!bEOL1) && ((strKeyWord1 != strLookAhead2) || (strLookAhead1 == strLookAhead2))) ++itrWordEntry1;
					if ((!bEOL2) && ((strKeyWord2 != strLookAhead1) || (strLookAhead1 == strLookAhead2))) ++itrWordEntry2;
				} else if (nComp < 0) {
					if (!strKeyWord1.isEmpty()) {
						strWordDiffOutput += itrWordEntry1->word() + "\n";
						if (!bEOL1) ++itrWordEntry1;
					} else if (!strKeyWord2.isEmpty()) {
						strWordDiffOutput += QString(" ").repeated(nMaxWordSize + COLUMN_SPACE) + itrWordEntry2->word() + "\n";
						if (!bEOL2) ++itrWordEntry2;
					}
				} else if (nComp > 0) {
					if (!strKeyWord2.isEmpty()) {
						strWordDiffOutput += QString(" ").repeated(nMaxWordSize + COLUMN_SPACE) + itrWordEntry2->word() + "\n";
						if (!bEOL2) ++itrWordEntry2;
					} else if (!strKeyWord1.isEmpty()) {
						strWordDiffOutput += itrWordEntry1->word() + "\n";
						if (!bEOL1) ++itrWordEntry1;
					}
				} else {
					// We can only be here if nothing is greater than something or we
					//		ran out of input on both sides and yet didn't exit the loop:
					assert(false);
				}
			}
		} else {
			TWordListMap::const_iterator itrWordEntry1 = pBible1->mapWordList().begin();
			TWordListMap::const_iterator itrWordEntry2 = pBible2->mapWordList().begin();
			while ((itrWordEntry1 != pBible1->mapWordList().end()) || (itrWordEntry2 != pBible2->mapWordList().end())) {
				bool bEOL1 = (itrWordEntry1 == pBible1->mapWordList().end());
				bool bEOL2 = (itrWordEntry2 == pBible2->mapWordList().end());
				QString strKeyWord1 = (!bEOL1 ? (itrWordEntry1->first) : QString());
				QString strKeyWord2 = (!bEOL2 ? (itrWordEntry2->first) : QString());

				int nComp = strKeyWord1.compare(strKeyWord2);
				if (nComp == 0) {
					assert(!strKeyWord1.isEmpty() && !strKeyWord2.isEmpty());
					if (!bEOL1) ++itrWordEntry1;
					if (!bEOL2) ++itrWordEntry2;
				} else if (nComp < 0) {
					if (!strKeyWord1.isEmpty()) {
						strWordDiffOutput += (itrWordEntry1->second).m_strWord + "\n";
						if (!bEOL1) ++itrWordEntry1;
					} else if (!strKeyWord2.isEmpty()) {
						strWordDiffOutput += QString(" ").repeated(nMaxWordSize + COLUMN_SPACE) + (itrWordEntry2->second).m_strWord + "\n";
						if (!bEOL2) ++itrWordEntry2;
					}
				} else if (nComp > 0) {
					if (!strKeyWord2.isEmpty()) {
						strWordDiffOutput += QString(" ").repeated(nMaxWordSize + COLUMN_SPACE) + (itrWordEntry2->second).m_strWord + "\n";
						if (!bEOL2) ++itrWordEntry2;
					} else if (!strKeyWord1.isEmpty()) {
						strWordDiffOutput += (itrWordEntry1->second).m_strWord + "\n";
						if (!bEOL1) ++itrWordEntry1;
					}
				} else {
					// We can only be here if nothing is greater than something or we
					//		ran out of input on both sides and yet didn't exit the loop:
					assert(false);
				}
			}
		}

		if (!strWordDiffOutput.isEmpty()) {
			if (bOutputedTextDiffs) {
				std::cout << QString("============================================================\n").toUtf8().data();
			}
			std::cout << strWordDiffOutput.toUtf8().data();
		}
	}

//	return a.exec();
	return 0;
}
Exemple #10
0
/**
 * trains the model using the patterns returned by the given query or the default query if none is given
 */
double Trainer::train(Optimizer& optimizer, ErrorFunction& errFct, size_t iterations) throw(MachineLearningException) {
	double error = 0;

	if(TRAINING_OUTPUT)
		writeHeader("Normal trainer", optimizer, errFct, iterations);

//		std::cout << "Query: \n" << query << std::endl;
	try {
		if(nFeatures() != model.getInputDimension() && model.iterativeTraining()) {
			std::cerr << "Number of features: " << nFeatures() << "\nModel input size: " << model.getInputDimension() << std::endl;
			throw MachineLearningException("Number of selected features is not equal to the model's input size");
		}

		Array<double> in, target;
		Array<double> out(model.getOutputDimension());

		size_t nRows = readDatabase(in, target);

		// do the actual training
		optimizer.init(model.getModel());

		// check if we are dealing with an svm, in this case the iterations argument is ignored
		if(SVM_Optimizer* svmOpt = dynamic_cast<SVM_Optimizer*>(&optimizer)){
			MyMultiClassSVM* csvm = dynamic_cast<MyMultiClassSVM*>(&model);
			MyEpsilon_SVM* esvm = dynamic_cast<MyEpsilon_SVM*>(&model);
			if(csvm) {
				optimizeDistorted(*svmOpt, csvm->getSVM(), errFct, in, target);
			} else if(esvm) {
				optimizeDistorted(*svmOpt, esvm->getSVM(), errFct, in, target);
			}
			assert_true(esvm || csvm) << "Trying to call SVM_Optimizer with a non Epsilon- or MultiClassSVM model";


			error = errFct.error(model.getModel(), in, target);
		}  else if(iterations != 0) {
			for(size_t i = 0; i < iterations; ++i) {
				optimizeDistorted(optimizer, model.getModel(), errFct, in, target);
				if(TRAINING_OUTPUT)
					writeStatistics(i, in, target, errFct, -1.0);
			}

			error = errFct.error(model.getModel(), in, target);
		} else
//			error = this->earlyStopping(optimizer, errFct, in, target, 10);
			error = this->myEarlyStopping(optimizer, errFct, in, target, 10, std::max(static_cast<size_t>(1),nRows/1000));

		size_t misClass = 0;
		for(size_t i = 0; i < in.dim(0); ++i ) {
			model.model(in.subarr(i,i), out);
//std::cout << in.subarr(i,i) << round(out(0)) << std::endl;
//std::cout << oneOfNtoIdx(target.subarr(i,i)) << " - " <<  oneOfNtoIdx(out) << std::endl;
			if(model.usesOneOfNCoding()) {
				if(oneOfNtoIdx(target.subarr(i,i)) != oneOfNtoIdx(out))
					++misClass;
			} else if(target.subarr(i,i)(0) != round(out(0)))
				++misClass;
		}
		LOG(INFO) << "Missclassification rate: " << (double(misClass)/in.dim(0)) * 100.0 << "%\n";

	} catch(Kompex::SQLiteException& sqle) {
		const std::string err = "\nSQL query for training data failed\n" ;
		LOG(ERROR) << err << std::endl;
		sqle.Show();
		throw ml::MachineLearningException(err);
	} catch(SharkException& se) {
		LOG(ERROR) << se.what() << std::endl;
		throw ml::MachineLearningException("Shark error");
	}catch (std::exception& exception) {
		const std::string err = "\nQuery for data failed\n" ;
		LOG(ERROR) << err << exception.what() << std::endl;
		throw ml::MachineLearningException(err);
	}

	return error;
}
Exemple #11
0
int main(int argc, char *argv[]){
  if (argc < 2){
    puts("Usage: db [FILE]");
    return -1;
  }
  Node list;
  list = readDatabase(argv[1]);

  puts("Welcome to");
  puts(" ____    ____       ");
  puts("/\\  _`\\ /\\  _`\\     ");
  puts("\\ \\ \\/\\ \\ \\ \\L\\ \\   ");
  puts(" \\ \\ \\ \\ \\ \\  _ <\\ ");
  puts("  \\ \\ \\_\\ \\ \\ \\L\\ \\ ");
  puts("   \\ \\____/\\ \\____/ ");
  puts("    \\/___/  \\/___/  ");
  puts("");

  
  // Main loop
  int choice = -1;
  while(choice != 0) {
    puts("Please choose an operation");
    puts("1. Query a key");
    puts("2. Update an entry");
    puts("3. New entry");
    puts("4. Remove entry");
    puts("5. Print database");
    puts("0. Exit database");
    printf("? ");
    scanf("%d", &choice);
    while(getchar() != '\n'); // Clear stdin
    //int found;
    // Node cursor;
    char buffer[128];
    switch(choice){
    case 1: //query
      queryDb(list, buffer);
     break;

    case 2: //update
      updateDb(list, buffer);
      break;

    case 3: //insert
      list = insertDb(list, buffer, buffer, 1);
      break;

    case 4: // Delete
      list = deleteDb(list, buffer);
      break;

    case 5: //print
      printDb(list);
      break;

    case 0: //Fel - prova igen
      // Exit
      puts("Good bye!");
      break;
    default:
      // Please try again
      puts("Could not parse choice! Please try again");
    }
    puts("");
  }
  return 0;
}
int main(int argc, char *argv[])
{
    static struct sockaddr_in ZERO_SOCKADDR;

    WSADATA w;
    struct sockaddr_in client, server = ZERO_SOCKADDR;
    SOCKADDR *c = (SOCKADDR *)&client;
    int cLen = (int)sizeof(struct sockaddr_in);
    int sd = 0;
    char *dbPath = NULL;
    unsigned short port = 0;
    User *head = NULL;
	char doLogin = FALSE;
	char doShutDown = FALSE;
	time_t currTime;
	int option = 0;
	char ipAddr[MAX_IP_LEN];
	char initialized = FALSE;

    // Test for correct number of arguments
    if (argc != 3)
    {
       usage();
       exit(0);
    }

    dbPath = argv[1];
    port = atoi(argv[2]);

    // Validate port number
    if (!port || port < 256 || port > 65535)
    {
        fprintf(stderr, "Invalid port number.\n");
        usage();
        exit(0);
    }
    
    // Open and parse the database file
    head = readDatabase(dbPath);
    if (!head)
        DieWithError("Error reading database file.\n");

    // Initialize Winsock
    if (WSAStartup(MAKEWORD(2, 0), &w))
        DieWithError("WSAStartup() failed.");

    // Open a datagram socket
    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sd == INVALID_SOCKET)
        DieWithError("Could not create socket.\n");

    // Clear out server struct
    server = ZERO_SOCKADDR;

    // Set family, port, and address
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    // Bind to the local address
    if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
    {
        closesocket(sd);
        DieWithError("bind() failed");
    }

    printf("\nWaiting for connection...\n\n");

    for (;;) // Run forever
    {
		char buffer[BUFFER_SIZE];
		User *clientUser;

		// Shut down the server if the flag is set
		if (doShutDown == TRUE)
			break;

		// Wait for client to send initial packet to confirm connection
		if (!doLogin && recvDecrypt(sd, buffer, BUFFER_SIZE, c, &cLen) == SOCKET_ERROR)
		{
			fprintf(stderr, "recvfrom() failed.\n");
			continue;
		}

		// Login on initial connection and if flag is set
		if(!strcmp(buffer, "connect") || doLogin)
		{
			// Get IP address if first transmission
			if (!initialized)
			{	
				recvDecrypt(sd, buffer, BUFFER_SIZE, c, &cLen);
				sscanf(buffer, "%s", &ipAddr);
			}

			// Loop until successful login
			while (!(clientUser = login(sd, c, cLen, head, ipAddr)))
				sendEncrypt(sd, "\nInvalid credentials. Please try again.\n", BUFFER_SIZE, 0, c, cLen);
			initialized = TRUE;
		}

		// Display successful login
		currTime = time(NULL);
        printf("%.24s : %s %s has logged in from %s.\n", ctime(&currTime), clientUser->firstName,
            clientUser->lastName, clientUser->ipAddr);

        sprintf(buffer, "\n\nLogin successful. Welcome, %s %s!\n",
            clientUser->firstName, clientUser->lastName);
        sendEncrypt(sd, buffer, BUFFER_SIZE, 0, c, cLen);

        sprintf(buffer, "User type: %s\n", clientUser->userType == 'C' ? "Customer" : "Manager");
        sendEncrypt(sd, buffer, BUFFER_SIZE, 0, c, cLen);

        if ((long long)clientUser->lastLogin > 0)
		    sprintf(buffer, "Last login: %.24s\n", ctime(&clientUser->lastLogin)); 
	    else
		    sprintf(buffer, "Last login: N/A\n");
	    sendEncrypt(sd, buffer, BUFFER_SIZE, 0, c, cLen);

		sprintf(buffer, "Last IP address: %s\n\n", clientUser->ipAddr);
        sendEncrypt(sd, buffer, BUFFER_SIZE, 0, c, cLen);

        // Set the last login time to the current time
        clientUser->lastLogin = currTime;

        // Initialize login flag
		doLogin = FALSE;

        while (doLogin == FALSE && doShutDown == FALSE)
        {
            // Print menu for correct user type
            switch(clientUser->userType) {

            case 'M': // Manager
                sendEncrypt(sd, "\nRequest Code\t Action\n\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "1\t\t Report balance of a selected customer\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "2\t\t Transfer money between two accounts\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "3\t\t Add a new customer to the system\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "4\t\t See the list of customers and their account information\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "5\t\t Report customer accounts sorted by balance\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "6\t\t See the total balance of all customers\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "7\t\t Shut down the server\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "8\t\t Logout\n", BUFFER_SIZE, 0, c, cLen);
                break;

            case 'C': // Customer
                sendEncrypt(sd, "Request Code\t Action\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "1\t\t Report balance of the customer\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "2\t\t Transfer money to another customer account\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "3\t\t Change password\n", BUFFER_SIZE, 0, c, cLen);
                sendEncrypt(sd, "4\t\t Logout\n", BUFFER_SIZE, 0, c, cLen);
                break;

            default:    // Shouldn't reach here since it loops until successful login.
                break;
            }

            sendEncrypt(sd, "\nPlease enter a Request Code: ", BUFFER_SIZE, 0, c, cLen);
            sendDone(sd, c, cLen);

            // Blocking wait for menu option from client
            if(recvDecrypt(sd, buffer, BUFFER_SIZE, c, &cLen) == (BUFFER_SIZE+1)) { doLogin = TRUE; continue; }

			// Get user input
			if (sscanf(buffer, "%d", &option) != 1)
				option = -1;

            // Perform appropriate action
            if (clientUser->userType == 'M')  // Manager
            {
                switch(option) {
                    case 1: if(seeBalanceSelected(sd, c, cLen, head) == -1){ doLogin = TRUE;} break;
                    case 2: if(transferBetweenAccounts(sd, c, cLen, head) == -1){ doLogin = TRUE;} break;
                    case 3: if(addNewCustomer(sd, c, cLen, &head) == -1){ doLogin = TRUE;} break;
                    case 4: listCustomers(sd, c, cLen, head); break;
                    case 5: sortByBalance(sd, c, cLen, &head); listCustomers(sd, c, cLen, head); break;
                    case 6: totalBalanceOfAll(sd, c, cLen, head); break;
                    case 7: doShutDown = TRUE; break;	// Sets flag to shut down server
                    case 8: doLogin = TRUE; break;		// Sets flag to loop back to login state
                    default: sendEncrypt(sd, "\n\nInvalid input. Please enter a valid option.\n\n", BUFFER_SIZE, 0, c, cLen); break;
                }
            }
            else if (clientUser->userType == 'C') // Customer
            {
                switch(option) {
                    case 1: seeUserBalance(sd, c, cLen, clientUser); break;
                    case 2: if(transferToCustomer(sd, c, cLen, clientUser, head) == -1){ doLogin = TRUE;} break;
                    case 3: if(changePassword(sd, c, cLen, clientUser) == -1){ doLogin = TRUE;} break;
                    case 4: doLogin = TRUE; break; // Sets flag to loop back to login state
                    default: sendEncrypt(sd, "\n\nInvalid input. Please enter a valid option.\n\n", BUFFER_SIZE, 0, c, cLen); break;
                }
            }
            else{}
        }
		// Reached when log out OR shut down flag is set to true
		sendEncrypt(sd, "\n\nLogging out.", BUFFER_SIZE, 0, c, cLen);
		currTime=time(NULL);
		printf("%.24s : %s %s has logged out.\n\n", ctime(&currTime), clientUser->firstName, clientUser->lastName);
		writeDatabase(dbPath, head);

		if (doShutDown == FALSE)
			sendEncrypt(sd, BORDER, BUFFER_SIZE, 0, c, cLen);
    }
    // Reached when shut down flag is set to true
	sendEncrypt(sd, BORDER, BUFFER_SIZE, 0, c, cLen);
	sendEncrypt(sd, "\nThe server has shut down. Client is closing. Thank you.\n\n", BUFFER_SIZE, 0, c, cLen);
	sendEncrypt(sd, "close", BUFFER_SIZE, 0, c, cLen);	// message to close the client
	printf("Server is shutting down by client request.\n\n");
}