-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathufojson_core.h
251 lines (181 loc) · 6.48 KB
/
ufojson_core.h
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
// ufojson_core.h
// Copyright (C) 2023 Richard Geldreich, Jr.
#pragma once
#include "utils.h"
// Note that May ends in a period.
extern const char* g_months[12];
extern const char* g_full_months[12];
extern const char* g_day_of_week[7];
const uint32_t NUM_DATE_PREFIX_STRINGS = 24;
extern const char* g_date_prefix_strings[NUM_DATE_PREFIX_STRINGS];
enum date_prefix_t
{
cNoPrefix = -1,
cEarlySpring,
cEarlySummer,
cEarlyAutumn,
cEarlyFall,
cEarlyWinter,
cMidSpring,
cMidSummer,
cMidAutumn,
cMidFall,
cMidWinter,
cLateSpring,
cLateSummer,
cLateAutumn,
cLateFall,
cLateWinter,
cSpring,
cSummer,
cAutumn,
cFall,
cWinter,
cEarly,
cMiddleOf,
cLate,
cEndOf,
cTotalPrefixes
};
bool is_season(date_prefix_t prefix);
int determine_month(const std::string& date, bool begins_with = true);
int determine_prefix(const std::string& date, bool begins_with = true);
int determine_day_of_week(const std::string& date, bool begins_with = true);
struct event_date
{
date_prefix_t m_prefix;
int m_year;
int m_month; // 1 based: [1,12] (NOT ZERO BASED), -1=invalid
int m_day; // 1 based: [1,31], -1=invalid
bool m_fuzzy; // ?
bool m_plural; // 's
bool m_approx; // (approximate)
bool m_estimated; // (estimated)
event_date();
event_date(const event_date& other);
bool sanity_check() const;
bool operator== (const event_date& rhs) const;
bool operator!= (const event_date& rhs) const;
event_date& operator =(const event_date& rhs);
void clear();
bool is_valid() const;
std::string get_string() const;
// Parses basic dates (not ranges).
// Date can end in "(approximate)", "(estimated)", "?", or "'s".
// 2 digit dates converted to 1900+.
// Supports year, month/year, or month/day/year.
bool parse(const char* pStr, bool fix_20century_dates);
// More advanced date range parsing, used for converting the Eberhart timeline.
// Note this doesn't support "'s", "(approximate)", "(estimated)", or converting 2 digit years to 1900'.
static bool parse_eberhart_date_range(std::string date,
event_date& begin_date,
event_date& end_date, event_date& alt_date,
int required_year = -1);
// Note the returned date may be invalid. It's only intended for sorting/comparison purposes against other sort dates.
void get_sort_date(int& year, int& month, int& day) const;
// Compares two timeline dates. true if lhs < rhs
static bool compare(const event_date& lhs, const event_date& rhs);
private:
static bool check_date_prefix(const event_date& date);
};
struct timeline_event
{
std::string m_date_str;
std::string m_time_str; // military, but currently it's in any format (not parsed yet)
std::string m_alt_date_str;
std::string m_end_date_str;
event_date m_begin_date;
event_date m_end_date;
event_date m_alt_date;
std::string m_desc; // Markdown
string_vec m_type;
string_vec m_refs; // Markdown
string_vec m_locations;
string_vec m_attributes;
string_vec m_see_also;
std::string m_rocket_type;
std::string m_rocket_altitude;
std::string m_rocket_range;
std::string m_atomic_type;
std::string m_atomic_kt;
std::string m_atomic_mt;
std::string m_source_id;
std::string m_source;
std::vector<string_pair> m_key_value_data;
std::string m_plain_desc; // Computed, ignored for comparison purposes, not deserialized from JSON
string_vec m_plain_refs; // Computed, ignored for comparison purposes, not deserialized from JSON
std::string m_search_words; // Computed, ignored for comparison purposes, not deserialized from JSON
bool operator==(const timeline_event& rhs) const;
bool operator!=(const timeline_event& rhs) const;
bool operator< (const timeline_event& rhs) const;
void print(FILE* pFile) const;
void from_json(const json& obj, const char* pSource_override, bool fix_20century_dates);
void to_json(json& j) const;
uint32_t get_crc32() const;
};
typedef std::vector<timeline_event> timeline_event_vec;
bool date_filter_single(
int start_month, int start_day, int start_year,
const event_date& evt_b, const event_date& evt_e);
bool date_filter_range(
int start_month, int start_day, int start_year,
int end_month, int end_day, int end_year,
const event_date& evt_b, const event_date& evt_e);
const uint32_t NUM_KWIC_FILE_STRINGS = 28;
static inline std::string get_kwic_index_name(uint32_t i)
{
assert(i < NUM_KWIC_FILE_STRINGS);
std::string name;
if (i < 26)
name += string_format("%c", 'a' + i);
else if (i == 26)
name += "numbers";
else
name += "misc";
return name;
}
class ufo_timeline
{
public:
ufo_timeline() :
m_name("Unnamed Timeline")
{
}
size_t size() const { return m_events.size(); }
timeline_event& operator[] (size_t i) { return m_events[i]; }
const timeline_event& operator[] (size_t i) const { return m_events[i]; }
const std::string& get_name() const { return m_name; }
void set_name(const std::string& str) { m_name = str; }
const timeline_event_vec& get_events() const { return m_events; }
timeline_event_vec& get_events() { return m_events; }
void sort()
{
std::stable_sort(m_events.begin(), m_events.end());
}
void create_json(json& j) const
{
j = json::object();
const char* pTimeline_name = m_name.c_str();
j[pTimeline_name] = json::array();
auto& ar = j[pTimeline_name];
for (size_t i = 0; i < m_events.size(); i++)
{
json obj;
m_events[i].to_json(obj);
ar.push_back(obj);
}
}
void create_plaintext();
bool write_file(const char* pFilename, bool utf8_bom = true)
{
json j;
create_json(j);
return serialize_to_json_file(pFilename, j, utf8_bom);
}
bool load_json(const char* pFilename, bool& utf8_flag, const char* pSource_override, bool fix_20century_dates);
typedef std::unordered_map<int, std::string> event_urls_map_t;
bool write_markdown(const char* pTimeline_filename, const char* pDate_range_desc, int begin_year, int end_year, bool single_file_output, event_urls_map_t& event_urls, bool output_kwic_directory);
private:
timeline_event_vec m_events;
std::string m_name;
};