#include "donationmanager.h" #include "udatabase.h" #include #include DonationManager::DonationManager(uDataBase *db, QObject *parent) : QObject(parent) , m_db(db) { } bool DonationManager::loadFromDatabase() { if (!m_db) return false; // Предполагаем, что в uDataBase есть метод loadAllDonationTriggers() m_triggers = m_db->loadAllDonationTriggers(); return true; } bool DonationManager::addTrigger(const QString &name, const QString &rule) { if (name.isEmpty() || rule.isEmpty()) return false; DonationTrigger trig; trig.name = name; trig.rule = rule; if (!parseRule(rule, trig)) { qWarning() << "Invalid rule:" << rule; return false; } // Сохраняем в БД (метод saveDonationTrigger должен вернуть id) int newId = m_db->saveDonationTrigger(trig); if (newId < 0) return false; trig.id = newId; m_triggers.append(trig); emit dataChanged(); return true; } bool DonationManager::deleteTrigger(int id) { if (!m_db->deleteDonationTrigger(id)) return false; for (int i = 0; i < m_triggers.size(); ++i) { if (m_triggers[i].id == id) { m_triggers.removeAt(i); break; } } emit dataChanged(); return true; } QList DonationManager::getAllTriggers() const { return m_triggers; } QString DonationManager::matchDonation(double amount) const { const DonationTrigger *best = nullptr; int bestPriority = 999; // чем меньше, тем выше приоритет for (const DonationTrigger &t : m_triggers) { bool ok = false; switch (t.priority) { case 1: // exact if (qFuzzyCompare(amount, t.minValue)) ok = true; break; case 2: // range if (amount >= t.minValue && amount <= t.maxValue) ok = true; break; case 3: // greater / greater-equal if (t.isGreaterEqual) { if (amount >= t.minValue) ok = true; } else { if (amount > t.minValue) ok = true; } break; default: continue; } if (ok) { // Сравниваем приоритет if (t.priority < bestPriority) { best = &t; bestPriority = t.priority; } // Если приоритет одинаковый, применяем дополнительные правила: else if (t.priority == bestPriority) { if (bestPriority == 2) { // Для диапазонов выбираем более узкий (меньше разница max-min) double bestRange = best->maxValue - best->minValue; double thisRange = t.maxValue - t.minValue; if (thisRange < bestRange) { best = &t; } } else if (bestPriority == 3) { // Для больше/больше-равно выбираем наибольшее пороговое значение (minValue) if (t.minValue > best->minValue) { best = &t; } } // Для exact приоритет 1 – только одно значение, совпадение уже есть. } } } return best ? best->name : QString(); } bool DonationManager::parseRule(const QString &rule, DonationTrigger &t) const { QString r = rule.trimmed(); if (r.isEmpty()) return false; // Точное равенство: =123 if (r.startsWith('=')) { QString numStr = r.mid(1); bool ok; double val = numStr.toDouble(&ok); if (!ok) return false; t.priority = 1; t.minValue = val; t.maxValue = val; return true; } // Диапазон: 100-200 if (r.contains('-')) { QStringList parts = r.split('-', Qt::SkipEmptyParts); if (parts.size() != 2) return false; bool ok1, ok2; double a = parts[0].toDouble(&ok1); double b = parts[1].toDouble(&ok2); if (!ok1 || !ok2 || a > b) return false; t.priority = 2; t.minValue = a; t.maxValue = b; return true; } // Больше/больше-равно if (r.startsWith(">=")) { QString numStr = r.mid(2); bool ok; double val = numStr.toDouble(&ok); if (!ok) return false; t.priority = 3; t.minValue = val; t.maxValue = 0; t.isGreaterEqual = true; return true; } if (r.startsWith('>')) { QString numStr = r.mid(1); bool ok; double val = numStr.toDouble(&ok); if (!ok) return false; t.priority = 3; t.minValue = val; t.maxValue = 0; t.isGreaterEqual = false; return true; } return false; }