bdoap 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/bdoap +8 -0
- data/lib/bdo_alchemy_profits.rb +94 -0
- data/lib/bdo_codex/bdo_codex_searcher.rb +269 -0
- data/lib/central_market/category_search_options.rb +120 -0
- data/lib/central_market/market_searcher.rb +414 -0
- data/lib/utils/array_utils.rb +21 -0
- data/lib/utils/constants.rb +135 -0
- data/lib/utils/hash_cache.rb +34 -0
- data/lib/utils/npc_item_index.rb +526 -0
- data/lib/utils/price_calculator.rb +26 -0
- data/lib/utils/recipe_logger.rb +71 -0
- data/lib/utils/user_cli.rb +110 -0
- metadata +54 -0
@@ -0,0 +1,526 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
class NPCItemIndex
|
5
|
+
def self.get_item(id)
|
6
|
+
ITEMS.dig(id.to_i)
|
7
|
+
end
|
8
|
+
|
9
|
+
ITEMS = {
|
10
|
+
7313 => {
|
11
|
+
name: 'Apple',
|
12
|
+
id: 7313,
|
13
|
+
price: 1000,
|
14
|
+
price_per_one: 1000,
|
15
|
+
count: Float::INFINITY,
|
16
|
+
is_npc_item: true,
|
17
|
+
npc_type: 'fruit',
|
18
|
+
main_category: 25,
|
19
|
+
sub_category: 3,
|
20
|
+
},
|
21
|
+
7316 => {
|
22
|
+
name: 'Banana',
|
23
|
+
id: 7316,
|
24
|
+
price: 1000,
|
25
|
+
price_per_one: 1000,
|
26
|
+
count: Float::INFINITY,
|
27
|
+
is_npc_item: true,
|
28
|
+
npc_type: 'fruit',
|
29
|
+
main_category: 25,
|
30
|
+
sub_category: 3,
|
31
|
+
},
|
32
|
+
7314 => {
|
33
|
+
name: 'Cherry',
|
34
|
+
id: 7314,
|
35
|
+
price: 1000,
|
36
|
+
price_per_one: 1000,
|
37
|
+
count: Float::INFINITY,
|
38
|
+
is_npc_item: true,
|
39
|
+
npc_type: 'fruit',
|
40
|
+
main_category: 25,
|
41
|
+
sub_category: 3,
|
42
|
+
},
|
43
|
+
7312 => {
|
44
|
+
name: 'Paprika',
|
45
|
+
id: 7312,
|
46
|
+
price: 850,
|
47
|
+
price_per_one: 850,
|
48
|
+
count: Float::INFINITY,
|
49
|
+
is_npc_item: true,
|
50
|
+
npc_type: 'fruit',
|
51
|
+
main_category: 25,
|
52
|
+
sub_category: 3,
|
53
|
+
},
|
54
|
+
7315 => {
|
55
|
+
name: 'Pear',
|
56
|
+
id: 7315,
|
57
|
+
price: 1000,
|
58
|
+
price_per_one: 1000,
|
59
|
+
count: Float::INFINITY,
|
60
|
+
is_npc_item: true,
|
61
|
+
npc_type: 'fruit',
|
62
|
+
main_category: 25,
|
63
|
+
sub_category: 3,
|
64
|
+
},
|
65
|
+
7317 => {
|
66
|
+
name: 'Pineapple',
|
67
|
+
id: 7317,
|
68
|
+
price: 1000,
|
69
|
+
price_per_one: 1000,
|
70
|
+
count: Float::INFINITY,
|
71
|
+
is_npc_item: true,
|
72
|
+
npc_type: 'fruit',
|
73
|
+
main_category: 25,
|
74
|
+
sub_category: 3,
|
75
|
+
},
|
76
|
+
7304 => {
|
77
|
+
name: 'Strawberry',
|
78
|
+
id: 9008,
|
79
|
+
price: 700,
|
80
|
+
price_per_one: 700,
|
81
|
+
count: Float::INFINITY,
|
82
|
+
is_npc_item: true,
|
83
|
+
npc_type: 'fruit',
|
84
|
+
main_category: 25,
|
85
|
+
sub_category: 3,
|
86
|
+
},
|
87
|
+
9016 => {
|
88
|
+
name: 'Deep Frying Oil',
|
89
|
+
id: 9016,
|
90
|
+
price: 40,
|
91
|
+
price_per_one: 40,
|
92
|
+
count: Float::INFINITY,
|
93
|
+
is_npc_item: true,
|
94
|
+
npc_type: 'cooking',
|
95
|
+
},
|
96
|
+
9015 => {
|
97
|
+
name: 'Olive Oil',
|
98
|
+
id: 9015,
|
99
|
+
price: 40,
|
100
|
+
price_per_one: 40,
|
101
|
+
count: Float::INFINITY,
|
102
|
+
is_npc_item: true,
|
103
|
+
npc_type: 'cooking',
|
104
|
+
},
|
105
|
+
9007 => {
|
106
|
+
name: 'Cooking Oil',
|
107
|
+
id: 9007,
|
108
|
+
price: 20,
|
109
|
+
price_per_one: 20,
|
110
|
+
count: Float::INFINITY,
|
111
|
+
is_npc_item: true,
|
112
|
+
npc_type: 'cooking',
|
113
|
+
},
|
114
|
+
9008 => {
|
115
|
+
name: 'Sun-Dried Salt',
|
116
|
+
id: 9008,
|
117
|
+
price: 200,
|
118
|
+
price_per_one: 200,
|
119
|
+
count: Float::INFINITY,
|
120
|
+
is_npc_item: true,
|
121
|
+
npc_type: 'cooking',
|
122
|
+
},
|
123
|
+
9002 => {
|
124
|
+
name: 'Sugar',
|
125
|
+
id: 9002,
|
126
|
+
price: 20,
|
127
|
+
price_per_one: 20,
|
128
|
+
count: Float::INFINITY,
|
129
|
+
is_npc_item: true,
|
130
|
+
npc_type: 'cooking',
|
131
|
+
},
|
132
|
+
9001 => {
|
133
|
+
name: 'Salt',
|
134
|
+
id: 9001,
|
135
|
+
price: 20,
|
136
|
+
price_per_one: 20,
|
137
|
+
count: Float::INFINITY,
|
138
|
+
is_npc_item: true,
|
139
|
+
npc_type: 'cooking',
|
140
|
+
},
|
141
|
+
9059 => {
|
142
|
+
name: 'Mineral Water',
|
143
|
+
id: 9059,
|
144
|
+
price: 30,
|
145
|
+
price_per_one: 30,
|
146
|
+
count: Float::INFINITY,
|
147
|
+
is_npc_item: true,
|
148
|
+
npc_type: 'cooking',
|
149
|
+
},
|
150
|
+
16080 => {
|
151
|
+
name: 'Cron Stone',
|
152
|
+
id: 16080,
|
153
|
+
price: 3_000_000,
|
154
|
+
price_per_one: 3_000_000,
|
155
|
+
count: Float::INFINITY,
|
156
|
+
is_npc_item: true,
|
157
|
+
npc_type: 'blacksmith',
|
158
|
+
},
|
159
|
+
6656 => {
|
160
|
+
name: 'Purified Water',
|
161
|
+
id: 6656,
|
162
|
+
price: 5000,
|
163
|
+
price_per_one: 5000,
|
164
|
+
count: Float::INFINITY,
|
165
|
+
is_npc_item: true,
|
166
|
+
npc_type: 'desert goods',
|
167
|
+
main_category: 25,
|
168
|
+
sub_category: 8,
|
169
|
+
},
|
170
|
+
8041 => {
|
171
|
+
name: 'Old Moon Solvent',
|
172
|
+
id: 8041,
|
173
|
+
price: 100000,
|
174
|
+
price_per_one: 100000,
|
175
|
+
count: Float::INFINITY,
|
176
|
+
is_npc_item: true,
|
177
|
+
npc_type: 'old moon',
|
178
|
+
},
|
179
|
+
820978 => {
|
180
|
+
name: "Dawn\'s Aura",
|
181
|
+
id: 820978,
|
182
|
+
price: 5_000_000,
|
183
|
+
price_per_one: 5_000_000,
|
184
|
+
count: Float::INFINITY,
|
185
|
+
is_npc_item: true,
|
186
|
+
npc_type: 'old moon',
|
187
|
+
},
|
188
|
+
820936 => {
|
189
|
+
name: 'Spellbound Catalyst',
|
190
|
+
id: 820936,
|
191
|
+
price: 1000000,
|
192
|
+
price_per_one: 1000000,
|
193
|
+
count: Float::INFINITY,
|
194
|
+
is_npc_item: true,
|
195
|
+
npc_type: 'old moon',
|
196
|
+
},
|
197
|
+
59378 => {
|
198
|
+
name: 'Growth Reagent',
|
199
|
+
id: 59378,
|
200
|
+
price: 60000000,
|
201
|
+
price_per_one: 60000000,
|
202
|
+
count: Float::INFINITY,
|
203
|
+
is_npc_item: true,
|
204
|
+
npc_type: 'old moon',
|
205
|
+
},
|
206
|
+
4986 => {
|
207
|
+
name: "Ibellab's Essence",
|
208
|
+
id: 4986,
|
209
|
+
price: 10000,
|
210
|
+
price_per_one: 10000,
|
211
|
+
count: Float::INFINITY,
|
212
|
+
is_npc_item: true,
|
213
|
+
npc_type: 'old moon',
|
214
|
+
},
|
215
|
+
4916 => {
|
216
|
+
name: 'Blue Reagent',
|
217
|
+
id: 4916,
|
218
|
+
price: 50000,
|
219
|
+
price_per_one: 50000,
|
220
|
+
count: Float::INFINITY,
|
221
|
+
is_npc_item: true,
|
222
|
+
npc_type: 'material vendor',
|
223
|
+
},
|
224
|
+
4925 => {
|
225
|
+
name: 'Tears of the Falling Moon',
|
226
|
+
id: 4925,
|
227
|
+
price: 10000,
|
228
|
+
price_per_one: 10000,
|
229
|
+
count: Float::INFINITY,
|
230
|
+
is_npc_item: true,
|
231
|
+
npc_type: 'old moon',
|
232
|
+
},
|
233
|
+
45162 => {
|
234
|
+
name: 'Old Moon Alchemy Catalyst',
|
235
|
+
id: 45162,
|
236
|
+
price: 3500000,
|
237
|
+
price_per_one: 3500000,
|
238
|
+
count: Float::INFINITY,
|
239
|
+
is_npc_item: true,
|
240
|
+
npc_type: 'old moon',
|
241
|
+
},
|
242
|
+
5408 => {
|
243
|
+
name: 'Arrow Mushroom',
|
244
|
+
id: 5408,
|
245
|
+
price: 1000,
|
246
|
+
price_per_one: 1000,
|
247
|
+
count: Float::INFINITY,
|
248
|
+
is_npc_item: true,
|
249
|
+
npc_type: 'mushroom vendor',
|
250
|
+
main_category: 25,
|
251
|
+
sub_category: 2,
|
252
|
+
},
|
253
|
+
5410 => {
|
254
|
+
name: 'Cloud Mushroom',
|
255
|
+
id: 5410,
|
256
|
+
price: 1000,
|
257
|
+
price_per_one: 1000,
|
258
|
+
count: Float::INFINITY,
|
259
|
+
is_npc_item: true,
|
260
|
+
npc_type: 'mushroom vendor',
|
261
|
+
main_category: 25,
|
262
|
+
sub_category: 2,
|
263
|
+
},
|
264
|
+
5409 => {
|
265
|
+
name: 'Dwarf Mushroom',
|
266
|
+
id: 5409,
|
267
|
+
price: 950,
|
268
|
+
price_per_one: 950,
|
269
|
+
count: Float::INFINITY,
|
270
|
+
is_npc_item: true,
|
271
|
+
npc_type: 'mushroom vendor',
|
272
|
+
main_category: 25,
|
273
|
+
sub_category: 2,
|
274
|
+
},
|
275
|
+
5413 => {
|
276
|
+
name: 'Emperor Mushroom',
|
277
|
+
id: 5413,
|
278
|
+
price: 900,
|
279
|
+
price_per_one: 900,
|
280
|
+
count: Float::INFINITY,
|
281
|
+
is_npc_item: true,
|
282
|
+
npc_type: 'mushroom vendor',
|
283
|
+
main_category: 25,
|
284
|
+
sub_category: 2,
|
285
|
+
},
|
286
|
+
5407 => {
|
287
|
+
name: 'Fortune Teller Mushroom',
|
288
|
+
id: 5407,
|
289
|
+
price: 900,
|
290
|
+
price_per_one: 900,
|
291
|
+
count: Float::INFINITY,
|
292
|
+
is_npc_item: true,
|
293
|
+
npc_type: 'mushroom vendor',
|
294
|
+
main_category: 25,
|
295
|
+
sub_category: 2,
|
296
|
+
},
|
297
|
+
5414 => {
|
298
|
+
name: 'Ghost Mushroom',
|
299
|
+
id: 5414,
|
300
|
+
price: 1000,
|
301
|
+
price_per_one: 1000,
|
302
|
+
count: Float::INFINITY,
|
303
|
+
is_npc_item: true,
|
304
|
+
npc_type: 'mushroom vendor',
|
305
|
+
main_category: 25,
|
306
|
+
sub_category: 2,
|
307
|
+
},
|
308
|
+
5411 => {
|
309
|
+
name: 'Sky Mushroom',
|
310
|
+
id: 5411,
|
311
|
+
price: 950,
|
312
|
+
price_per_one: 950,
|
313
|
+
count: Float::INFINITY,
|
314
|
+
is_npc_item: true,
|
315
|
+
npc_type: 'mushroom vendor',
|
316
|
+
main_category: 25,
|
317
|
+
sub_category: 2,
|
318
|
+
},
|
319
|
+
5412 => {
|
320
|
+
name: 'Tiger Mushroom',
|
321
|
+
id: 5412,
|
322
|
+
price: 950,
|
323
|
+
price_per_one: 950,
|
324
|
+
count: Float::INFINITY,
|
325
|
+
is_npc_item: true,
|
326
|
+
npc_type: 'mushroom vendor',
|
327
|
+
main_category: 25,
|
328
|
+
sub_category: 2,
|
329
|
+
},
|
330
|
+
5404 => {
|
331
|
+
name: 'Dry Mane Grass',
|
332
|
+
id: 5404,
|
333
|
+
price: 525,
|
334
|
+
price_per_one: 525,
|
335
|
+
count: Float::INFINITY,
|
336
|
+
is_npc_item: true,
|
337
|
+
npc_type: 'herb vendor',
|
338
|
+
main_category: 25,
|
339
|
+
sub_category: 2,
|
340
|
+
},
|
341
|
+
5403 => {
|
342
|
+
name: 'Fire Flake Flower',
|
343
|
+
id: 5403,
|
344
|
+
price: 550,
|
345
|
+
price_per_one: 550,
|
346
|
+
count: Float::INFINITY,
|
347
|
+
is_npc_item: true,
|
348
|
+
npc_type: 'herb vendor',
|
349
|
+
main_category: 25,
|
350
|
+
sub_category: 2,
|
351
|
+
},
|
352
|
+
5405 => {
|
353
|
+
name: 'Silk Honey Grass',
|
354
|
+
id: 5405,
|
355
|
+
price: 500,
|
356
|
+
price_per_one: 500,
|
357
|
+
count: Float::INFINITY,
|
358
|
+
is_npc_item: true,
|
359
|
+
npc_type: 'herb vendor',
|
360
|
+
main_category: 25,
|
361
|
+
sub_category: 2,
|
362
|
+
},
|
363
|
+
5402 => {
|
364
|
+
name: 'Silver Azalea',
|
365
|
+
id: 5402,
|
366
|
+
price: 575,
|
367
|
+
price_per_one: 575,
|
368
|
+
count: Float::INFINITY,
|
369
|
+
is_npc_item: true,
|
370
|
+
npc_type: 'herb vendor',
|
371
|
+
main_category: 25,
|
372
|
+
sub_category: 2,
|
373
|
+
},
|
374
|
+
5401 => {
|
375
|
+
name: 'Sunrise Herb',
|
376
|
+
id: 5401,
|
377
|
+
price: 500,
|
378
|
+
price_per_one: 500,
|
379
|
+
count: Float::INFINITY,
|
380
|
+
is_npc_item: true,
|
381
|
+
npc_type: 'herb vendor',
|
382
|
+
main_category: 25,
|
383
|
+
sub_category: 2,
|
384
|
+
},
|
385
|
+
# 15009 => {
|
386
|
+
# name: 'Magic Crystal of Abundance - Healing',
|
387
|
+
# id: 15009,
|
388
|
+
# price: 30000,
|
389
|
+
# price_per_one: 30000,
|
390
|
+
# count: Float::INFINITY,
|
391
|
+
# is_npc_item: true,
|
392
|
+
# npc_type: 'jeweler',
|
393
|
+
# },
|
394
|
+
# 15001 => {
|
395
|
+
# name: 'Magic Crystal of Flame - Precision',
|
396
|
+
# id: 15001,
|
397
|
+
# price: 30000,
|
398
|
+
# price_per_one: 30000,
|
399
|
+
# count: Float::INFINITY,
|
400
|
+
# is_npc_item: true,
|
401
|
+
# npc_type: 'jeweler',
|
402
|
+
# },
|
403
|
+
# 15020 => {
|
404
|
+
# name: 'Magic Crystal of Enchantment - Agility',
|
405
|
+
# id: 15020,
|
406
|
+
# price: 30000,
|
407
|
+
# price_per_one: 30000,
|
408
|
+
# count: Float::INFINITY,
|
409
|
+
# is_npc_item: true,
|
410
|
+
# npc_type: 'jeweler',
|
411
|
+
# },
|
412
|
+
# 15019 => {
|
413
|
+
# name: 'Magic Crystal of Enchantment - Vision',
|
414
|
+
# id: 15019,
|
415
|
+
# price: 30000,
|
416
|
+
# price_per_one: 30000,
|
417
|
+
# count: Float::INFINITY,
|
418
|
+
# is_npc_item: true,
|
419
|
+
# npc_type: 'jeweler',
|
420
|
+
# },
|
421
|
+
# 15013 => {
|
422
|
+
# name: 'Magic Crystal of Nature - Ascension',
|
423
|
+
# id: 15013,
|
424
|
+
# price: 30000,
|
425
|
+
# price_per_one: 30000,
|
426
|
+
# count: Float::INFINITY,
|
427
|
+
# is_npc_item: true,
|
428
|
+
# npc_type: 'jeweler',
|
429
|
+
# },
|
430
|
+
4915 => {
|
431
|
+
name: 'Manos Stone',
|
432
|
+
id: 4915,
|
433
|
+
price: 5000000,
|
434
|
+
price_per_one: 5000000,
|
435
|
+
count: Float::INFINITY,
|
436
|
+
is_npc_item: true,
|
437
|
+
npc_type: 'jeweler',
|
438
|
+
},
|
439
|
+
4903 => {
|
440
|
+
name: 'Empty Crystal',
|
441
|
+
id: 4903,
|
442
|
+
price: 2500,
|
443
|
+
price_per_one: 2500,
|
444
|
+
count: Float::INFINITY,
|
445
|
+
is_npc_item: true,
|
446
|
+
npc_type: 'general goods',
|
447
|
+
main_category: 25,
|
448
|
+
sub_category_: 8,
|
449
|
+
},
|
450
|
+
517 => {
|
451
|
+
name: 'HP Potion (Small)',
|
452
|
+
id: 517,
|
453
|
+
price: 80,
|
454
|
+
price_per_one: 80,
|
455
|
+
count: Float::INFINITY,
|
456
|
+
is_npc_item: true,
|
457
|
+
npc_type: 'general goods',
|
458
|
+
main_category: 35,
|
459
|
+
sub_category_: 5,
|
460
|
+
},
|
461
|
+
521 => {
|
462
|
+
name: 'HP Potion (Medium)',
|
463
|
+
id: 517,
|
464
|
+
price: 200,
|
465
|
+
price_per_one: 200,
|
466
|
+
count: Float::INFINITY,
|
467
|
+
is_npc_item: true,
|
468
|
+
npc_type: 'general goods',
|
469
|
+
main_category: 35,
|
470
|
+
sub_category_: 5,
|
471
|
+
},
|
472
|
+
519 => {
|
473
|
+
name: 'HP Potion (Large)',
|
474
|
+
id: 517,
|
475
|
+
price: 500,
|
476
|
+
price_per_one: 500,
|
477
|
+
count: Float::INFINITY,
|
478
|
+
is_npc_item: true,
|
479
|
+
npc_type: 'general goods',
|
480
|
+
main_category: 35,
|
481
|
+
sub_category_: 5,
|
482
|
+
},
|
483
|
+
524 => {
|
484
|
+
name: 'HP Potion (Extra Large)',
|
485
|
+
id: 524,
|
486
|
+
price: 1250,
|
487
|
+
price_per_one: 1250,
|
488
|
+
count: Float::INFINITY,
|
489
|
+
is_npc_item: true,
|
490
|
+
npc_type: 'general goods',
|
491
|
+
main_category: 35,
|
492
|
+
sub_category_: 5,
|
493
|
+
},
|
494
|
+
520 => {
|
495
|
+
name: 'MP Potion (Small)',
|
496
|
+
id: 520,
|
497
|
+
price: 80,
|
498
|
+
price_per_one: 80,
|
499
|
+
count: Float::INFINITY,
|
500
|
+
is_npc_item: true,
|
501
|
+
npc_type: 'general goods',
|
502
|
+
main_category: 35,
|
503
|
+
sub_category_: 5,
|
504
|
+
},
|
505
|
+
522 => {
|
506
|
+
name: 'MP Potion (Large)',
|
507
|
+
id: 522,
|
508
|
+
price: 500,
|
509
|
+
price_per_one: 500,
|
510
|
+
count: Float::INFINITY,
|
511
|
+
is_npc_item: true,
|
512
|
+
npc_type: 'general goods',
|
513
|
+
},
|
514
|
+
526 => {
|
515
|
+
name: 'MP Potion (Extra Large)',
|
516
|
+
id: 526,
|
517
|
+
price: 1250,
|
518
|
+
price_per_one: 1250,
|
519
|
+
count: Float::INFINITY,
|
520
|
+
is_npc_item: true,
|
521
|
+
npc_type: 'general goods',
|
522
|
+
},
|
523
|
+
}
|
524
|
+
|
525
|
+
end
|
526
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
class PriceCalculator
|
5
|
+
def self.calculate_taxed_price(price, has_value_pack = true, fame_level = 0)
|
6
|
+
fame_levels = [1, 1.005, 1.01, 1.015]
|
7
|
+
output_price = 0.65 * ((has_value_pack ? 0.3 : 0) + fame_levels[fame_level]) * price
|
8
|
+
|
9
|
+
return output_price if output_price == Float::INFINITY
|
10
|
+
return 0 unless output_price.is_a?(Numeric) && output_price.to_s.downcase != 'nan'
|
11
|
+
output_price.floor
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.format_price(price)
|
15
|
+
return price.to_s.downcase if price == Float::INFINITY
|
16
|
+
return 0 unless price.is_a?(Numeric) && price.to_s.downcase != 'nan'
|
17
|
+
"¤#{price.floor.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse}".to_s.downcase
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.format_num(num)
|
21
|
+
return num.to_s.downcase if num == Float::INFINITY
|
22
|
+
return 0 unless num.is_a?(Numeric) && num.to_s.downcase != 'nan'
|
23
|
+
num.floor.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse.to_s.downcase
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
# log recipe information
|
5
|
+
class RecipeLogger
|
6
|
+
def initialize(cli)
|
7
|
+
@cli = cli
|
8
|
+
end
|
9
|
+
|
10
|
+
def padstr(str, space_around = ' ', len = 32, pad_with = '.')
|
11
|
+
padded = "#{str}#{space_around}"
|
12
|
+
"#{padded.ljust(len, pad_with)}#{space_around}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def seconds_to_str(seconds)
|
16
|
+
return seconds if seconds == Float::INFINITY
|
17
|
+
["#{(seconds / 3600).floor}h", "#{(seconds / 60 % 60).floor}m", "#{(seconds % 60).floor}s"]
|
18
|
+
.select { |str| str =~ /[1-9]/ }.join(" ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_recipe_data(item, selected_recipe, max_potion_count, item_market_sell_price, total_ingredient_cost, average_procs, total_max_ingredient_cost, raw_max_market_sell_price, max_taxed_sell_profit_after_procs, raw_profit_with_procs, taxed_sell_profit_after_procs)
|
22
|
+
stock_counts = []
|
23
|
+
|
24
|
+
selected_recipe.each do |ingredient|
|
25
|
+
amount_required_for_max_potions = max_potion_count * ingredient[:quant]
|
26
|
+
ingredient_market_sell_price = ingredient[:price].to_i
|
27
|
+
|
28
|
+
next if (amount_required_for_max_potions * ingredient_market_sell_price) < 0
|
29
|
+
|
30
|
+
raw_max_ingredient_sell_price = ingredient[:price] * max_potion_count
|
31
|
+
formatted_price = @cli.yellow PriceCalculator.format_price ingredient_market_sell_price
|
32
|
+
formatted_max_price = @cli.yellow PriceCalculator.format_price raw_max_ingredient_sell_price
|
33
|
+
formatted_potion_amount = @cli.yellow PriceCalculator.format_num(ingredient[:quant]).rjust(4, ' ')
|
34
|
+
formatted_max_potion_amount = @cli.yellow PriceCalculator.format_num max_potion_count * ingredient[:quant]
|
35
|
+
formatted_stock_count = @cli.yellow PriceCalculator.format_num ingredient[:total_in_stock]
|
36
|
+
formatted_npc_information = ingredient[:is_npc_item] ? @cli.yellow(" (sold by #{ingredient[:npc_type]} npcs)") : ''
|
37
|
+
|
38
|
+
stock_counts.push "#{formatted_potion_amount} [max: #{formatted_max_potion_amount}] [#{ingredient[:id]}] #{@cli.yellow "#{ingredient[:name].downcase}: #{formatted_stock_count}"} in stock#{formatted_npc_information}. price: #{formatted_price} [for max: #{formatted_max_price}]"
|
39
|
+
end
|
40
|
+
|
41
|
+
market_stock_string = item[:total_in_stock] > 2000 ? @cli.red(PriceCalculator.format_num(item[:total_in_stock])) : @cli.green(PriceCalculator.format_num(item[:total_in_stock]))
|
42
|
+
|
43
|
+
trade_count_string = item[:total_trade_count] < 10_000_000 ? @cli.red(PriceCalculator.format_num(item[:total_trade_count])) : @cli.green(PriceCalculator.format_num(item[:total_trade_count]))
|
44
|
+
|
45
|
+
estimated_craft_time = 1.2
|
46
|
+
calculated_time = max_potion_count * estimated_craft_time
|
47
|
+
crafting_time_string = calculated_time > 21600 ? @cli.red((seconds_to_str(calculated_time))) : @cli.green((seconds_to_str(calculated_time)))
|
48
|
+
silver_per_hour = max_taxed_sell_profit_after_procs.to_f / (calculated_time.to_f / 3600)
|
49
|
+
|
50
|
+
information = " #{@cli.yellow "[#{item[:id]}] [#{item[:name].downcase}], recipe id: #{selected_recipe[0][:for_recipe_id]}"}
|
51
|
+
|
52
|
+
#{padstr("market price of item")}#{@cli.yellow PriceCalculator.format_price item_market_sell_price}
|
53
|
+
#{padstr("market stock of item")}#{market_stock_string}
|
54
|
+
#{padstr("total trades of item")}#{trade_count_string}
|
55
|
+
#{padstr("you can craft")}#{@cli.yellow PriceCalculator.format_num max_potion_count}
|
56
|
+
#{padstr("theoretical max output")}#{@cli.yellow PriceCalculator.format_num(max_potion_count * average_procs)}
|
57
|
+
#{padstr("cost of ingredients")}#{@cli.yellow PriceCalculator.format_price total_ingredient_cost} (accounting for average #{average_procs} / craft)
|
58
|
+
#{padstr("max cost of ingredients")}#{@cli.yellow PriceCalculator.format_price total_max_ingredient_cost} (accounting for average #{average_procs} / craft)
|
59
|
+
#{padstr("time to craft max")}#{crafting_time_string} (accounting for average #{estimated_craft_time}s / craft due to typical server delay)
|
60
|
+
|
61
|
+
\t#{stock_counts.join "\n\t"}
|
62
|
+
|
63
|
+
total income for max items before cost subtraction #{@cli.green PriceCalculator.format_price raw_max_market_sell_price}
|
64
|
+
#{padstr("total taxed silver per hour")}#{@cli.green PriceCalculator.format_price(silver_per_hour) } silver / hour
|
65
|
+
#{padstr("total untaxed profit")}#{@cli.green PriceCalculator.format_price raw_profit_with_procs} [max: #{@cli.green PriceCalculator.format_price(raw_profit_with_procs * max_potion_count)}]
|
66
|
+
#{padstr("total taxed profit")}#{@cli.green PriceCalculator.format_price taxed_sell_profit_after_procs} [max: #{@cli.green PriceCalculator.format_price(max_taxed_sell_profit_after_procs)}]
|
67
|
+
"
|
68
|
+
{ recipe_info: information, silver_per_hour: silver_per_hour }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|