MainOptHandler help
This commit is contained in:
parent
089e9115f1
commit
365b24e651
12
.idea/dataSources.xml
generated
Normal file
12
.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="budget.sqlite" uuid="bba32b4d-f424-4d0f-8ee6-c6e2f73d9010">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/.local/share/budget/budget.sqlite</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
6
.idea/discord.xml
generated
Normal file
6
.idea/discord.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
</component>
|
||||
</project>
|
@ -3,16 +3,5 @@ project(budget)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(${PROJECT_NAME} src/main.cpp src/main.h
|
||||
src/money/account.cpp src/money/account.h
|
||||
src/money/payment.cpp src/money/payment.h
|
||||
src/money/recept.cpp src/money/recept.h
|
||||
src/data/data.tpp src/data/data.h
|
||||
src/data/accountData.cpp src/data/accountData.h
|
||||
src/money/earning.cpp src/money/earning.h
|
||||
src/data/dateMoney.cpp src/data/dateMoney.h
|
||||
src/optHandlers/optHandler.cpp src/optHandlers/optHandler.h
|
||||
src/optHandlers/accountOptHandler.cpp src/optHandlers/accountOptHandler.h
|
||||
src/optHandlers/mainOptHandler.cpp src/optHandlers/mainOptHandler.h
|
||||
utilities/math.cpp utilities/math.h
|
||||
utilities/polynomialFunction.cpp utilities/polynomialFunction.h src/money/transaction.cpp src/money/transaction.h)
|
||||
add_executable(${PROJECT_NAME} src/main.cpp
|
||||
src/optHandlers/mainOptHandler.h src/optHandlers/mainOptHandler.cpp)
|
||||
|
41
README.md
Normal file
41
README.md
Normal file
@ -0,0 +1,41 @@
|
||||
Output of budget.
|
||||
```
|
||||
Usage:
|
||||
|
||||
budget <action> [options] ...
|
||||
Actions:
|
||||
-h --help Prints this.
|
||||
-a --account<=STRING> Management tools for an account.
|
||||
-c --create<=STRING> Creates a new account with NAME.
|
||||
-e --earn<=STRING> Add an earning to an account.
|
||||
-p --payment<=STRING> Add a payment to an account.
|
||||
Account Options: [-dDv]
|
||||
-d --delete Deletes specified account.
|
||||
--force-delete Deletes the specified account without confirmation.
|
||||
-v --value Gets the current value of the account.
|
||||
-D --description Changes the description of the account.
|
||||
Create Options: [-d]
|
||||
-d --description Sets a description for an account.
|
||||
Earn Options: -v [-drD]
|
||||
-v --value=<FlOAT> Value for earning.
|
||||
-d --description=<STRING> Description for earning.
|
||||
-r --receipt=<PATH> Path to file to store in DB as receipt.
|
||||
-D --date=<dd/mm/yyyy> Date as dd/mm/yyyy. Default will be today.
|
||||
-t --time=<hh/mm/ss> 24 hour time as hh/mm/ss. Default will be now.
|
||||
Payment Options: -v [-drD]
|
||||
-v --value=<FlOAT> Value for payment.
|
||||
-d --description=<STRING> Description for payment.
|
||||
-r --receipt=<PATH> Path to file to store in DB as receipt.
|
||||
-D --date=<NUM/NUM/NUM> Date as dd/mm/yyyy. Default will be today.
|
||||
-t --time=<hh/mm/ss> 24 hour time as hh/mm/ss. Default will be now.
|
||||
```
|
||||
|
||||
Arguments are processed like blocks with each one terminated by the next Action. For example
|
||||
```
|
||||
budget -cAcct -eAcct -v10.00 -r"./receipt.pdf" -pAcct -v5.50 -r"./payment.pdf"
|
||||
```
|
||||
Does the following in order:
|
||||
1. Creates an account named ``Acct`` with no description.
|
||||
2. Earns ``10.00`` to it with a receipt.
|
||||
3. Pays ``5.50`` to it with a receipt.
|
||||
|
@ -1,99 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#include "accountData.h"
|
||||
#include <iostream>
|
||||
|
||||
AccountData::AccountData(const std::string &file) : Data(file) {
|
||||
account = AccountData::createObject();
|
||||
}
|
||||
|
||||
AccountData::AccountData(const std::string &file, const std::string &name) : Data(file) {
|
||||
std::string json = R"({"name":")" + name + R"(","payments":[],"earnings":[]})";
|
||||
document.Parse(json.c_str());
|
||||
account = AccountData::createObject();
|
||||
std::cout << "Created account " << name << std::endl;
|
||||
}
|
||||
|
||||
Account AccountData::createObject() {
|
||||
if (isJsonCorrect()) {
|
||||
std::string name = document["name"].GetString();
|
||||
|
||||
std::list<Payment> payments;
|
||||
for (auto &domPayment : document["payments"].GetArray()) {
|
||||
Receipt receipt(domPayment["receipt"]["file"].GetString());
|
||||
double value = domPayment["value"].GetDouble();
|
||||
std::time_t date = domPayment["date"].GetInt64();
|
||||
std::tm tmTime{};
|
||||
std::memcpy(&tmTime, std::localtime(&date), sizeof(struct tm));
|
||||
|
||||
payments.emplace_back(value, receipt, tmTime);
|
||||
}
|
||||
|
||||
std::list<Earning> earnings;
|
||||
for (auto &domEarning : document["earnings"].GetArray()) {
|
||||
double value = domEarning["value"].GetDouble();
|
||||
std::time_t date = domEarning["date"].GetInt64();
|
||||
std::tm tmTime{};
|
||||
std::memcpy(&tmTime, std::localtime(&date), sizeof(struct tm));
|
||||
|
||||
earnings.emplace_back(value, tmTime);
|
||||
}
|
||||
|
||||
return Account(payments, earnings, name);
|
||||
}
|
||||
|
||||
std::string strAnswer;
|
||||
bool answer;
|
||||
while (true) {
|
||||
std::cout << "Account " + getFilePath() + " Is malformed, would you like to remove it? (Y/n): ";
|
||||
std::cin >> strAnswer;
|
||||
std::transform(strAnswer.begin(), strAnswer.end(), strAnswer.begin(), ::toupper);
|
||||
if (strAnswer == "Y" || strAnswer == "YES") {
|
||||
answer = true;
|
||||
break;
|
||||
}
|
||||
if (strAnswer == "N" || strAnswer == "NO") {
|
||||
answer = false;
|
||||
break;
|
||||
}
|
||||
std::cout << "Sorry, answer " + strAnswer + " not understood." << std::endl;
|
||||
}
|
||||
|
||||
return Account();
|
||||
}
|
||||
|
||||
bool AccountData::isJsonCorrect() {
|
||||
if (document.IsObject() &&
|
||||
document.HasMember("name") && document["name"].IsString() &&
|
||||
document.HasMember("payments") && document["payments"].IsArray() &&
|
||||
document.HasMember("earnings") && document["earnings"].IsArray()) {
|
||||
for (auto &domPayment : document["payments"].GetArray()) {
|
||||
if (!(domPayment.IsObject() &&
|
||||
domPayment.HasMember("receipt") && domPayment["receipt"].IsObject() &&
|
||||
domPayment["receipt"].HasMember("file") && domPayment["receipt"]["file"].IsString() &&
|
||||
domPayment.HasMember("value") && domPayment["value"].IsDouble() &&
|
||||
domPayment.HasMember("date") && domPayment["date"].IsInt64())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto &domEarning : document["earnings"].GetArray()) {
|
||||
if (!(domEarning.IsObject() &&
|
||||
domEarning.HasMember("value") && domEarning["value"].IsDouble() &&
|
||||
domEarning.HasMember("date") && domEarning["date"].IsInt64())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Account *AccountData::getAccount() {
|
||||
return &account;
|
||||
}
|
||||
|
||||
AccountData::AccountData() : Data("/dev/null") {}
|
@ -1,36 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_ACCOUNTDATA_H
|
||||
#define BUDGET_ACCOUNTDATA_H
|
||||
|
||||
|
||||
#include "data.h"
|
||||
#include "../money/account.h"
|
||||
|
||||
static const char *jsonTemplate = "";
|
||||
|
||||
class AccountData : private Data<Account> {
|
||||
public:
|
||||
AccountData();
|
||||
|
||||
AccountData(const AccountData &) = default;
|
||||
|
||||
explicit AccountData(const std::string &file);
|
||||
|
||||
explicit AccountData(const std::string &file, const std::string &name);
|
||||
|
||||
Account *getAccount();
|
||||
|
||||
using Data<Account>::deleteObject;
|
||||
private:
|
||||
Account account;
|
||||
|
||||
Account createObject() override;
|
||||
|
||||
bool isJsonCorrect() override;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_ACCOUNTDATA_H
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_DATA_H
|
||||
#define BUDGET_DATA_H
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
template<class T>
|
||||
class Data {
|
||||
public:
|
||||
rapidjson::Document document;
|
||||
|
||||
virtual ~Data();
|
||||
|
||||
Data(const Data &data);
|
||||
|
||||
explicit Data(std::string file);
|
||||
|
||||
virtual T createObject() = 0;
|
||||
|
||||
std::string getFilePath();
|
||||
|
||||
void flushToFile();
|
||||
|
||||
void deleteObject();
|
||||
|
||||
private:
|
||||
const std::string fileName;
|
||||
const std::string homeDirectory = getpwuid(getuid())->pw_dir;
|
||||
std::string fileDirectory;
|
||||
bool flush = true;
|
||||
|
||||
virtual bool isJsonCorrect() = 0;
|
||||
};
|
||||
|
||||
#include "data.tpp"
|
||||
|
||||
#endif //BUDGET_DATA_H
|
@ -1,85 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
|
||||
#include "data.h"
|
||||
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
#include <rapidjson/writer.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
template<class T>
|
||||
Data<T>::Data(std::string file) : fileName(std::move(file)) {
|
||||
// Create file if it doesnt exist
|
||||
std::ifstream chkExistIfs(getFilePath(), std::ios::in | std::ios::binary | std::ios::ate);
|
||||
if (chkExistIfs) {
|
||||
// File exists, were not creating one
|
||||
std::ifstream::pos_type fileSize = chkExistIfs.tellg();
|
||||
chkExistIfs.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> bytes(fileSize);
|
||||
chkExistIfs.read(bytes.data(), fileSize);
|
||||
|
||||
document.Parse(std::string(bytes.data(), fileSize).c_str());
|
||||
chkExistIfs.close();
|
||||
} else {
|
||||
// File doesnt exist we need to create one
|
||||
// This is the job of the derives constructor.
|
||||
chkExistIfs.close();
|
||||
};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::string Data<T>::getFilePath() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Data<T>::flushToFile() {
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
document.Accept(writer);
|
||||
|
||||
std::ofstream file(getFilePath());
|
||||
file << buffer.GetString();
|
||||
file.close();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Data<T>::~Data() {
|
||||
if (flush) {
|
||||
flushToFile();
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Data<T>::deleteObject() {
|
||||
remove(getFilePath().c_str());
|
||||
flush = false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Data<T>::Data(const Data &data) : fileName(data.fileName) {
|
||||
// Create file if it doesnt exist
|
||||
std::ifstream chkExistIfs(getFilePath(), std::ios::in | std::ios::binary | std::ios::ate);
|
||||
if (chkExistIfs) {
|
||||
// File exists, were not creating one
|
||||
std::ifstream::pos_type fileSize = chkExistIfs.tellg();
|
||||
chkExistIfs.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> bytes(fileSize);
|
||||
chkExistIfs.read(bytes.data(), fileSize);
|
||||
|
||||
document.Parse(std::string(bytes.data(), fileSize).c_str());
|
||||
chkExistIfs.close();
|
||||
} else {
|
||||
// File doesnt exist we need to create one
|
||||
// This is the job of the derives constructor.
|
||||
chkExistIfs.close();
|
||||
};
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/12/22.
|
||||
//
|
||||
|
||||
#include "dateMoney.h"
|
||||
|
||||
|
||||
DateMoney::DateMoney(const double *value, tm *date) : value(value), date(date) {}
|
||||
|
||||
bool DateMoney::operator<(const DateMoney &rhs) const {
|
||||
return mktime(date) < mktime(rhs.date);
|
||||
}
|
||||
|
||||
bool DateMoney::operator>(const DateMoney &rhs) const {
|
||||
return rhs < *this;
|
||||
}
|
||||
|
||||
bool DateMoney::operator<=(const DateMoney &rhs) const {
|
||||
return !(rhs < *this);
|
||||
}
|
||||
|
||||
bool DateMoney::operator>=(const DateMoney &rhs) const {
|
||||
return !(*this < rhs);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const DateMoney &money) {
|
||||
os << "Value: " << *money.value << " Date: " << money.date->tm_mon + 1 << "/" << money.date->tm_mday << "/"
|
||||
<< money.date->tm_year+1900;
|
||||
return os;
|
||||
}
|
||||
|
||||
const double *DateMoney::getValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
tm *DateMoney::getDate() const {
|
||||
return date;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/12/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_DATEMONEY_H
|
||||
#define BUDGET_DATEMONEY_H
|
||||
|
||||
|
||||
#include <ctime>
|
||||
#include <ostream>
|
||||
|
||||
class DateMoney {
|
||||
public:
|
||||
DateMoney(const double *value, tm *date);
|
||||
|
||||
[[nodiscard]] const double *getValue() const;
|
||||
|
||||
[[nodiscard]] tm *getDate() const;
|
||||
|
||||
bool operator<(const DateMoney &rhs) const;
|
||||
|
||||
bool operator>(const DateMoney &rhs) const;
|
||||
|
||||
bool operator<=(const DateMoney &rhs) const;
|
||||
|
||||
bool operator>=(const DateMoney &rhs) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &os, const DateMoney &money);
|
||||
|
||||
private:
|
||||
const double *value;
|
||||
tm *date;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_DATEMONEY_H
|
83
src/main.cpp
83
src/main.cpp
@ -2,18 +2,13 @@
|
||||
// Created by quentin on 8/3/22.
|
||||
//
|
||||
|
||||
#include "main.h"
|
||||
#include "data/accountData.h"
|
||||
#include "optHandlers/accountOptHandler.h"
|
||||
#include "optHandlers/mainOptHandler.h"
|
||||
#include "../utilities/math.h"
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
using namespace Budget;
|
||||
|
||||
@ -31,81 +26,5 @@ void createRequiredFolders() {
|
||||
int main(int argc, char *argv[]) {
|
||||
std::vector<char *> args(argv, argv + argc);
|
||||
|
||||
// Parse main options (-ah)
|
||||
OptHandlers::MainOptHandler mainOptHandler(args);
|
||||
mainOptHandler.parse();
|
||||
if (mainOptHandler.getSetOpts()->help)
|
||||
mainOptHandler.help();
|
||||
|
||||
createRequiredFolders();
|
||||
// Read all accounts saved and store them in accounts
|
||||
std::unordered_map<std::string, AccountData> accounts;
|
||||
for (const auto &file : std::filesystem::directory_iterator(
|
||||
homeDirectory + "/.local/share/budget/accounts")) {
|
||||
AccountData account(file.path());
|
||||
accounts.insert(std::pair(account.getAccount()->getName(), account));
|
||||
}
|
||||
|
||||
// Parse account options if main options tells us to.
|
||||
if (mainOptHandler.getSetOpts()->account) {
|
||||
std::vector<char *> vec{argv[0]};
|
||||
vec.insert(vec.end(), args.begin() + mainOptHandler.getSetOpts()->accountArgStart, args.end());
|
||||
OptHandlers::AccountOptHandler accountOptHandler(vec);
|
||||
accountOptHandler.parse();
|
||||
|
||||
// Do what we need to do for parsed options
|
||||
if (accountOptHandler.getSetOpts()->help) {
|
||||
accountOptHandler.help();
|
||||
}
|
||||
if (accountOptHandler.getSetOpts()->create) {
|
||||
auto a = accounts.find(accountOptHandler.getSetOpts()->delAccount);
|
||||
if (a == accounts.end()) {
|
||||
accounts.emplace(std::piecewise_construct,
|
||||
std::make_tuple(accountOptHandler.getSetOpts()->createAccount), std::make_tuple(
|
||||
storageD + "accounts/" + accountOptHandler.getSetOpts()->createAccount + ".json",
|
||||
accountOptHandler.getSetOpts()->createAccount));
|
||||
} else {
|
||||
std::cout << "Account " << accountOptHandler.getSetOpts()->delAccount << " already exists."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
if (accountOptHandler.getSetOpts()->value) {
|
||||
auto a = accounts.find(accountOptHandler.getSetOpts()->valueAccount);
|
||||
if (a != accounts.end()) {
|
||||
int value = a->second.getAccount()->getValue();
|
||||
std::vector<DateMoney> timeline = a->second.getAccount()->getTimeline();
|
||||
printf("Account value: %d\n", value);
|
||||
printf("Last 10 transactions:\n");
|
||||
for (int i = 0; i < timeline.size() && i < 10; i++) {
|
||||
const double *amount = timeline[i].getValue();
|
||||
const tm *date = timeline[i].getDate();
|
||||
if (*amount <= 0) {
|
||||
// Red
|
||||
printf("Value: \033[31m%.2f\033[0m, ", *amount);
|
||||
}
|
||||
else {
|
||||
// Green
|
||||
printf("Value: \033[32m%.2f\033[0m, ", *amount);
|
||||
}
|
||||
printf("Date: %d/%d/%d\n", date->tm_mon+1, date->tm_mday, date->tm_year+1900);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
if (accountOptHandler.getSetOpts()->del) {
|
||||
auto a = accounts.find(accountOptHandler.getSetOpts()->delAccount);
|
||||
if (a != accounts.end()) {
|
||||
accounts.erase(a);
|
||||
std::cout << "Deleted account: " << accountOptHandler.getSetOpts()->delAccount << std::endl;
|
||||
}
|
||||
}
|
||||
if (accountOptHandler.getSetOpts()->list) {
|
||||
std::cout << "Accounts: " << std::endl;
|
||||
for (auto &accountPair : accounts) {
|
||||
std::cout << accountPair.second.getAccount()->getName() << ": " << std::endl;
|
||||
std::cout << " Value: " << accountPair.second.getAccount()->getValue() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/12/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_MAIN_H
|
||||
#define BUDGET_MAIN_H
|
||||
|
||||
#endif //BUDGET_MAIN_H
|
@ -1,44 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#include "account.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
Account::Account(std::list<Payment> payments, std::list<Earning> earnings,
|
||||
std::string name) : payments(std::move(payments)), earnings(std::move(earnings)),
|
||||
name(std::move(name)) {}
|
||||
|
||||
Account::Account() {
|
||||
name = "";
|
||||
}
|
||||
|
||||
int Account::getValue() {
|
||||
int total = 0;
|
||||
for (auto &payment : payments) {
|
||||
total -= payment.value;
|
||||
}
|
||||
for (auto &earning : earnings) {
|
||||
total += earning.value;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
std::vector<DateMoney> Account::getTimeline() {
|
||||
std::vector<DateMoney> timeline;
|
||||
for (auto &payment : payments) {
|
||||
timeline.emplace_back(payment.getValue(), payment.getDate());
|
||||
}
|
||||
for (auto &earning : earnings) {
|
||||
timeline.emplace_back(&earning.value, earning.getDate());
|
||||
}
|
||||
std::sort(timeline.begin(), timeline.end(), std::greater<>());
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
const std::string &Account::getName() const {
|
||||
return name;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_ACCOUNT_H
|
||||
#define BUDGET_ACCOUNT_H
|
||||
|
||||
|
||||
#include "payment.h"
|
||||
#include "earning.h"
|
||||
#include "../data/dateMoney.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Account {
|
||||
public:
|
||||
Account(std::list<Payment> payments, std::list<Earning> earnings, std::string name);
|
||||
|
||||
Account();
|
||||
|
||||
int getValue();
|
||||
|
||||
std::vector<DateMoney> getTimeline();
|
||||
|
||||
[[nodiscard]] const std::string &getName() const;
|
||||
|
||||
private:
|
||||
std::list<Payment> payments;
|
||||
std::list<Earning> earnings;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_ACCOUNT_H
|
@ -1,7 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/11/22.
|
||||
//
|
||||
|
||||
#include "earning.h"
|
||||
|
||||
Earning::Earning(const double value, std::tm date) : Transaction(value, date) {}
|
@ -1,17 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/11/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_EARNING_H
|
||||
#define BUDGET_EARNING_H
|
||||
|
||||
#include <ctime>
|
||||
#include "transaction.h"
|
||||
|
||||
class Earning : public Transaction {
|
||||
public:
|
||||
explicit Earning(double value, std::tm date);
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_EARNING_H
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#include "payment.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
Payment::Payment(const double value, Receipt receipt, std::tm date) : Transaction(value, date), receipt(std::move(receipt)) {
|
||||
negativeValue = -value;
|
||||
}
|
||||
|
||||
Receipt &Payment::getReceipt() {
|
||||
return receipt;
|
||||
}
|
||||
|
||||
const double *Payment::getValue() {
|
||||
return &negativeValue;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_PAYMENT_H
|
||||
#define BUDGET_PAYMENT_H
|
||||
|
||||
|
||||
#include "recept.h"
|
||||
#include "transaction.h"
|
||||
|
||||
class Payment : public Transaction {
|
||||
public:
|
||||
Payment(double value, Receipt receipt, std::tm date);
|
||||
|
||||
Receipt &getReceipt();
|
||||
|
||||
const double *getValue();
|
||||
|
||||
private:
|
||||
Receipt receipt;
|
||||
|
||||
double negativeValue;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_PAYMENT_H
|
@ -1,9 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#include "recept.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
Receipt::Receipt(std::string file) : file(std::move(file)) {}
|
@ -1,21 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/4/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_RECEPT_H
|
||||
#define BUDGET_RECEPT_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
class Receipt {
|
||||
private:
|
||||
public:
|
||||
explicit Receipt(std::string file);
|
||||
|
||||
private:
|
||||
std::string file;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_RECEPT_H
|
@ -1,11 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/16/22.
|
||||
//
|
||||
|
||||
#include "transaction.h"
|
||||
|
||||
Transaction::Transaction(const double value, const tm &date) : value(value), date(date) {}
|
||||
|
||||
tm *Transaction::getDate() {
|
||||
return &date;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/16/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_TRANSACTION_H
|
||||
#define BUDGET_TRANSACTION_H
|
||||
|
||||
#include <ctime>
|
||||
|
||||
class Transaction {
|
||||
public:
|
||||
Transaction(double value, const tm &date);
|
||||
|
||||
const double value;
|
||||
|
||||
tm *getDate();
|
||||
|
||||
private:
|
||||
std::tm date;
|
||||
};
|
||||
|
||||
|
||||
#endif //BUDGET_TRANSACTION_H
|
@ -1,70 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "accountOptHandler.h"
|
||||
|
||||
using namespace Budget::OptHandlers;
|
||||
|
||||
|
||||
void AccountOptHandler::parse() {
|
||||
struct option longOpts[] = {
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"list", no_argument, nullptr, 'l'},
|
||||
{"delete", required_argument, nullptr, 'd'},
|
||||
{"create", required_argument, nullptr, 'c'},
|
||||
{"value", required_argument, nullptr, 'v'},
|
||||
};
|
||||
|
||||
while (true) {
|
||||
int opt = getopt_long(getArgc(), getArgv(), "hld:c:v:", longOpts, nullptr);
|
||||
|
||||
if (opt == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
setOpts.help = true;
|
||||
break;
|
||||
case 'l':
|
||||
setOpts.list = true;
|
||||
break;
|
||||
case 'd':
|
||||
setOpts.del = true;
|
||||
setOpts.delAccount = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
setOpts.create = true;
|
||||
setOpts.createAccount = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
setOpts.value = true;
|
||||
setOpts.valueAccount = optarg;
|
||||
break;
|
||||
case '?':
|
||||
setOpts.help = true;
|
||||
setOpts.helpOut = stderr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AccountOptHandler::help() {
|
||||
fprintf(setOpts.helpOut, "Help budget -a {-cvd account|-hl}\n");
|
||||
fprintf(setOpts.helpOut, " -h --help Output this message.\n");
|
||||
fprintf(setOpts.helpOut, " -l --list List available accounts.\n");
|
||||
fprintf(setOpts.helpOut, " -d --delete account Delete the specified account.\n");
|
||||
fprintf(setOpts.helpOut, " -c --create account Create a new account.\n");
|
||||
fprintf(setOpts.helpOut, " -v --value account Print the current value of account.\n");
|
||||
}
|
||||
|
||||
const AccountOptHandler::SetOpts *AccountOptHandler::getSetOpts() const {
|
||||
return &setOpts;
|
||||
}
|
||||
|
||||
AccountOptHandler::AccountOptHandler(const std::vector<char *> &argv) : OptHandler(argv) {}
|
||||
|
@ -1,41 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_ACCOUNTOPTHANDLER_H
|
||||
#define BUDGET_ACCOUNTOPTHANDLER_H
|
||||
|
||||
|
||||
#include "optHandler.h"
|
||||
|
||||
namespace Budget::OptHandlers {
|
||||
class AccountOptHandler : public OptHandler {
|
||||
struct SetOpts {
|
||||
FILE *helpOut = stdout;
|
||||
bool help = false;
|
||||
bool list = false;
|
||||
bool del = false;
|
||||
char *delAccount{};
|
||||
bool create = false;
|
||||
char *createAccount{};
|
||||
bool value = false;
|
||||
char *valueAccount{};
|
||||
};
|
||||
|
||||
public:
|
||||
explicit AccountOptHandler(const std::vector<char *> &argv);
|
||||
|
||||
void parse() override;
|
||||
|
||||
void help() override;
|
||||
|
||||
[[nodiscard]] const SetOpts *getSetOpts() const;
|
||||
|
||||
private:
|
||||
SetOpts setOpts;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //BUDGET_ACCOUNTOPTHANDLER_H
|
@ -1,51 +1,51 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
// Created by quentin on 1/8/23.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include "mainOptHandler.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Budget::OptHandlers;
|
||||
|
||||
MainOptHandler::MainOptHandler(const std::vector<char *> &argv) {
|
||||
|
||||
MainOptHandler::MainOptHandler(const std::vector<char *> &argv) : OptHandler(argv) {}
|
||||
|
||||
void MainOptHandler::parse() {
|
||||
struct option longOpts[] = {
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"account", no_argument, nullptr, 'a'},
|
||||
};
|
||||
|
||||
while (true) {
|
||||
int opt = getopt_long(getArgc(), getArgv(), "ha", longOpts, nullptr);
|
||||
if (opt == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
setOpts.help = true;
|
||||
break;
|
||||
case 'a':
|
||||
setOpts.account = true;
|
||||
setOpts.accountArgStart = optind - 1;
|
||||
return;
|
||||
case '?':
|
||||
setOpts.help = true;
|
||||
setOpts.helpOut = stderr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainOptHandler::help() {
|
||||
fprintf(setOpts.helpOut, "Help budget {-ha}\n");
|
||||
fprintf(setOpts.helpOut, " -h --help Output this message.\n");
|
||||
fprintf(setOpts.helpOut, " -a --account Do budget -a -h for more info.\n");
|
||||
}
|
||||
|
||||
const MainOptHandler::SetOpts *MainOptHandler::getSetOpts() const {
|
||||
return &setOpts;
|
||||
std::cout << "Output of budget." << std::endl;
|
||||
std::cout << "Usage:" << std::endl;
|
||||
std::cout << "\tbudget <action> [options] ..." << std::endl;
|
||||
std::cout << "Actions:" << std::endl;
|
||||
std::cout << "\t-h --help\t\t\t\tPrints this." << std::endl;
|
||||
std::cout << "\t-a --account<=STRING>\tManagement tools for an account." << std::endl;
|
||||
std::cout << "\t-c --create<=STRING>\tCreates a new account with NAME." << std::endl;
|
||||
std::cout << "\t-e --earn<=STRING>\t\tAdd an earning to an account." << std::endl;
|
||||
std::cout << "\t-p --payment<=STRING>\tAdd a payment to an account." << std::endl;
|
||||
std::cout << "Account Options: [-dDv]" << std::endl;
|
||||
std::cout << "\t-d --delete\t\t\t\tDeletes specified account." << std::endl;
|
||||
std::cout << "\t--force-delete\t\t\tDeletes the specified account without confirmation." << std::endl;
|
||||
std::cout << "\t-v --value\t\t\t\tGets the current value of the account." << std::endl;
|
||||
std::cout << "\t-D --description\t\tChanges the description of the account." << std::endl;
|
||||
std::cout << "Create Options: [-d]" << std::endl;
|
||||
std::cout << "\t-d --description\t\tSets a description for an account." << std::endl;
|
||||
std::cout << "Earn Options: -v [-drD]" << std::endl;
|
||||
std::cout << "\t-v --value=<FlOAT>\t\tValue for earning." << std::endl;
|
||||
std::cout << "\t-d --description=<STRING>\tDescription for earning." << std::endl;
|
||||
std::cout << "\t-r --receipt=<PATH>\t\tPath to file to store in DB as receipt." << std::endl;
|
||||
std::cout << "\t-D --date=<dd/mm/yyyy>\tDate as dd/mm/yyyy. Default will be today." << std::endl;
|
||||
std::cout << "\t-t --time=<hh/mm/ss>\t\t24 hour time as hh/mm/ss. Default will be now." << std::endl;
|
||||
std::cout << "Payment Options: -v [-drD]" << std::endl;
|
||||
std::cout << "\t-v --value=<FlOAT>\t\tValue for payment." << std::endl;
|
||||
std::cout << "\t-d --description=<STRING>\tDescription for payment." << std::endl;
|
||||
std::cout << "\t-r --receipt=<PATH>\t\tPath to file to store in DB as receipt." << std::endl;
|
||||
std::cout << "\t-D --date=<NUM/NUM/NUM>\t\tDate as dd/mm/yyyy. Default will be today." << std::endl;
|
||||
std::cout << "\t-t --time=<hh/mm/ss>\t\t24 hour time as hh/mm/ss. Default will be now." << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Arguments are processed like blocks with each one terminated by the next Action. For example" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << R"(budget -cAcct -eAcct -v10.00 -r"./receipt.pdf" -pAcct -v5.50 -r"./payment.pdf")" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Does the following in order:" << std::endl;
|
||||
std::cout << "Creates an account named Acct with no description." << std::endl;
|
||||
std::cout << "Earns 10.00 to it with a receipt." << std::endl;
|
||||
std::cout << "Pays 5.50 to it with a receipt." << std::endl;
|
||||
}
|
||||
|
@ -1,32 +1,18 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
// Created by quentin on 1/8/23.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_MAINOPTHANDLER_H
|
||||
#define BUDGET_MAINOPTHANDLER_H
|
||||
|
||||
#include "optHandler.h"
|
||||
#include <vector>
|
||||
|
||||
namespace Budget::OptHandlers {
|
||||
class MainOptHandler : public OptHandler {
|
||||
struct SetOpts {
|
||||
FILE *helpOut = stdout;
|
||||
bool help = false;
|
||||
bool account = false;
|
||||
int accountArgStart = -1;
|
||||
};
|
||||
|
||||
namespace Budget::OptHandlers{
|
||||
class MainOptHandler {
|
||||
public:
|
||||
explicit MainOptHandler(const std::vector<char *> &argv);
|
||||
|
||||
void parse() override;
|
||||
|
||||
void help() override;
|
||||
|
||||
[[nodiscard]] const SetOpts *getSetOpts() const;
|
||||
|
||||
private:
|
||||
SetOpts setOpts;
|
||||
void help();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,20 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
//
|
||||
|
||||
#include "optHandler.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace Budget::OptHandlers;
|
||||
|
||||
|
||||
OptHandler::OptHandler(std::vector<char *> argv) : argv(std::move(argv)) {}
|
||||
|
||||
int OptHandler::getArgc() {
|
||||
return argv.size();
|
||||
}
|
||||
|
||||
char **OptHandler::getArgv() {
|
||||
return argv.data();
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 8/13/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_OPTHANDLER_H
|
||||
#define BUDGET_OPTHANDLER_H
|
||||
|
||||
#include <getopt.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Budget::OptHandlers {
|
||||
class OptHandler {
|
||||
public:
|
||||
explicit OptHandler(std::vector<char *> argv);
|
||||
|
||||
virtual void parse() = 0;
|
||||
|
||||
int getArgc();
|
||||
|
||||
char **getArgv();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<char *> argv;
|
||||
|
||||
virtual void help() = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //BUDGET_OPTHANDLER_H
|
@ -1,97 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/13/22.
|
||||
//
|
||||
|
||||
#include "math.h"
|
||||
|
||||
//Polynomial Fit
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Budget::Utilities;
|
||||
|
||||
PolynomialFunction Math::polynomialFit(int degree, int numberOfPoints, const double x[], const double y[]) {
|
||||
//Array that will store the values of sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2numberOfPoints)
|
||||
double X[2 * degree + 1];
|
||||
for (int i = 0; i < 2 * degree + 1; i++) {
|
||||
X[i] = 0;
|
||||
for (int j = 0; j < numberOfPoints; j++) {
|
||||
//consecutive positions of the array will store numberOfPoints,sigma(xi),sigma(xi^2),sigma(xi^3)....sigma(xi^2n)
|
||||
X[i] = X[i] + pow(x[j], i);
|
||||
}
|
||||
}
|
||||
//B is the Normal matrix(augmented) that will store the equations, 'a' is for value of the final coefficients
|
||||
double B[degree + 1][degree + 2], a[degree + 1];
|
||||
for (int i = 0; i <= degree; i++) {
|
||||
for (int j = 0; j <= degree; j++) {
|
||||
//Build the Normal matrix by storing the corresponding coefficients at the right positions except the last column of the matrix
|
||||
B[i][j] = X[i + j];
|
||||
}
|
||||
}
|
||||
|
||||
//Array to store the values of sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^degree*yi)
|
||||
double Y[degree + 1];
|
||||
for (int i = 0; i < degree + 1; i++) {
|
||||
Y[i] = 0;
|
||||
for (int j = 0; j < numberOfPoints; j++) {
|
||||
//consecutive positions will store sigma(yi),sigma(xi*yi),sigma(xi^2*yi)...sigma(xi^degree*yi)
|
||||
Y[i] = Y[i] + pow(x[j], i) * y[j];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i <= degree; i++) {
|
||||
//load the values of Y as the last column of B(Normal Matrix but augmented)
|
||||
B[i][degree + 1] = Y[i];
|
||||
}
|
||||
|
||||
//degree is made degree+1 because the Gaussian Elimination part below was for degree equations, but here degree is the degree of polynomial and for degree degree we get degree+1 equations
|
||||
degree = degree + 1;
|
||||
//From now Gaussian Elimination starts(can be ignored) to solve the set of linear equations (Pivotisation)
|
||||
for (int i = 0; i < degree; i++) {
|
||||
for (int k = i + 1; k < degree; k++) {
|
||||
if (B[i][i] < B[k][i]) {
|
||||
for (int j = 0; j <= degree; j++) {
|
||||
double temp = B[i][j];
|
||||
B[i][j] = B[k][j];
|
||||
B[k][j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//loop to perform the gauss elimination
|
||||
for (int i = 0; i < degree - 1; i++) {
|
||||
for (int k = i + 1; k < degree; k++) {
|
||||
double t = B[k][i] / B[i][i];
|
||||
for (int j = 0; j <= degree; j++) {
|
||||
//make the elements below the pivot elements equal to zero or elimnate the variables
|
||||
B[k][j] = B[k][j] - t * B[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//back-substitution
|
||||
for (int i = degree - 1; i >= 0; i--) {
|
||||
//x is an array whose values correspond to the values of x,y,z..
|
||||
//make the variable to be calculated equal to the rhs of the last equation
|
||||
a[i] = B[i][degree];
|
||||
for (int j = 0; j < degree; j++) {
|
||||
//then subtract all the lhs values except the coefficient of the variable whose value is being calculated
|
||||
if (j != i) {
|
||||
a[i] = a[i] - B[i][j] * a[j];
|
||||
}
|
||||
}
|
||||
//now finally divide the rhs by the coefficient of the variable to be calculated
|
||||
a[i] = a[i] / B[i][i];
|
||||
}
|
||||
std::cout << "\nThe values of the coefficients are as follows:\n";
|
||||
for (int i = 0; i < degree; i++)
|
||||
std::cout << "x^" << i << "=" << a[i] << std::endl; // Print the values of x^0,x^1,x^2,x^3,....
|
||||
std::cout << "\nHence the fitted Polynomial is given by:\ny=";
|
||||
for (int i = 0; i < degree; i++)
|
||||
std::cout << " + (" << a[i] << ")" << "x^" << i;
|
||||
std::cout << "\n";
|
||||
|
||||
std::vector<double> va(a, a + degree);
|
||||
return PolynomialFunction(va);
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/13/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_MATH_H
|
||||
#define BUDGET_MATH_H
|
||||
|
||||
|
||||
#include "polynomialFunction.h"
|
||||
|
||||
namespace Budget::Utilities {
|
||||
class Math {
|
||||
public:
|
||||
static PolynomialFunction polynomialFit(int degree, int numberOfPoints, const double x[], const double y[]);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //BUDGET_MATH_H
|
@ -1,21 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/13/22.
|
||||
//
|
||||
|
||||
#include "polynomialFunction.h"
|
||||
|
||||
#include <utility>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Budget::Utilities;
|
||||
|
||||
PolynomialFunction::PolynomialFunction(std::vector<double> a) : a(std::move(a)) {}
|
||||
|
||||
double PolynomialFunction::get(double x) {
|
||||
double ret = 0;
|
||||
for (int i = 0; i < a.size(); ++i) {
|
||||
ret += a[i] * std::pow(x, i);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
//
|
||||
// Created by quentin on 9/13/22.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_POLYNOMIALFUNCTION_H
|
||||
#define BUDGET_POLYNOMIALFUNCTION_H
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Budget::Utilities {
|
||||
class PolynomialFunction {
|
||||
private:
|
||||
public:
|
||||
explicit PolynomialFunction(std::vector<double> a);
|
||||
|
||||
double get(double x);
|
||||
|
||||
private:
|
||||
std::vector<double> a;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //BUDGET_POLYNOMIALFUNCTION_H
|
Loading…
x
Reference in New Issue
Block a user