+107
-86
src/condition_overload.gleam
+107
-86
src/condition_overload.gleam
···
13
13
pub fn main() {
14
14
let assert Ok(search) =
15
15
argv.load().arguments
16
-
|> list.first()
16
+
|> list.reduce(fn(acc, x) { acc <> " " <> x })
17
17
as "search has to be supplied as argument"
18
18
let search = string.lowercase(search)
19
19
20
-
let _ =
21
-
[
22
-
"https://wiki.warframe.com/w/Condition_Overload_%28Mechanic%29?action=edit§ion=7",
23
-
"https://wiki.warframe.com/w/Condition_Overload_%28Mechanic%29?action=edit§ion=8",
24
-
]
25
-
|> list.map(get_page_data)
26
-
|> promise.await_list()
27
-
|> promise.map(result.values)
28
-
|> promise.map(list.flatten)
29
-
|> promise.map(
30
-
list.find(_, fn(item) {
31
-
item.names
32
-
|> list.any(fn(name) {
33
-
let lower = string.lowercase(name)
34
-
string.contains(lower, search)
35
-
})
36
-
}),
37
-
)
38
-
// print value
39
-
|> promise.map(result.map(_, fn(x) { io.println(format_row(x)) }))
40
-
// print error
41
-
|> promise.map(
42
-
result.map_error(_, fn(x) {
43
-
io.println("something went wrong: " <> string.inspect(x))
44
-
}),
45
-
)
20
+
[
21
+
"https://wiki.warframe.com/w/Condition_Overload_%28Mechanic%29?action=edit§ion=7",
22
+
"https://wiki.warframe.com/w/Condition_Overload_%28Mechanic%29?action=edit§ion=8",
23
+
]
24
+
|> list.map(get_page_data)
25
+
|> promise.await_list()
26
+
|> promise.map(result.values)
27
+
|> promise.map(list.flatten)
28
+
|> promise.map(
29
+
list.filter(_, fn(item) {
30
+
item.names
31
+
|> list.any(fn(name) {
32
+
let lower = string.lowercase(name)
33
+
string.contains(lower, search)
34
+
})
35
+
}),
36
+
)
37
+
|> promise.map(list.take(_, 4))
38
+
// print values
39
+
|> promise.map(list.map(_, fn(x) { io.println(format_row(x)) }))
46
40
}
47
41
42
+
// format row into human readable string
43
+
//
48
44
fn format_row(row: Row) -> String {
49
-
case row {
45
+
let rating = case row {
50
46
Row(math_behavior: "Multiplying", ..) -> "very good"
51
47
Row(math_behavior: "Adding", co_bonus_rel_base:, ..) -> {
52
48
let co_bonus_rel_base =
···
68
64
69
65
_ -> "some secret third option"
70
66
}
67
+
68
+
let Row(
69
+
names:,
70
+
attack:,
71
+
projectile: _,
72
+
base_damage: _,
73
+
co_bonus_at_100: _,
74
+
co_bonus_rel_base: _,
75
+
math_behavior: _,
76
+
notes: _,
77
+
) = row
78
+
79
+
let name =
80
+
list.first(names)
81
+
|> result.unwrap("")
82
+
83
+
"The '"
84
+
<> name
85
+
<> "' '"
86
+
<> attack
87
+
<> "' attack has a "
88
+
<> rating
89
+
<> " interaction with GunCO"
71
90
}
72
91
73
92
// do request and return Row if successful
···
158
177
fn process_lines(lines: List(String), acc: List(Row)) -> List(Row) {
159
178
case lines {
160
179
["|{{Weapon|" <> name_line, ..rest] -> {
161
-
let row = case rest {
162
-
["|-", ..] -> {
163
-
parse_values_line(name_line)
164
-
}
165
-
[] | _ -> {
166
-
let #(names, _) = parse_names(name_line, [])
167
-
let row = parse_values_vertical(names, rest)
168
-
row
169
-
}
170
-
}
180
+
let #(row, rest) = parse_row(name_line, rest)
171
181
172
182
process_lines(rest, [row, ..acc])
173
183
}
···
188
198
//
189
199
// |{{Weapon|Braton}}/{{Weapon|MK1-Braton|MK1}}/{{Weapon|Braton Prime|Prime}}/{{Weapon|Braton Vandal|Vandal}}||Incarnon Form AoE||AoE||74||70||95%||Adding||Listed values for Braton Prime with inactive Daring Reverie. Radial hit only receives CO bonus on target directly hit by bullet. AoE does not scale off multishot.
190
200
//
191
-
fn parse_values_line(line: String) -> Row {
192
-
let #(names, rest) = parse_names(line, [])
193
-
194
-
let sep = splitter.new(["||"])
195
-
196
-
let #(attack, _, rest) = splitter.split(sep, rest)
197
-
let #(projectile, _, rest) = splitter.split(sep, rest)
198
-
let #(base_damage, _, rest) = splitter.split(sep, rest)
199
-
let #(co_bonus_at_100, _, rest) = splitter.split(sep, rest)
200
-
let #(co_bonus_rel_base, _, rest) = splitter.split(sep, rest)
201
-
let #(math_behavior, _, rest) = splitter.split(sep, rest)
202
-
let #(notes, _, _) = splitter.split(sep, rest)
203
-
Row(
204
-
names:,
205
-
attack:,
206
-
projectile:,
207
-
base_damage:,
208
-
co_bonus_at_100:,
209
-
co_bonus_rel_base:,
210
-
math_behavior:,
211
-
notes:,
212
-
)
213
-
}
214
-
215
201
// multi line - single & multi name
216
202
//
217
203
// |{{Weapon|Evensong}}
···
224
210
// |Does not apply
225
211
// |-
226
212
//
227
-
fn parse_values_vertical(names: List(String), lines: List(String)) -> Row {
228
-
let #(attack, rest) = parse_value(lines)
229
-
let #(projectile, rest) = parse_value(rest)
230
-
let #(base_damage, rest) = parse_value(rest)
231
-
let #(co_bonus_at_100, rest) = parse_value(rest)
232
-
let #(co_bonus_rel_base, rest) = parse_value(rest)
233
-
let #(math_behavior, rest) = parse_value(rest)
234
-
let #(notes, _) = parse_value(rest)
213
+
fn parse_row(name_line: String, lines: List(String)) -> #(Row, List(String)) {
214
+
let #(names, line_rest) = parse_names(name_line, [])
235
215
236
-
Row(
237
-
names:,
238
-
attack:,
239
-
projectile:,
240
-
base_damage:,
241
-
co_bonus_at_100:,
242
-
co_bonus_rel_base:,
243
-
math_behavior:,
244
-
notes:,
216
+
let #(attack, line_rest, rest) = parse_next_value(line_rest, lines)
217
+
let #(projectile, line_rest, rest) = parse_next_value(line_rest, rest)
218
+
let #(base_damage, line_rest, rest) = parse_next_value(line_rest, rest)
219
+
let #(co_bonus_at_100, line_rest, rest) = parse_next_value(line_rest, rest)
220
+
let #(co_bonus_rel_base, line_rest, rest) = parse_next_value(line_rest, rest)
221
+
let #(math_behavior, line_rest, rest) = parse_next_value(line_rest, rest)
222
+
let #(notes, _, rest) = parse_next_value(line_rest, rest)
223
+
224
+
#(
225
+
Row(
226
+
names:,
227
+
attack:,
228
+
projectile:,
229
+
base_damage:,
230
+
co_bonus_at_100:,
231
+
co_bonus_rel_base:,
232
+
math_behavior:,
233
+
notes:,
234
+
),
235
+
rest,
245
236
)
246
237
}
247
238
248
-
// read values one at a time until the next |-
249
-
//
250
-
fn parse_value(lines: List(String)) {
239
+
fn parse_next_value(
240
+
line_rest: String,
241
+
lines: List(String),
242
+
) -> #(String, String, List(String)) {
243
+
let sep = splitter.new(["||"])
244
+
245
+
case splitter.split(sep, line_rest) {
246
+
#("", _, _) -> do_lines(sep, lines)
247
+
#(value, "||", line_rest) -> #(value, line_rest, lines)
248
+
#(value, "", _) -> #(value, "", lines)
249
+
#(_, _, _) -> do_lines(sep, lines)
250
+
}
251
+
}
252
+
253
+
fn do_lines(sep, lines) {
251
254
case lines {
252
-
["|-", ..] -> #("", lines)
253
-
["|" <> value, ..rest] -> #(value, rest)
254
-
[] | [_] | [_, _, ..] -> #("", lines)
255
+
["|-", ..] -> #("", "", lines)
256
+
["|" <> value, ..rest] -> {
257
+
case splitter.split(sep, value) {
258
+
#(value, "||", line_rest) -> #(value, line_rest, rest)
259
+
#(value, _, _) -> #(value, "", rest)
260
+
}
261
+
}
262
+
[] | [_] | [_, _, ..] -> #("", "", lines)
255
263
}
256
264
}
257
265
···
262
270
263
271
let #(name, split_by, rest) = splitter.split(sep, line)
264
272
273
+
let name =
274
+
string.split_once(name, "|")
275
+
|> result.map(pair.first)
276
+
|> result.unwrap(name)
277
+
265
278
case split_by {
266
279
"}}/{{Weapon|" | "}}/{{Weapon" -> parse_names(rest, [name, ..acc])
267
-
_ -> #([name, ..acc], rest)
280
+
_ -> {
281
+
// handle special cases where extra text is included after the weapon names
282
+
let rest =
283
+
string.split_once(rest, "||")
284
+
|> result.map(pair.second)
285
+
|> result.unwrap(rest)
286
+
287
+
#([name, ..acc], rest)
288
+
}
268
289
}
269
290
}