File indexing completed on 2024-05-12 05:40:40

0001 /***************************************************************************
0002  *   Copyright (C) 2015 by Renaud Guezennec                                *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 
0021 #include "namegeneratorwidget.h"
0022 #include "ui_namegeneratorwidget.h"
0023 #include <QDateTime>
0024 #include <QDebug>
0025 #include <QFile>
0026 #include <QJsonDocument>
0027 #include <QJsonObject>
0028 #include <stdlib.h>
0029 
0030 #define FName "FemaleName"
0031 #define MName "MaleName"
0032 #define LName "LastName"
0033 #define BothName "BothName"
0034 
0035 NameGeneratorWidget::NameGeneratorWidget(QWidget* parent)
0036     : QWidget(parent)
0037     , ui(new Ui::NameGeneratorWidget)
0038     , m_generator(quintptr(this) + QDateTime::currentDateTime().toMSecsSinceEpoch())
0039 {
0040     setWindowTitle(QStringLiteral("Name Generator"));
0041     setObjectName(QStringLiteral("NameGenerator"));
0042     ui->setupUi(this);
0043 
0044     m_model << tr("Chinese Name") << tr("Elve Name") << tr("English Name") << tr("French Name") << tr("Japanese Name")
0045             << tr("Star Wars Name") << tr("Russian Name");
0046     ui->m_database->addItems(m_model);
0047     connect(ui->m_database, SIGNAL(currentIndexChanged(int)), this, SLOT(checkFeatureAvailability()));
0048 
0049     connect(ui->m_gen, SIGNAL(clicked()), this, SLOT(generateName()));
0050 
0051     // Japanese
0052     DataBase jpMale;
0053     jpMale.filepath= ":/data/result_Name_Japanese_Male.txt";
0054     jpMale.gender= Male;
0055     jpMale.generate= true;
0056     jpMale.id= 0;
0057 
0058     DataBase jpFemale;
0059     jpFemale.filepath= ":/data/result_Name_Japanese_Female.txt";
0060     jpFemale.gender= Female;
0061     jpFemale.generate= true;
0062     jpFemale.id= 1;
0063 
0064     // Elves
0065     DataBase elveMale;
0066     elveMale.filepath= ":/data/result_Name_Elve_Male.txt";
0067     elveMale.gender= Male;
0068     elveMale.generate= true;
0069     elveMale.id= 2;
0070 
0071     DataBase elveFemale;
0072     elveFemale.filepath= ":/data/result_Name_Elve_Female.txt";
0073     elveFemale.gender= Female;
0074     elveFemale.generate= true;
0075     elveFemale.id= 3;
0076 
0077     // Chinese
0078     DataBase chineseMale;
0079     chineseMale.filepath= ":/data/result_Name_Chinese_Male.txt";
0080     chineseMale.gender= Male;
0081     chineseMale.generate= true;
0082     chineseMale.id= 4;
0083 
0084     DataBase chineseFemale;
0085     chineseFemale.filepath= ":/data/result_Name_Chinese_Female.txt";
0086     chineseFemale.gender= Female;
0087     chineseFemale.generate= true;
0088     chineseFemale.id= 5;
0089 
0090     // French
0091     DataBase frenchMale;
0092     frenchMale.filepath= ":/data/data_Name_French_Male.txt";
0093     frenchMale.gender= Male;
0094     frenchMale.generate= false;
0095     frenchMale.id= 6;
0096 
0097     DataBase frenchFemale;
0098     frenchFemale.filepath= ":/data/data_Name_French_Female.txt";
0099     frenchFemale.gender= Female;
0100     frenchFemale.generate= false;
0101     frenchFemale.id= 7;
0102 
0103     DataBase frenchName;
0104     frenchName.filepath= ":/data/data_Last_Name_French.txt";
0105     frenchName.gender= NONE;
0106     frenchName.generate= false;
0107     frenchName.id= 8;
0108 
0109     // star wars
0110     DataBase swBoth;
0111     swBoth.filepath= ":/data/result_Name_human_star_wars_Male.txt";
0112     swBoth.gender= BOTH;
0113     swBoth.generate= true;
0114     swBoth.id= 9;
0115 
0116     DataBase swName;
0117     swName.filepath= ":/data/result_Last_Name_human_star_wars_Male.txt";
0118     swName.gender= NONE;
0119     swName.generate= true;
0120     swName.id= 10;
0121 
0122     // Russian
0123     DataBase russianMale;
0124     russianMale.filepath= ":/data/datarussian_firstname_h.txt";
0125     russianMale.gender= Male;
0126     russianMale.generate= false;
0127     russianMale.id= 11;
0128 
0129     DataBase russianFemale;
0130     russianFemale.filepath= ":/data/datarussian_firstname_w.txt";
0131     russianFemale.gender= Female;
0132     russianFemale.generate= false;
0133     russianFemale.id= 12;
0134 
0135     DataBase russianName;
0136     russianName.filepath= ":/data/result_last_name_russian.txt";
0137     russianName.gender= NONE;
0138     russianName.generate= true;
0139     russianName.id= 13;
0140 
0141     // English
0142     DataBase englishMale;
0143     englishMale.filepath= ":/data/data_Name_English_Male.txt";
0144     englishMale.gender= Male;
0145     englishMale.generate= false;
0146     englishMale.id= 14;
0147 
0148     DataBase englishFemale;
0149     englishFemale.filepath= ":/data/data_Name_English_Female.txt";
0150     englishFemale.gender= Female;
0151     englishFemale.generate= false;
0152     englishFemale.id= 15;
0153 
0154     DataBase englishName;
0155     englishName.filepath= ":/data/lastName_english.txt";
0156     englishName.gender= NONE;
0157     englishName.generate= false;
0158     englishName.id= 16;
0159 
0160     // database
0161     QHash<QString, DataBase> chineseDataBase;
0162     chineseDataBase.insert(MName, chineseMale);
0163     chineseDataBase.insert(FName, chineseFemale);
0164 
0165     QHash<QString, DataBase> swDataBase;
0166     swDataBase.insert(BothName, swBoth);
0167     swDataBase.insert(LName, swName);
0168 
0169     QHash<QString, DataBase> elveDataBase;
0170     elveDataBase.insert(MName, elveMale);
0171     elveDataBase.insert(FName, elveFemale);
0172 
0173     QHash<QString, DataBase> jpnDataBase;
0174     jpnDataBase.insert(MName, jpMale);
0175     jpnDataBase.insert(FName, jpFemale);
0176 
0177     // create french database
0178     QHash<QString, DataBase> FrenchDataBase;
0179     FrenchDataBase.insert(MName, frenchMale);
0180     FrenchDataBase.insert(FName, frenchFemale);
0181     FrenchDataBase.insert(LName, frenchName);
0182 
0183     // russian
0184     QHash<QString, DataBase> russianDataBase;
0185     russianDataBase.insert(MName, russianMale);
0186     russianDataBase.insert(FName, russianFemale);
0187     russianDataBase.insert(LName, russianName);
0188 
0189     QHash<QString, DataBase> englishDataBase;
0190     englishDataBase.insert(MName, englishMale);
0191     englishDataBase.insert(FName, englishFemale);
0192     englishDataBase.insert(LName, englishName);
0193 
0194     // inserting databases
0195     m_complexName.insert(Japanese, jpnDataBase);
0196     m_complexName.insert(Chinese, chineseDataBase);
0197     m_complexName.insert(Elves, elveDataBase);
0198     m_complexName.insert(French, FrenchDataBase);
0199     m_complexName.insert(StarWars, swDataBase);
0200     m_complexName.insert(Russian, russianDataBase);
0201     m_complexName.insert(English, englishDataBase);
0202 
0203     checkFeatureAvailability();
0204 }
0205 
0206 NameGeneratorWidget::~NameGeneratorWidget()
0207 {
0208     delete ui;
0209 }
0210 
0211 void NameGeneratorWidget::buildAllNames(int count, QHash<QString, DataBase> data)
0212 {
0213     QList<DataBase> list;
0214     if((ui->m_femaleBtn->isChecked()) && (ui->m_femaleBtn->isEnabled()))
0215     {
0216         list << data.value(FName);
0217     }
0218     else if((ui->m_maleBtn->isChecked()) && (ui->m_maleBtn->isEnabled()))
0219     {
0220         list << data.value(MName);
0221     }
0222     else
0223     {
0224         list << data.value(BothName);
0225     }
0226     if(ui->m_complexName->isChecked())
0227     {
0228         list << data.value(LName);
0229     }
0230     QList<QJsonDocument> generationData;
0231     QList<QStringList> pickUpData;
0232 
0233     for(auto& database : list)
0234     {
0235         QFile loadFile(database.filepath);
0236 
0237         if(!loadFile.open(QIODevice::ReadOnly))
0238         {
0239             qWarning("Couldn't open save file.");
0240             return;
0241         }
0242         if(database.generate)
0243         {
0244             QByteArray saveData= loadFile.readAll();
0245 
0246             QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
0247             generationData.append(loadDoc);
0248         }
0249         else
0250         {
0251             QTextStream in(&loadFile);
0252 
0253             QStringList strData;
0254             while(!in.atEnd())
0255             {
0256                 strData << in.readLine();
0257             }
0258 
0259             pickUpData.append(strData);
0260         }
0261     }
0262     int maxTry= 30;
0263     for(int i= 0; i < count; ++i)
0264     {
0265         int indexGenerated= 0;
0266         int indexPickUp= 0;
0267         QString result("");
0268         for(auto& database : list)
0269         {
0270             QString tmpresult;
0271 
0272             if(database.generate)
0273             {
0274                 QJsonObject json= generationData.at(indexGenerated).object();
0275                 do
0276                 {
0277                     --maxTry;
0278                     tmpresult= buildName(json);
0279                 } while(tmpresult.size() < 2 && maxTry > 0);
0280                 ++indexGenerated;
0281             }
0282             else
0283             {
0284                 do
0285                 {
0286                     --maxTry;
0287                     tmpresult= pickUpName(pickUpData.at(indexPickUp));
0288                 } while(tmpresult.size() < 2 && maxTry > 0);
0289                 ++indexPickUp;
0290             }
0291 
0292             result+= QString("%1 ").arg(tmpresult);
0293         }
0294         ui->m_result->append(result);
0295     }
0296 }
0297 
0298 void NameGeneratorWidget::generateName()
0299 {
0300     ui->m_result->clear();
0301     int i= ui->m_database->currentIndex() * 2;
0302     if(ui->m_femaleBtn->isChecked())
0303     {
0304         ++i;
0305     }
0306     TypeOfGeneration index= (TypeOfGeneration)ui->m_database->currentIndex();
0307 
0308     QHash<QString, DataBase> data= m_complexName.value(index);
0309 
0310     buildAllNames(ui->m_nameCount->value(), data);
0311 }
0312 QString NameGeneratorWidget::pickUpName(QStringList data)
0313 {
0314     if(data.isEmpty())
0315         return QString();
0316     int len= m_generator.bounded(data.size());
0317 
0318     if(data.size() > len)
0319         return data.at(len);
0320     else
0321         return QString();
0322 }
0323 
0324 QString NameGeneratorWidget::buildName(const QJsonObject& json)
0325 {
0326     int len= m_generator.bounded(10) + 2;
0327     QString result;
0328     QJsonObject firstLetter= json["firstLetter"].toObject();
0329     qreal first= m_generator.generateDouble(); // / std::numeric_limits<qreal>::digits;
0330     qreal sum= 0;
0331 
0332     auto keys= firstLetter.keys();
0333     for(auto& key : keys)
0334     {
0335         sum+= firstLetter[key].toDouble();
0336         if((sum > first) && (result.isEmpty()))
0337         {
0338             result= key;
0339         }
0340     }
0341     int rLen= len - 1; // already find the first character.
0342 
0343     for(int index= 0; index < rLen; ++index)
0344     {
0345         bool lastIndex= result.size() + 1 == len ? true : false;
0346         bool beforeLast= ((result.size() + 2) == len) ? true : false;
0347         QString duo;
0348         if(result.count() == 1)
0349         {
0350             duo= "0" + result;
0351         }
0352         else
0353         {
0354             duo= result.right(2);
0355         }
0356 
0357         QJsonObject dataJson= json["data"].toObject();
0358         QJsonObject duoJson= dataJson[duo.toLower()].toObject();
0359         QString lastestChar= result.right(1);
0360 
0361         if(lastIndex)
0362         {
0363             dataJson= json["lastLetter"].toObject();
0364             duoJson= dataJson[duo.toLower()].toObject();
0365         }
0366 
0367         QJsonObject::iterator i;
0368         int sumDict= 0;
0369         for(i= duoJson.begin(); i != duoJson.end(); ++i)
0370         {
0371             if(i.key() != "0")
0372             {
0373                 if(nextIsPossible(json, QStringLiteral("%1%2").arg(lastestChar, i.key()), beforeLast))
0374                 {
0375                     sumDict+= i.value().toInt();
0376                 }
0377             }
0378         }
0379         if(sumDict > 0)
0380         {
0381             int value= m_generator.bounded(sumDict);
0382             sumDict= 0;
0383             bool unfound= true;
0384             for(i= duoJson.begin(); i != duoJson.end() && unfound; ++i)
0385             {
0386                 if(i.key() != "0")
0387                 {
0388                     if(nextIsPossible(json, QStringLiteral("%1%2").arg(lastestChar, i.key()), beforeLast))
0389                     {
0390                         sumDict+= i.value().toInt();
0391                         if(sumDict > value)
0392                         {
0393                             result.append(i.key());
0394                             unfound= false;
0395                         }
0396                     }
0397                 }
0398             }
0399         }
0400     }
0401     return result;
0402 }
0403 bool NameGeneratorWidget::nextCharacterCanEnd(const QJsonObject& json, QString key)
0404 {
0405     QJsonObject dataJson= json["lastLetter"].toObject();
0406     if(dataJson[key.toLower()].isUndefined())
0407     {
0408         return false;
0409     }
0410     else
0411     {
0412         return true;
0413     }
0414 }
0415 void NameGeneratorWidget::checkFeatureAvailability()
0416 {
0417     TypeOfGeneration index= (TypeOfGeneration)ui->m_database->currentIndex();
0418 
0419     QHash<QString, DataBase> data= m_complexName.value(index);
0420     if(!data.contains(LName))
0421     {
0422         ui->m_complexName->setChecked(false);
0423         ui->m_complexName->setEnabled(false);
0424     }
0425     else
0426     {
0427         ui->m_complexName->setEnabled(true);
0428     }
0429 
0430     if(data.contains(FName))
0431     {
0432         ui->m_femaleBtn->setEnabled(true);
0433     }
0434     else
0435     {
0436         ui->m_femaleBtn->setEnabled(false);
0437         ui->m_femaleBtn->setChecked(false);
0438     }
0439     if(data.contains(MName))
0440     {
0441         ui->m_maleBtn->setEnabled(true);
0442     }
0443     else
0444     {
0445         ui->m_maleBtn->setEnabled(false);
0446         ui->m_maleBtn->setChecked(false);
0447     }
0448 }
0449 
0450 bool NameGeneratorWidget::nextIsPossible(const QJsonObject& json, QString key, bool last)
0451 {
0452     if(last)
0453     {
0454         return nextCharacterCanEnd(json, key);
0455     }
0456     QJsonObject dataJson= json["data"].toObject();
0457     if(dataJson[key.toLower()].isUndefined())
0458     {
0459         return false;
0460     }
0461     else
0462     {
0463         return true;
0464     }
0465 }