File indexing completed on 2024-03-24 04:04:41
0001 /* 0002 This file is part of the KDE project "KAtomic" 0003 0004 SPDX-FileCopyrightText: 2006-2009 Dmitry Suzdalev <dimsuz@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "levelset.h" 0010 0011 #include "katomic_debug.h" 0012 #include "atom.h" 0013 #include "molecule.h" 0014 0015 #include <KConfigGroup> 0016 #include <KLocalizedString> 0017 0018 #include <QFileInfo> 0019 #include <QStandardPaths> 0020 0021 LevelData::LevelData(const QList<Element>& elements, const Molecule* mol) 0022 : m_molecule(mol) 0023 { 0024 memset(m_field, 0, sizeof(m_field)); 0025 m_atoms.reserve(elements.size()); 0026 for (const Element& el : elements) 0027 { 0028 if (el.atom == -1) 0029 { 0030 m_field[el.x][el.y] = true; // a wall 0031 } 0032 else 0033 { 0034 m_atoms.append(el); 0035 } 0036 } 0037 m_atoms.squeeze(); 0038 } 0039 0040 LevelData::~LevelData() 0041 { 0042 delete m_molecule; 0043 } 0044 0045 QList<LevelData::Element> LevelData::atomElements() const 0046 { 0047 return m_atoms; 0048 } 0049 0050 bool LevelData::containsWallAt(int x, int y) const 0051 { 0052 return m_field[x][y]; 0053 } 0054 0055 const Molecule* LevelData::molecule() const 0056 { 0057 return m_molecule; 0058 } 0059 0060 // ================================================== 0061 0062 LevelSet::LevelSet() 0063 { 0064 reset(); 0065 } 0066 0067 LevelSet::~LevelSet() 0068 { 0069 qDeleteAll(m_levelCache); 0070 } 0071 0072 void LevelSet::reset() 0073 { 0074 m_name = QString(); 0075 m_visibleName = QString(); 0076 m_description = QString(); 0077 m_author = QString(); 0078 m_authorEmail = QString(); 0079 m_levelCount = 0; 0080 0081 qDeleteAll(m_levelCache); 0082 m_levelCache.clear(); 0083 } 0084 0085 bool LevelSet::load(const QString& levelSetName) 0086 { 0087 QString file = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("levels/%1.dat").arg(levelSetName)); 0088 if (file.isEmpty()) 0089 { 0090 qCDebug(KATOMIC_LOG) << "level set \"" << levelSetName << "\" data file not found. Check your installation"; 0091 return false; 0092 } 0093 0094 bool res = loadFromFile(file); 0095 if (!res) { 0096 qCDebug(KATOMIC_LOG) << "warning: failed to load level set" << levelSetName; 0097 } 0098 0099 return res; 0100 } 0101 0102 bool LevelSet::loadFromFile(const QString& fileName) 0103 { 0104 reset(); 0105 0106 m_levelsFile = KSharedConfig::openConfig(fileName, KConfig::SimpleConfig); 0107 KConfigGroup gr = m_levelsFile->group(QStringLiteral("LevelSet")); 0108 0109 m_visibleName = gr.readEntry("Name"); 0110 m_description = gr.readEntry("Description"); 0111 m_author = gr.readEntry("Author"); 0112 m_authorEmail = gr.readEntry("AuthorEmail"); 0113 m_levelCount = gr.readEntry("LevelCount", 0); 0114 0115 m_name = QFileInfo(fileName).baseName(); 0116 0117 if (m_levelCount <= 0) { 0118 //qCDebug(KATOMIC_LOG) << "warning: in level set" << m_name << "level count not specified or invalid"; 0119 } 0120 0121 return true; 0122 } 0123 0124 QString LevelSet::name() const 0125 { 0126 return m_name; 0127 } 0128 0129 QString LevelSet::visibleName() const 0130 { 0131 return m_visibleName; 0132 } 0133 0134 QString LevelSet::author() const 0135 { 0136 return m_author; 0137 } 0138 0139 QString LevelSet::authorEmail() const 0140 { 0141 return m_authorEmail; 0142 } 0143 0144 QString LevelSet::description() const 0145 { 0146 return m_description; 0147 } 0148 0149 int LevelSet::levelCount() const 0150 { 0151 return m_levelCount; 0152 } 0153 0154 const LevelData* LevelSet::levelData(int levelNum) const 0155 { 0156 LevelData* data = m_levelCache.value(levelNum, nullptr); 0157 return data ? data : readLevel(levelNum); 0158 } 0159 0160 const LevelData* LevelSet::readLevel(int levelNum) const 0161 { 0162 KConfigGroup config = m_levelsFile->group(QStringLiteral("Level")+QString::number(levelNum)); 0163 0164 QList<LevelData::Element> elements; 0165 0166 elements.reserve(FIELD_SIZE * FIELD_SIZE); 0167 for (int j = 0; j < FIELD_SIZE; j++) 0168 { 0169 const QString key = QString::asprintf("feld_%02d", j); 0170 QString line = config.readEntry(key,QString()); 0171 0172 for (int i = 0; i < FIELD_SIZE; i++) 0173 { 0174 if (line.isEmpty()) 0175 { 0176 //qCDebug(KATOMIC_LOG) << "error while reading level" << levelNum << "data from" << m_name; 0177 return nullptr; 0178 } 0179 0180 QChar c = line.at(i); 0181 if( c == QLatin1Char('#') ) 0182 { 0183 LevelData::Element el; 0184 el.x = i; 0185 el.y = j; 0186 el.atom = -1; // indicates wall 0187 0188 elements.append(el); 0189 } 0190 else if (c != QLatin1Char('.'))//atom 0191 { 0192 LevelData::Element el; 0193 el.x = i; 0194 el.y = j; 0195 el.atom = atom2int(c.toLatin1()); 0196 0197 elements.append(el); 0198 } 0199 } 0200 } 0201 elements.squeeze(); 0202 0203 // Molecule object will be deleted by LevelData, it takes ownership 0204 LevelData* level = new LevelData(elements, readLevelMolecule(levelNum)); 0205 m_levelCache[levelNum] = level; 0206 0207 return level; 0208 } 0209 0210 const Molecule* LevelSet::readLevelMolecule(int levelNum) const 0211 { 0212 Molecule* mol = new Molecule(); 0213 KConfigGroup config = m_levelsFile->group(QStringLiteral("Level")+QString::number(levelNum)); 0214 0215 0216 atom current; 0217 0218 int atom_index = 1; 0219 QString value; 0220 while (true) { 0221 const QString key = QString::asprintf("atom_%c", int2atom(atom_index)); 0222 value = config.readEntry(key,QString()); 0223 if (value.isEmpty()) 0224 break; 0225 0226 current.obj = value.at(0).toLatin1(); 0227 value = value.mid(2); 0228 0229 strncpy(current.conn, value.toLatin1().constData(), sizeof(current.conn)); 0230 if (mol->m_atoms.indexOf(current) != -1) 0231 qCWarning(KATOMIC_LOG) 0232 << "OOOPS, duplicate atom definition in" << key; 0233 mol->m_atoms.append(current); 0234 atom_index++; 0235 } 0236 0237 QString line; 0238 0239 mol->m_width = 0; 0240 mol->m_height = 0; 0241 mol->m_weight = 0.0; 0242 0243 int max_i = -1; 0244 for (int j = 0; j < MOLECULE_SIZE; j++) { 0245 0246 const QString key = QString::asprintf("mole_%d", j); 0247 line = config.readEntry(key,QString()); 0248 0249 int max_non_null_i = -1; 0250 for (int i = 0; i < MOLECULE_SIZE; i++) 0251 { 0252 if (i >= line.size()) 0253 mol->m_molek[i][j] = 0; 0254 else 0255 { 0256 mol->m_molek[i][j] = atom2int(line.at(i).toLatin1()); 0257 mol->m_weight += mol->getAtom(mol->m_molek[i][j]).weight(); 0258 max_non_null_i = i; 0259 } 0260 } 0261 if( max_non_null_i != -1 ) 0262 mol->m_height++; 0263 max_i = qMax( max_i, max_non_null_i ); 0264 } 0265 0266 mol->m_width = max_i+1; 0267 0268 mol->m_name = i18n(config.readEntry("Name", i18n("Noname")).toUtf8().constData()); 0269 0270 return mol; 0271 } 0272 0273 bool LevelSet::isDefaultLevelsAvailable() 0274 { 0275 QString file = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("levels/%1.dat").arg(QLatin1String(DEFAULT_LEVELSET_NAME))); 0276 if (file.isEmpty()) 0277 { 0278 //qCDebug(KATOMIC_LOG) << "default level set \"" << DEFAULT_LEVELSET_NAME << "\" data file not found. Check your installation"; 0279 return false; 0280 } 0281 0282 return true; 0283 }