-
Notifications
You must be signed in to change notification settings - Fork 0
/
dbLib.cpp
276 lines (258 loc) · 10 KB
/
dbLib.cpp
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/*
* =========================================================================================
* Name : dbLib.cpp
* Author : Duc Dung Nguyen, Nguyen Hoang Minh
* Email : [email protected]
* Copyright : Faculty of Computer Science and Engineering - Bach Khoa University
* Description : library for Assignment 1 - Data structures and Algorithms - Fall 2017
* This file implements functions used for database management
* =========================================================================================
*/
#include "dbLib.h"
#include <time.h>
#include <fstream>
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#define pi 3.14159265358979323846
#define earthRadiusKm 6371.0
using namespace std;
//struct PointOnEarth
//{
// double longt{ 0.0 }, lat{ 0.0 };
// PointOnEarth() {}
// PointOnEarth(double a, double b);
//};
// structure for global data
//class PointerToGData
//{
//public:
// // attributes
// L1List<ninjaEvent_t> pLE; // copy list of events list for reprint
// L1List<L1List<NinjaInfo_t>> pLL; // list of lists
// double *totalDistance{ nullptr }; // total distance of traveling array
// time_t *totalUnmovingTime{ nullptr }; // array of total unmoved time of each ninja
// size_t *numOfTimesUnmoving{ nullptr }; // array of the number of times each ninja unmove
// time_t *firstTimeMoving{ nullptr }; // array of each ninja's first time moving
// time_t *lastTimeUnmoving{ nullptr }; // array of each ninja's last time unmoving
// time_t *totalMovingTime{ nullptr }; // array of each ninja's total moving time
// // methods
// PointerToGData();
// ~PointerToGData();
// const char* findMaxID();
// const char* findAndKill(char *killerID);
// void statisticizeData(); // Ninjas'data statistic
// const char* findFirstTimeMovingOf(char *ninjaID);
// const char* findLastTimeUnmovingOf(char *ninjaID);
// int findNumberOfUnmovingTimesOf(char *ninjaID);
// string findSumOfTravelingDistanceOf(char *ninjaID);
// const char* findMaxTrvlDist();
// const char* findMaxTrvlTime();
// const char* findMaxUnmovingTime();
// //void findAndPrintListOfNinjaTrapped(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D);
// void findAndPrintListOfNinjasLost();
// // friend function
// //friend bool checkIfTowGivenLineSegmentsIntersect(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D);
// //friend bool checkIfAGivenLineSegmentIntersectAGivenSquare(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D, PointOnEarth &E, PointOnEarth &F);
// //friend bool checkIfAPointIsInsideOrOnTheEdgeOfAGivenSquare(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D, PointOnEarth &E);
////private:
//};
void strPrintTime(char *des, time_t &t) {
tm *pTime = localtime(&t); // gmtime(&t);
strftime(des, 26, "%Y-%m-%d %H:%M:%S", pTime);
}
//#define timegm _mkgmtime
// Load database
void loadNinjaDB(char *fName, L1List<NinjaInfo_t> &db) {
// TODO: write code to load information from file into db
ifstream dbFile(fName);
if (!dbFile)
{
db.clean();
cerr << "\nCannot open the database file for reading!\n";
return;
}
else
{
stringstream buf;
string str;
tm t;
int in;
getline(dbFile, str); // discard the first line
while (!dbFile.eof())
{
NinjaInfo_t n;
getline(dbFile, str, ','); // discard the 1st item on each line
// handle time data
//if (str.empty()) continue; // str[0] == '\n' || str[0] == '\r' ||
if (!str.empty() && (str.back() > ' ')) //
{
getline(dbFile, str, ','); // "Report time"
buf << str;
buf >> in;
t.tm_mon = in - 1; // month [0-11]
buf.ignore(); // discard '/'
buf >> t.tm_mday; // day
buf.ignore(); // discard '/'
buf >> in;
t.tm_year = in - 1900; // number of years from 1900
buf.ignore(); // discard ' '
buf >> t.tm_hour;
buf.ignore(); // discard ':'
buf >> t.tm_min;
buf.ignore(); // discard ':'
buf >> t.tm_sec;
//buf >> get_time(&t, "%m/%d/%Y %H:%M:%S");
n.timestamp = mktime(&t); // convert from tm to time_t
buf.str("");
buf.clear();
// handle ninja id
getline(dbFile, str, ','); // Ninja tag
if (str.length() < 4) strcpy(n.id, str.insert(0, 4 - str.length(), '0').data());
else strcpy(n.id, str.data());
// handle longitude
getline(dbFile, str, ','); // Longitude
/*buf << str;
buf >> n.longitude;
buf.str("");
buf.clear();*/
n.longitude = stod(str);
// handle latitude
getline(dbFile, str, ','); // Latitude
/*buf << str;
buf >> n.latitude;
buf.str("");
buf.clear();*/
n.latitude = stod(str);
getline(dbFile, str); // read the rest of the line
db.push_back(n);
//printNinjaInfo(n);
}
}
dbFile.close();
}
return;
}
// Not use
bool parseNinjaInfo(char* pBuf, NinjaInfo_t& nInfo) {
// TODO: write code to parse information from a string buffer, ignore if you don't use it
return true;
}
// struct for the coordinates
struct PointOnEarth
{
double longt{ 0.0 }, lat{ 0.0 };
PointOnEarth() {}
PointOnEarth(double a, double b) :longt{ a }, lat{ b } {}
};
// structure for global data
//struct TimeAnalytics
//
class PointerToGData
{
public:
// attributes
L1List<ninjaEvent_t> pLE; // copy list of events list for reprint
L1List<L1List<NinjaInfo_t>> pLL; // list of lists
double *totalDistance{ nullptr }; // total distance of traveling array
time_t *totalUnmovingTime{ nullptr }; // array of total unmoved time of each ninja
size_t *numOfTimesUnmoving{ nullptr }; // array of the number of times each ninja unmove
time_t *firstTimeMoving{ nullptr }; // array of each ninja's first time moving
time_t *lastTimeUnmoving{ nullptr }; // array of each ninja's last time unmoving
time_t *totalMovingTime{ nullptr }; // array of each ninja's total moving time
// methods
PointerToGData() {}
~PointerToGData();
const char* findMaxID();
const char* findAndKill(char *killerID);
void statisticizeData(); // Ninjas'data statistic
const char* findFirstTimeMovingOf(char *ninjaID);
const char* findLastTimeUnmovingOf(char *ninjaID);
int findNumberOfUnmovingTimesOf(char *ninjaID);
string findSumOfTravelingDistanceOf(char *ninjaID);
const char* findMaxTrvlDist();
const char* findMaxTrvlTime();
const char* findMaxUnmovingTime();
//void findAndPrintListOfNinjaTrapped(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D);
void findAndPrintListOfNinjasLost();
// friend function
//friend bool checkIfTowGivenLineSegmentsIntersect(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D);
//friend bool checkIfAGivenLineSegmentIntersectAGivenSquare(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D, PointOnEarth &E, PointOnEarth &F);
//friend bool checkIfAPointIsInsideOrOnTheEdgeOfAGivenSquare(PointOnEarth &A, PointOnEarth &B, PointOnEarth &C, PointOnEarth &D, PointOnEarth &E);
//private:
};
bool initNinjaGlobalData(void* *pGData) {
/// TODO: You should define this function if you would like to use some extra data
/// the data should be allocated and pass the address into pGData
try
{
*pGData = new PointerToGData();
return true;
}
catch (const std::exception& e)
{
cerr << '\n' << e.what() << '\n';
return 0;
}
}
void releaseNinjaGlobalData(void *pGData) {
/// TODO: You should define this function if you allocated extra data at initialization stage
/// The data pointed by pGData should be released
delete static_cast<PointerToGData*>(pGData);
return;
}
// forward declaration of some function use for sorting a list
//void traverse(L1List<L1List<NinjaInfo>> &L, NinjaInfo &a);
void traverse(L1List<NinjaInfo> &lN, L1List<L1List<NinjaInfo>> &lL);
//void printListNinja(L1List<NinjaInfo> &l);
// function process called by main to execute the whole program
void process(L1List<ninjaEvent_t> &eventList, L1List<NinjaInfo_t> &bList) {
void *pGData = NULL;
if (initNinjaGlobalData(&pGData))
{
PointerToGData *p{ static_cast<PointerToGData*>(pGData) };
// copy list eventList
eventList.traverse(p->pLE);
// create a list of lists of each ninja's data
traverse(bList, p->pLL);
//p->pLL.traverse(printListNinja);
p->statisticizeData();
}
while (!eventList.isEmpty()) {
if (!processEvent(eventList[0], bList, pGData))
cout << eventList[0].code << " is an invalid event\n";
eventList.removeHead();
}
releaseNinjaGlobalData(pGData);
}
void printNinjaInfo(NinjaInfo_t& b) {
printf("%s: (%0.5f, %0.5f), %s\n", b.id, b.longitude, b.latitude, ctime(&b.timestamp));
}
/// This function converts decimal degrees to radians
double deg2rad(double deg) {
return (deg * pi / 180);
}
/// This function converts radians to decimal degrees
double rad2deg(double rad) {
return (rad * 180 / pi);
}
/**
* Returns the distance between two points on the Earth.
* Direct translation from http://en.wikipedia.org/wiki/Haversine_formula
* @param lat1d Latitude of the first point in degrees
* @param lon1d Longitude of the first point in degrees
* @param lat2d Latitude of the second point in degrees
* @param lon2d Longitude of the second point in degrees
* @return The distance between the two points in kilometers
*/
double distanceEarth(double lat1d, double lon1d, double lat2d, double lon2d) {
double lat1r, lon1r, lat2r, lon2r, u, v;
lat1r = deg2rad(lat1d);
lon1r = deg2rad(lon1d);
lat2r = deg2rad(lat2d);
lon2r = deg2rad(lon2d);
u = sin((lat2r - lat1r)/2);
v = sin((lon2r - lon1r)/2);
return 2.0 * earthRadiusKm * asin(sqrt(u * u + cos(lat1r) * cos(lat2r) * v * v));
}