154 lines
6 KiB
C++
154 lines
6 KiB
C++
|
//
|
||
|
// Created by trotfunky on 02/10/2021.
|
||
|
//
|
||
|
|
||
|
#include "LicenceOperations.h"
|
||
|
|
||
|
void dbError(const std::string& errorMessage, char* dbError) {
|
||
|
std::cerr << errorMessage << " : " << std::endl << dbError << std::endl;
|
||
|
sqlite3_free(dbError);
|
||
|
}
|
||
|
|
||
|
int addNewLicence(sqlite3* db, const std::string& licenceID) {
|
||
|
// Shift the hash two places down to fit properly in an SQLite integer
|
||
|
std::string idHash = std::to_string(std::hash<std::string>{}(licenceID) >> 2);
|
||
|
char* errorMessage = nullptr;
|
||
|
int errorCode;
|
||
|
errorCode = sqlite3_exec(db, ("INSERT INTO " + pointsTable + " VALUES (" + idHash
|
||
|
+ ", '" + licenceID + "', 12, 0, 0, 0, 0);").c_str(),
|
||
|
nullptr, nullptr, &errorMessage);
|
||
|
|
||
|
if (errorCode) {
|
||
|
dbError("Error adding new licence with ID " + licenceID, errorMessage);
|
||
|
}
|
||
|
|
||
|
return errorCode;
|
||
|
}
|
||
|
|
||
|
int applyOffence(sqlite3* db, const std::string& licenceID, int lostPoints, offenceClass offenceClass) {
|
||
|
// Shift the hash two places down to fit properly in an SQLite integer
|
||
|
std::string idHash = std::to_string(std::hash<std::string>{}(licenceID) >> 2);
|
||
|
char* errorMessage = nullptr;
|
||
|
int errorCode;
|
||
|
char** licenceInfo = nullptr;
|
||
|
|
||
|
// Retrieve points and grave offence info, that's all we need.
|
||
|
errorCode = sqlite3_get_table(db, ("SELECT " + pointsColumn + "," + graveOffenceColumn + ", " + onePointCountdownColumn
|
||
|
+ " FROM " + pointsTable + " WHERE " + keyColumn + " = " + idHash + ";").c_str(),
|
||
|
&licenceInfo, nullptr, nullptr, &errorMessage);
|
||
|
if (errorCode) {
|
||
|
dbError("Error getting info for licence " + licenceID, errorMessage);
|
||
|
return errorCode;
|
||
|
}
|
||
|
|
||
|
int points = std::stoi(licenceInfo[3]);
|
||
|
bool hasGraveOffence = std::stoi(licenceInfo[4]);
|
||
|
// Can only change from false to true for offences of class 4 or 5
|
||
|
bool newGraveOffence = offenceClass > offenceClass::Three && !hasGraveOffence;
|
||
|
|
||
|
int newTenYearCountdown = -1;
|
||
|
// Only set for the first new offence when at maximum points, clears if class five offence
|
||
|
if (points == 12 && offenceClass < offenceClass::Five) {
|
||
|
newTenYearCountdown = 3653;
|
||
|
} else if (offenceClass == offenceClass::Five) {
|
||
|
newTenYearCountdown = 0;
|
||
|
}
|
||
|
|
||
|
int newCountdown;
|
||
|
int onePointCountdown = std::stoi(licenceInfo[5]);
|
||
|
int newOnePointCountdown = -1;
|
||
|
// This minimizes affected rows for one point offences when it's the first offence at maximum points.
|
||
|
// Not sure if that's useful.
|
||
|
if (lostPoints == 1 && points == 12) {
|
||
|
newCountdown = 183;
|
||
|
} else {
|
||
|
newCountdown = (2 + (hasGraveOffence || newGraveOffence)) * 365;
|
||
|
if (lostPoints == 1) {
|
||
|
newOnePointCountdown = 183;
|
||
|
} else if (onePointCountdown) {
|
||
|
newOnePointCountdown = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
points -= lostPoints;
|
||
|
// Licence is revoked, reset everything.
|
||
|
if (points <= 0) {
|
||
|
points = 0;
|
||
|
newCountdown = 0;
|
||
|
newOnePointCountdown = 0;
|
||
|
newTenYearCountdown = 0;
|
||
|
}
|
||
|
|
||
|
errorCode = sqlite3_exec(
|
||
|
db, ("UPDATE " + pointsTable + " SET "
|
||
|
+ pointsColumn + " = " + std::to_string(points) + ", "
|
||
|
+ countdownColumn + " = " + std::to_string(newCountdown)
|
||
|
+ (newOnePointCountdown >= 0 ? ", " + onePointCountdownColumn + " = " + std::to_string(newOnePointCountdown) : "")
|
||
|
+ (newTenYearCountdown >= 0 ? ", " + tenYearsCountdownColumn + " = " + std::to_string(newTenYearCountdown) : "")
|
||
|
+ (newGraveOffence ? ", " + graveOffenceColumn + " = 1" : "")
|
||
|
+ " WHERE " + keyColumn + " = " + idHash + ";").c_str(),
|
||
|
nullptr, nullptr, &errorMessage);
|
||
|
|
||
|
if (errorCode) {
|
||
|
dbError("Error updating licence " + licenceID, errorMessage);
|
||
|
}
|
||
|
|
||
|
return errorCode;
|
||
|
}
|
||
|
|
||
|
int countdown(void* db, int columnCount, char** rowData, char** columnNames) {
|
||
|
char* errorMessage = nullptr;
|
||
|
int errorCode;
|
||
|
|
||
|
int points = std::stoi(rowData[1]);
|
||
|
int newPoints = -1;
|
||
|
int countdown = std::stoi(rowData[2]);
|
||
|
int onePointCoutdown = std::stoi(rowData[3]);
|
||
|
int tenYearCountdown = std::stoi(rowData[4]);
|
||
|
|
||
|
if (tenYearCountdown == 1 || countdown == 1) {
|
||
|
// If resetting the counters, don't do anything else
|
||
|
return reset((sqlite3*)db, rowData[0]);
|
||
|
} else if (onePointCoutdown == 1) {
|
||
|
newPoints = points + 1;
|
||
|
}
|
||
|
|
||
|
countdown -= 1;
|
||
|
onePointCoutdown -= 1;
|
||
|
tenYearCountdown -= 1;
|
||
|
|
||
|
errorCode = sqlite3_exec(
|
||
|
(sqlite3*)db, ("UPDATE " + pointsTable + " SET "
|
||
|
+ countdownColumn + " = " + std::to_string(countdown)
|
||
|
+ (newPoints >= 0 ? ", " + pointsColumn + " = " + std::to_string(newPoints) : "")
|
||
|
+ (onePointCoutdown >= 0 ? ", " + onePointCountdownColumn + " = " + std::to_string(onePointCoutdown) : "")
|
||
|
+ (tenYearCountdown >= 0 ? ", " + tenYearsCountdownColumn + " = " + std::to_string(tenYearCountdown) : "")
|
||
|
+ " WHERE " + keyColumn + " = " + rowData[0]).c_str(),
|
||
|
nullptr, nullptr, &errorMessage);
|
||
|
|
||
|
if (errorCode) {
|
||
|
dbError("Error while updating coutdowns for licence hash " + std::string(rowData[0]), errorMessage);
|
||
|
}
|
||
|
|
||
|
return errorCode;
|
||
|
}
|
||
|
|
||
|
int reset(sqlite3* db, const std::string& idHash) {
|
||
|
char* errorMessage = nullptr;
|
||
|
int errorCode;
|
||
|
|
||
|
errorCode = sqlite3_exec(db, ("UPDATE " + pointsTable + " SET "
|
||
|
+ pointsColumn + " = 12, "
|
||
|
+ countdownColumn + " = 0,"
|
||
|
+ onePointCountdownColumn + " = 0,"
|
||
|
+ tenYearsCountdownColumn + " = 0,"
|
||
|
+ " WHERE " + keyColumn + " = " + idHash).c_str(),
|
||
|
nullptr, nullptr, &errorMessage);
|
||
|
|
||
|
if (errorCode) {
|
||
|
dbError("Error resetting licence " + idHash, errorMessage);
|
||
|
}
|
||
|
|
||
|
return errorCode;
|
||
|
}
|