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
|
package main
import "core:fmt"
import "core:os"
import "core:strings"
import "core:strconv"
dayrate : f64 = 3500
Arg_Type :: enum {
NONE,
FROM,
TO,
IN,
}
Arg_Flags :: bit_set[Arg_Type]
Range_Flags_Enum :: enum {
YEAR,
MONTH,
DAY,
HOUR,
MINUTE,
}
Range_Flags :: bit_set[Range_Flags_Enum]
Filter :: struct {
ranges : Range_Flags,
time : Moment,
}
main :: proc() {
arg_count := len(os.args)-1
filters : Arg_Flags = {}
parsing : Arg_Type = .NONE
verbose := false
to_filter : Filter
from_filter : Filter
in_filter : Filter
in_filter_out : Filter
file_index_buffer : [dynamic]int
for &arg, i in os.args {
switch parsing {
case .NONE:
lower := strings.to_lower(arg, context.temp_allocator)
if lower[max(0, len(lower)-4):len(lower)] == ".ics" {
append(&file_index_buffer, i)
} else {
switch lower {
case "-t":
parsing = .TO
case "-f":
parsing = .FROM
case "-i":
parsing = .IN
case "-v":
verbose = true
case "-h":
fmt.println("statICS by Sander J. Skjegstad\n")
fmt.println("Usage:")
fmt.println("statics path/to/file.ics path/to/another_file.ics [FLAGS]")
fmt.println("\nFlags:")
fmt.println("\t-t To: Filter up to and NOT including a specific time.")
fmt.println("\t-f From: Filter from and including a specific time.")
fmt.println("\t-i In: Filter to inside a specific year, month, etc.")
fmt.println("\t-v Verbose: Prints more info.")
fmt.println("\t-h Help: Show this screen.")
fmt.println("\nFilter syntax:")
fmt.println("Filters currently only filter based on the event start time.")
fmt.println("Specify only as much as you want to filter by.")
fmt.println("YYYY-MM-DD-Hr-Mn")
fmt.println("\n-t 2015-12-31-12-45 will not count anything from that point and out.")
fmt.println("-i 2018-12 will only count things within December of 2018.")
os.exit(0)
}
}
case .FROM:
parse_to_filter(&arg, &from_filter)
filters |= {.FROM}
fmt.println("FROM filter set up from", momentToString(from_filter.time))
parsing = .NONE
case .TO:
parse_to_filter(&arg, &to_filter)
filters |= {.TO}
fmt.println("TO filter set up to", momentToString(to_filter.time))
filter_maxx(&to_filter)
parsing = .NONE
case .IN:
parse_to_filter(&arg, &in_filter)
in_filter_out = in_filter
filter_maxx(&in_filter_out)
filters |= {.IN}
fmt.println("IN filter set up from", momentToString(in_filter.time), "to", momentToString(in_filter_out.time))
parsing = .NONE
}
}
total_hours : f64 = 0;
fmt.println()
for i in file_index_buffer {
fmt.printf("%d: ", i)
fmt.println(os.args[i])
timeblocks, ok := importICS(os.args[i])
if ok {
hours : f64 = 0
for each_block in timeblocks {
if verbose do fmt.println("Timeblock:", timeblockToString(each_block))
pass := true
if .FROM in filters {
pass_from := greatEq(each_block.start, from_filter.time)
if verbose do if !pass_from do fmt.println(" FILTERED! By From filter")
pass &= pass_from
}
if .TO in filters {
pass_to := lessEq(each_block.start, to_filter.time)
if verbose do if !pass_to do fmt.println(" FILTERED! By To filter")
pass &= pass_to
}
if .IN in filters {
pass_in := lessEq(in_filter.time, each_block.start) && lessEq(each_block.start, in_filter_out.time)
if verbose do if !pass_in do fmt.println(" FILTERED! By In filter: ")
pass &= pass_in
}
if !pass do continue
hours += f64(hourcount(each_block))
}
minutes := int(f64(hours-f64(int(hours)))*60.0)
fmt.printf(" Hour count: %f\nHours & Minutes: %02d:%02d\n\n",
hours, int(hours), minutes)
total_hours += hours
} else {
// Noffin i guess
fmt.printf("\n\n")
}
}
fmt.printf("\nTOTAL\n\n")
total_final_hour_fraction : f64 = total_hours - f64(int(total_hours));
total_minutes := int(total_final_hour_fraction*60.0)
fmt.printf(" Hour count: %f\nHours & Minutes: %02d:%02d\n",
total_hours, int(total_hours), total_minutes)
return
}
parse_to_filter :: proc(input : ^string, filter : ^Filter) {
i : int = 0
ok : bool
for substring in strings.split_iterator(input, "-") {
switch i {
case 0:
filter.time.year, ok = strconv.parse_int(substring)
if !ok {fmt.eprintln("ERROR: Failed to parse year:", substring)}
filter.ranges |= {.YEAR}
case 1:
filter.time.month, ok = strconv.parse_int(substring)
if !ok {fmt.eprintln("ERROR: Failed to parse month:", substring)}
filter.ranges |= {.MONTH}
case 2:
filter.time.day, ok = strconv.parse_int(substring)
if !ok {fmt.eprintln("ERROR: Failed to parse day:", substring)}
filter.ranges |= {.DAY}
case 3:
filter.time.hours, ok = strconv.parse_int(substring)
if !ok {fmt.eprintln("ERROR: Failed to parse hours:", substring)}
filter.ranges |= {.HOUR}
case 4:
filter.time.minutes, ok = strconv.parse_int(substring)
if !ok {fmt.eprintln("ERROR: Failed to parse minutes:", substring)}
filter.ranges |= {.MINUTE}
}
i += 1
if !ok do os.exit(1)
}
}
filter_maxx :: proc(filter : ^Filter) {
// Super evil retarded bad hack, but it works!
if .MONTH not_in filter.ranges { filter.time.month = 99 }
if .DAY not_in filter.ranges { filter.time.day = 99 }
if .HOUR not_in filter.ranges { filter.time.hours = 99 }
if .MINUTE not_in filter.ranges { filter.time.minutes = 99 }
}
|