-
Notifications
You must be signed in to change notification settings - Fork 0
/
repo.cc
132 lines (105 loc) · 3.17 KB
/
repo.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <string>
#include <fstream>
#include <vector>
#include <map>
#include <chrono>
#include <ctime>
#include <locale>
#include <iostream>
#include "repo.h"
#include "utility.h"
// public
Repo::Repo(std::string name) {
std::fstream filestream;
filename = name + ".csv";
filestream.open(filename, std::ios::in);
if (filestream.fail()) {
// Create file if it doesn't exist
filestream.open(filename, std::ios::out);
filestream.close();
store = {};
} else {
while(!filestream.eof()) {
std::string row_string;
std::map<std::string, std::string> datum;
std::getline(filestream, row_string, '\n');
std::vector<std::string> row = Utility::String::split(row_string, ',');
std::vector<std::vector<std::string>> row_value
= Utility::Vector::zip(headers, row);
for (std::vector<std::string> teeth_chain : row_value) {
std::string key = teeth_chain.front();
std::string value = teeth_chain.back();
datum[key] = value;
}
store.push_back(datum);
}
}
}
std::vector<std::map<std::string, std::string>> Repo::all() {
return store;
}
void Repo::delete_at(std::string identifier) {
// can't immediately find an idiomatic way to delete an element from a vector
// so i'm just going to copy and assign while skipping element to be deleted
std::vector<std::map<std::string, std::string>> updated_store;
for (std::map<std::string, std::string> row : store) {
if (row["id"] != identifier){
updated_store.push_back(row);
}
}
store = updated_store;
persist();
}
void Repo::insert(std::map<std::string, std::string> task) {
// ids are strings even though they are represented as numbers wanted to
// implement ids as random series of alphanumeric string but not much time
// and don't quite get how to do it so doing it incremental index based
if (store.empty()) {
task["id"] = "1";
} else {
task["id"] = (std::to_string(std::stoi(store.back()["id"]) + 1));
}
task["created_at"] = generate_timestamp();
store.push_back(task);
persist();
}
std::vector<std::string> Repo::get_headers() const {
return headers;
}
void Repo::update(std::string identifier, std::string key, std::string new_value) {
for (std::map<std::string, std::string> &row : store) {
if (row["id"] == identifier) {
row[key] = new_value;
row["updated_at"] = generate_timestamp();
break;
}
}
persist();
}
// private
void Repo::persist() {
std::ofstream file;
file.open(filename);
for (std::map<std::string, std::string> record : store) {
std::vector<std::string> ordered_values;
for (std::string header : headers) {
ordered_values.push_back(record[header]);
}
std::string csv_row = Utility::Vector::join(ordered_values, ",");
file << csv_row << std::endl;
}
file.close();
}
std::string Repo::generate_timestamp() {
char timestamp[50];
std::chrono::time_point<std::chrono::system_clock> end =
std::chrono::system_clock::now();
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::strftime(
timestamp,
sizeof(timestamp),
"%Y%m%d %p%l:%M:%S",
std::localtime(&end_time)
);
return timestamp;
}