Basic demonstrator
Works fine but can be slow, especially because of heavy IO.
This commit is contained in:
commit
afe832654d
8 changed files with 414 additions and 0 deletions
153
LicenceOperations.cpp
Normal file
153
LicenceOperations.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue