aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-21 17:26:09 +0200
committerMosder <xmosder12@gmail.com>2026-07-21 17:26:09 +0200
commit5c0e713713143bad475a92d20ee5fe215b5bafd3 (patch)
tree2f0dfb464b46181644f28a6be59a88f2ef6305d4
parentf73349115edbc75021885eefd33ee33ee504d9a7 (diff)
feat: added parsing for gear
-rw-r--r--Makefile1
-rw-r--r--analyzer/parser/fight_results.c169
-rw-r--r--analyzer/parser/fight_results.h375
-rw-r--r--analyzer/render.c2
-rw-r--r--analyzer/render.h24
-rw-r--r--analyzer/utils/roman.c16
-rw-r--r--analyzer/utils/roman.h12
-rw-r--r--csv/artifact_sizes.csv5
-rw-r--r--csv/orbs.csv3
9 files changed, 482 insertions, 125 deletions
diff --git a/Makefile b/Makefile
index afb61fd..72f94e0 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@ utils:
$(CC) $(CFLAGS) -c analyzer/utils/time.c
$(CC) $(CFLAGS) -c analyzer/utils/tcp.c
$(CC) $(CFLAGS) -c analyzer/utils/tcp_seq_math.c
+ $(CC) $(CFLAGS) -c analyzer/utils/roman.c
parser:
$(CC) $(CFLAGS) -c analyzer/parser/parser.c
diff --git a/analyzer/parser/fight_results.c b/analyzer/parser/fight_results.c
index f201fb1..c1d6420 100644
--- a/analyzer/parser/fight_results.c
+++ b/analyzer/parser/fight_results.c
@@ -4,8 +4,11 @@
#include <stdlib.h>
#include <string.h>
+#include "csv/id_to_artifact_size.h"
#include "csv/id_to_item_name.h"
+#include "csv/id_to_orb_name.h"
#include "csv/id_to_saturation_type.h"
+#include "utils/roman.h"
// function to cleanup fight results to be used in ParsedData struct
void cleanup_fight_results(void *data) {
@@ -70,15 +73,18 @@ void get_struct_data(size_t field_count, TypeEnum *field_types, void **field_poi
}
}
+// free struct fields which are STRING
+void destroy_struct(size_t field_count, TypeEnum *field_types, void **field_pointers) {
+ for (size_t i = 0; i < field_count; i++) {
+ if (field_types[i] == STRING)
+ free(*(char **)field_pointers[i]);
+ }
+}
+
void destroy_entity_results(EntityResults results) {
- free(results.name);
- free(results.field7);
- free(results.gear);
- free(results.items);
- free(results.drifs);
- free(results.field29);
- free(results.field34);
- free(results.saturation);
+ TypeEnum field_types[ENTITY_FIELD_COUNT] = ENTITY_FIELD_TYPES;
+ void *field_pointers[ENTITY_FIELD_COUNT] = ENTITY_FIELD_ADDRESSES(results);
+ destroy_struct(ENTITY_FIELD_COUNT, field_types, field_pointers);
}
// get entity results from the string
@@ -96,35 +102,148 @@ Item *expand_items(Item *items, size_t *items_capacity, size_t to_fit) {
return realloc(items, *items_capacity * sizeof(Item));
}
-void add_gear(FriendlyResults *results, size_t *items_capacity, char *gear_str) {
- if (strlen(gear_str) == 0)
+void destroy_gear(Gear gear) {
+ TypeEnum field_types[GEAR_FIELD_COUNT] = GEAR_FIELD_TYPES;
+ void *field_pointers[GEAR_FIELD_COUNT] = GEAR_FIELD_ADDRESSES(gear);
+ destroy_struct(GEAR_FIELD_COUNT, field_types, field_pointers);
+}
+
+Gear get_gear(char *data, size_t length) {
+ Gear gear;
+ TypeEnum field_types[GEAR_FIELD_COUNT] = GEAR_FIELD_TYPES;
+ void *field_pointers[GEAR_FIELD_COUNT] = GEAR_FIELD_ADDRESSES(gear);
+ get_struct_data(GEAR_FIELD_COUNT, field_types, field_pointers, SEPARATOR_GEAR_FIELDS, data, length);
+ return gear;
+}
+
+void destroy_gear_info(GearInfo gear_info) {
+ TypeEnum field_types[GEAR_INFO_FIELD_COUNT] = GEAR_INFO_FIELD_TYPES;
+ void *field_pointers[GEAR_INFO_FIELD_COUNT] = GEAR_INFO_FIELD_ADDRESSES(gear_info);
+ destroy_struct(GEAR_INFO_FIELD_COUNT, field_types, field_pointers);
+}
+
+GearInfo get_gear_info(char *data, size_t length) {
+ GearInfo gear_info;
+ TypeEnum field_types[GEAR_INFO_FIELD_COUNT] = GEAR_INFO_FIELD_TYPES;
+ void *field_pointers[GEAR_INFO_FIELD_COUNT] = GEAR_INFO_FIELD_ADDRESSES(gear_info);
+ get_struct_data(GEAR_INFO_FIELD_COUNT, field_types, field_pointers, SEPARATOR_GEAR_INFO_FIELDS, data, length);
+ return gear_info;
+}
+
+void destroy_orb(Orb orb) {
+ TypeEnum field_types[ORB_FIELD_COUNT] = ORB_FIELD_TYPES;
+ void *field_pointers[ORB_FIELD_COUNT] = ORB_FIELD_ADDRESSES(orb);
+ destroy_struct(ORB_FIELD_COUNT, field_types, field_pointers);
+}
+
+Orb get_orb(char *data, size_t length) {
+ Orb orb;
+ TypeEnum field_types[ORB_FIELD_COUNT] = ORB_FIELD_TYPES;
+ void *field_pointers[ORB_FIELD_COUNT] = ORB_FIELD_ADDRESSES(orb);
+ get_struct_data(ORB_FIELD_COUNT, field_types, field_pointers, SEPARATOR_ORB_FIELDS, data, length);
+ return orb;
+}
+
+char *get_artifact_size(int artifact_size_id) {
+ return artifact_size_id < id_to_artifact_size_len ? id_to_artifact_size[artifact_size_id] : "null";
+}
+
+char *get_orb_name(int orb_name_id) {
+ return orb_name_id < id_to_orb_name_len ? id_to_orb_name[orb_name_id] : "null";
+}
+
+void get_stars(char *buffer, int incr_above_b1) {
+ char star_types[] = {'B', 'S', 'G'};
+ buffer[0] = star_types[incr_above_b1 / 3];
+ buffer[1] = incr_above_b1 % 3 + 1 + '0';
+ buffer[2] = '\0';
+}
+
+void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) {
+ if (strlen(gears_str) == 0)
return;
- // TODO: parse
- if (results->num_items >= *items_capacity)
- results->items = expand_items(results->items, items_capacity, results->num_items + 1);
+ char *gears_separator;
+ do {
+ gears_separator = strstr(gears_str, SEPARATOR_GEARS);
+ Gear gear = get_gear(gears_str, gears_separator ? gears_separator - gears_str : strlen(gears_str));
+
+ // if there are still gears - modify gears_str pointer
+ if (gears_separator)
+ gears_str = gears_separator + strlen(SEPARATOR_DRIFS);
+
+ // expand if needed
+ if (results->num_items >= *items_capacity)
+ results->items = expand_items(results->items, items_capacity, results->num_items + 1);
+
+ Item item;
+
+ GearInfo gear_info = get_gear_info(gear.info, strlen(gear.info));
+ char buffer[SINGLE_ITEM_BUFFER_LEN];
+ char roman[5];
+ to_roman(roman, gear_info.rank);
+ sprintf(buffer, "[%s] %s", roman, gear_info.name);
+ switch (gear.type) {
+ case TYPE_SYNG_NORMAL:
+ // atoi should be fine, since syng_tier starts from 1 for syngs
+ if (atoi(gear.syng_tier))
+ sprintf(buffer, "%s (%d)", buffer, gear_info.lvl);
+ break;
+ default: {
+ char stars[3];
+ get_stars(stars, gear_info.stars);
+ sprintf(buffer, "%s (%s)", buffer, stars);
+ break;
+ }
+ }
+ item.data = strdup(buffer);
+ destroy_gear_info(gear_info);
- Item item;
- item.data = strdup(gear_str);
- item.type = RARE;
- results->items[results->num_items++] = item;
+ switch (gear.type) {
+ case TYPE_SYNG_NORMAL:
+ // atoi should be fine, since syng_tier starts from 1 for syngs
+ item.type = atoi(gear.syng_tier) ? SYNG : NORMAL;
+ break;
+ case TYPE_SET:
+ item.type = SET;
+ break;
+ case TYPE_RARE:
+ item.type = RARE;
+ break;
+ default:
+ item.type = EPIC;
+ break;
+ }
+
+ results->items[results->num_items++] = item;
+
+ // add orb to items if it exists
+ if (strlen(gear.orb)) {
+ Item item;
+ char buffer[SINGLE_ITEM_BUFFER_LEN];
+ Orb orb = get_orb(gear.orb, strlen(gear.orb));
+ sprintf(buffer, "%sorb %s", get_artifact_size(orb.size), get_orb_name(orb.id));
+ item.data = strdup(buffer);
+ destroy_orb(orb);
+ item.type = ORB;
+ results->items[results->num_items++] = item;
+ }
+
+ destroy_gear(gear);
+ } while (gears_separator);
}
void destroy_drif(Drif drif) {
- free(drif.field1);
- free(drif.field4);
- free(drif.field11);
- free(drif.field12);
- free(drif.name);
- free(drif.field18);
- free(drif.field19);
+ TypeEnum field_types[DRIF_FIELD_COUNT] = DRIF_FIELD_TYPES;
+ void *field_pointers[DRIF_FIELD_COUNT] = DRIF_FIELD_ADDRESSES(drif);
+ destroy_struct(DRIF_FIELD_COUNT, field_types, field_pointers);
}
Drif get_drif(char *data, size_t length) {
Drif drif;
TypeEnum field_types[DRIF_FIELD_COUNT] = DRIF_FIELD_TYPES;
void *field_pointers[DRIF_FIELD_COUNT] = DRIF_FIELD_ADDRESSES(drif);
- get_struct_data(DRIF_FIELD_COUNT, field_types, field_pointers, SEPARATOR_DRIF_INFO, data, length);
+ get_struct_data(DRIF_FIELD_COUNT, field_types, field_pointers, SEPARATOR_DRIF_FIELDS, data, length);
return drif;
}
diff --git a/analyzer/parser/fight_results.h b/analyzer/parser/fight_results.h
index 76083ab..59d1e45 100644
--- a/analyzer/parser/fight_results.h
+++ b/analyzer/parser/fight_results.h
@@ -14,6 +14,10 @@
#define SEPARATOR_ENTITY "[--]"
#define SEPARATOR_RESULT "&"
+// values of field "team" in EntityResults
+#define TEAM_FRIEND 1
+#define TEAM_ENEMY 2
+
// EntityResults structure:
// field (SEPARATOR_RESULT field)*
// fields are defined in order in the EntityResults struct
@@ -54,44 +58,44 @@
/* field32 */ INT, \
/* field33 */ INT, \
/* field34 */ STRING, \
- /* saturation */ STRING \
+ /* saturation */ STRING, \
}
#define ENTITY_FIELD_ADDRESSES(entity_results) {\
- &entity_results.team, \
- &entity_results.name, \
- &entity_results.exp, \
- &entity_results.field4, \
- &entity_results.gold, \
- &entity_results.field6, \
- &entity_results.field7, \
- &entity_results.gear, \
- &entity_results.field9, \
- &entity_results.items, \
- &entity_results.field11, \
- &entity_results.field12, \
- &entity_results.field13, \
- &entity_results.field14, \
- &entity_results.field15, \
- &entity_results.level, \
- &entity_results.field17, \
- &entity_results.field18, \
- &entity_results.field19, \
- &entity_results.field20, \
- &entity_results.field21, \
- &entity_results.field22, \
- &entity_results.field23, \
- &entity_results.field24, \
- &entity_results.psycho, \
- &entity_results.drifs, \
- &entity_results.splinters, \
- &entity_results.field28, \
- &entity_results.field29, \
- &entity_results.field30, \
- &entity_results.field31, \
- &entity_results.field32, \
- &entity_results.field33, \
- &entity_results.field34, \
- &entity_results.saturation \
+ &entity_results.team, \
+ &entity_results.name, \
+ &entity_results.exp, \
+ &entity_results.field4, \
+ &entity_results.gold, \
+ &entity_results.field6, \
+ &entity_results.field7, \
+ &entity_results.gear, \
+ &entity_results.field9, \
+ &entity_results.items, \
+ &entity_results.field11, \
+ &entity_results.field12, \
+ &entity_results.field13, \
+ &entity_results.field14, \
+ &entity_results.field15, \
+ &entity_results.level, \
+ &entity_results.field17, \
+ &entity_results.field18, \
+ &entity_results.field19, \
+ &entity_results.field20, \
+ &entity_results.field21, \
+ &entity_results.field22, \
+ &entity_results.field23, \
+ &entity_results.field24, \
+ &entity_results.psycho, \
+ &entity_results.drifs, \
+ &entity_results.splinters, \
+ &entity_results.field28, \
+ &entity_results.field29, \
+ &entity_results.field30, \
+ &entity_results.field31, \
+ &entity_results.field32, \
+ &entity_results.field33, \
+ &entity_results.field34, \
+ &entity_results.saturation, \
}
// clang-format on
typedef struct {
@@ -137,87 +141,280 @@ typedef struct {
#define SINGLE_ITEM_BUFFER_LEN 128
#define SEPARATOR_ITEMS "[-]"
#define SEPARATOR_DRIFS "???" // TODO: change it to correct one which idk at this moment
-#define SEPARATOR_DRIF_INFO ","
+#define SEPARATOR_GEARS "???" // TODO: change it to correct one which idk at this moment
// Item struct - for keeping item string and type
-typedef enum { NORMAL, DRIF, SYNG, SET, RARE, EPIC } ItemType;
+typedef enum { NORMAL, DRIF, ORB, SYNG, SET, RARE, EPIC } ItemType;
typedef struct {
char *data;
ItemType type;
} Item;
// Drif structure:
-// field (SEPARATOR_DRIF field)*
+// field (SEPARATOR_DRIF_FIELDS field)*
// fields are defined in order in the Drif struct
-#define DRIF_FIELD_COUNT 19
+#define DRIF_FIELD_COUNT 18
+#define SEPARATOR_DRIF_FIELDS ","
// clang-format off
#define DRIF_FIELD_TYPES { \
- /* field1 */ STRING, \
- /* field2 */ INT, \
- /* field3 */ INT, \
- /* field4 */ STRING, \
- /* field5 */ INT, \
- /* field6 */ INT, \
- /* field7 */ FLOAT, \
- /* field8 */ FLOAT, \
- /* field9 */ INT, \
- /* field10 */ INT, \
- /* field11 */ STRING, \
- /* field12 */ STRING, \
- /* field13 */ INT, \
- /* field14 */ INT, \
- /* field15 */ INT, \
- /* field16 */ INT, \
- /* name */ STRING, \
- /* field18 */ STRING, \
- /* field19 */ STRING, \
+ /* field1 */ STRING, \
+ /* field2 */ INT, \
+ /* size */ INT, \
+ /* field4 */ STRING, \
+ /* field5 */ INT, \
+ /* id */ INT, \
+ /* value1 */ FLOAT, \
+ /* value2 */ FLOAT, \
+ /* field9 */ INT, \
+ /* field10 */ INT, \
+ /* field11 */ STRING, \
+ /* size_str */ STRING, \
+ /* field13 */ INT, \
+ /* power */ INT, \
+ /* field15 */ INT, \
+ /* field16 */ INT, \
+ /* name */ STRING, \
+ /* field18 */ STRING, \
}
#define DRIF_FIELD_ADDRESSES(drif) {\
- &drif.field1, \
- &drif.field2, \
- &drif.field3, \
- &drif.field4, \
- &drif.field5, \
- &drif.field6, \
- &drif.field7, \
- &drif.field8, \
- &drif.field9, \
- &drif.field10, \
- &drif.field11, \
- &drif.field12, \
- &drif.field13, \
- &drif.field14, \
- &drif.field15, \
- &drif.field16, \
- &drif.name, \
- &drif.field18, \
- &drif.field19, \
+ &drif.field1, \
+ &drif.field2, \
+ &drif.size, \
+ &drif.field4, \
+ &drif.field5, \
+ &drif.id, \
+ &drif.value1, \
+ &drif.value2, \
+ &drif.field9, \
+ &drif.field10, \
+ &drif.field11, \
+ &drif.size_str, \
+ &drif.field13, \
+ &drif.power, \
+ &drif.field15, \
+ &drif.field16, \
+ &drif.name, \
+ &drif.field18, \
}
// clang-format on
typedef struct {
- char *field1;
+ char *field1; // just says "drif"
int field2;
- int field3;
+ int size; // 1 - sub, 2 - bi, 3 - magni, 4 - arcy
char *field4;
int field5;
- int field6;
- float field7;
- float field8;
+ int id; // id of orb type
+ float value1; // value1, value2 (in %) - one is start value, the other is value per lvl (both are the same)
+ float value2; // value1, value2 (in %) - one is start value, the other is value per lvl (both are the same)
int field9;
int field10;
char *field11;
- char *field12;
+ char *size_str; // sub - small, medium - bi, big - magni, ??? - arcy
int field13;
- int field14;
+ int power; // how much space it takes
int field15;
int field16;
char *name; // <size>drif <name>
char *field18;
- char *field19;
} Drif;
-// values of field "team"
-#define TEAM_FRIEND 1
-#define TEAM_ENEMY 2
+// Gear structure:
+// field (SEPARATOR_GEAR_FIELDS field)*
+// fields are defined in order in the Gear struct
+#define GEAR_FIELD_COUNT 19
+#define SEPARATOR_GEAR_FIELDS "$"
+// values of field "type" in Gear
+#define TYPE_SYNG_NORMAL 0
+#define TYPE_SET 1
+#define TYPE_RARE 2
+// clang-format off
+#define GEAR_FIELD_TYPES { \
+ /* stats */ STRING, \
+ /* resistances */ STRING, \
+ /* info */ STRING, \
+ /* reqs */ STRING, \
+ /* field5 */ STRING, \
+ /* psycho */ STRING, \
+ /* field7 */ STRING, \
+ /* field8 */ STRING, \
+ /* field9 */ STRING, \
+ /* syng_tier */ STRING, \
+ /* field11 */ INT, \
+ /* field12 */ INT, \
+ /* field13 */ INT, \
+ /* field14 */ STRING, \
+ /* type */ INT, \
+ /* field16 */ INT, \
+ /* orb */ STRING, \
+ /* field18 */ STRING, \
+ /* field19 */ STRING, \
+}
+#define GEAR_FIELD_ADDRESSES(gear) {\
+ &gear.stats, \
+ &gear.resistances, \
+ &gear.info, \
+ &gear.reqs, \
+ &gear.field5, \
+ &gear.psycho, \
+ &gear.field7, \
+ &gear.field8, \
+ &gear.field9, \
+ &gear.syng_tier, \
+ &gear.field11, \
+ &gear.field12, \
+ &gear.field13, \
+ &gear.field14, \
+ &gear.type, \
+ &gear.field16, \
+ &gear.orb, \
+ &gear.field18, \
+ &gear.field19, \
+}
+// clang-format on
+typedef struct {
+ char *stats; // strength, dexterity, power, knowledge, hp, mana, stamina
+ char *resistances; // slashing, crushing, piercing, fire, cold, energy, mental
+ char *info; // GearInfo struct data
+ char *reqs; // requirements (str, dex, pow, know), weight, something else
+ char *field5;
+ char *psycho; // psycho effects (id,%) for syngs
+ char *field7;
+ char *field8;
+ char *field9;
+ char *syng_tier; // lvl 20 - 1, lvl 30 - 2, etc..., null for non-syngs
+ int field11;
+ int field12;
+ int field13;
+ char *field14;
+ int type; // 0 - normal item or syng, 1 - set, 2 - rare
+ int field16; // 10 for rare, -1 for others ???
+ char *orb; // orb info
+ char *field18;
+ char *field19;
+} Gear;
+
+// GearInfo structure:
+// field (SEPARATOR_GEAR_INFO_FIELDS field)*
+// fields are defined in order in the GearInfo struct
+#define GEAR_INFO_FIELD_COUNT 23
+#define SEPARATOR_GEAR_INFO_FIELDS ","
+// clang-format off
+#define GEAR_INFO_FIELD_TYPES { \
+ /* name */ STRING, \
+ /* field2 */ INT, \
+ /* lvl */ INT, \
+ /* price */ INT, \
+ /* field5 */ INT, \
+ /* field6 */ INT, \
+ /* field7 */ INT, \
+ /* rank */ INT, \
+ /* field9 */ INT, \
+ /* field10 */ INT, \
+ /* field11 */ INT, \
+ /* durability */ INT, \
+ /* field13 */ STRING, \
+ /* field14 */ INT, \
+ /* field15 */ INT, \
+ /* charges */ FLOAT, \
+ /* field17 */ STRING, \
+ /* field18 */ INT, \
+ /* stars */ INT, \
+ /* field20 */ INT, \
+ /* field21 */ INT, \
+ /* field22 */ INT, \
+ /* field23 */ INT, \
+}
+#define GEAR_INFO_FIELD_ADDRESSES(gear_info) {\
+ &gear_info.name, \
+ &gear_info.field2, \
+ &gear_info.lvl, \
+ &gear_info.price, \
+ &gear_info.field5, \
+ &gear_info.field6, \
+ &gear_info.field7, \
+ &gear_info.rank, \
+ &gear_info.field9, \
+ &gear_info.field10, \
+ &gear_info.field11, \
+ &gear_info.durability, \
+ &gear_info.field13, \
+ &gear_info.field14, \
+ &gear_info.field15, \
+ &gear_info.charges, \
+ &gear_info.field17, \
+ &gear_info.field18, \
+ &gear_info.stars, \
+ &gear_info.field20, \
+ &gear_info.field21, \
+ &gear_info.field22, \
+ &gear_info.field23, \
+}
+// clang-format on
+typedef struct {
+ char *name; // item name
+ int field2;
+ int lvl; // level requirement
+ int price; // gold price value
+ int field5;
+ int field6;
+ int field7;
+ int rank; // I-XII
+ int field9;
+ int field10;
+ int field11;
+ int durability; // in %
+ char *field13;
+ int field14;
+ int field15;
+ float charges; // charge count
+ char *field17;
+ int field18;
+ int stars; // incrustation level: 0 - b1, 1 - b2, ... (-100 for syngs)
+ int field20;
+ int field21;
+ int field22;
+ int field23;
+} GearInfo;
+
+// Orb structure:
+// field (SEPARATOR_ORB_FIELDS field)*
+// fields are defined in order in the Orb struct
+#define ORB_FIELD_COUNT 9
+#define SEPARATOR_ORB_FIELDS ","
+// clang-format off
+#define ORB_FIELD_TYPES { \
+ /* field1 */ STRING, \
+ /* field2 */ INT, \
+ /* field3 */ INT, \
+ /* field4 */ STRING, \
+ /* field5 */ INT, \
+ /* id */ INT, \
+ /* size */ INT, \
+ /* value */ FLOAT, \
+ /* field9 */ STRING, \
+}
+#define ORB_FIELD_ADDRESSES(orb) {\
+ &orb.field1, \
+ &orb.field2, \
+ &orb.field3, \
+ &orb.field4, \
+ &orb.field5, \
+ &orb.id, \
+ &orb.size, \
+ &orb.value, \
+ &orb.field9, \
+}
+// clang-format on
+typedef struct {
+ char *field1; // just says "orb"
+ int field2;
+ int field3;
+ char *field4;
+ int field5;
+ int id; // id of orb type
+ int size; // 1 - sub, 2 - bi, 3 - magni, 4 - arcy
+ float value; // value in % you gain from the orb
+ char *field9;
+} Orb;
// fight results data for friendly
typedef struct {
diff --git a/analyzer/render.c b/analyzer/render.c
index 28d1673..0fdd334 100644
--- a/analyzer/render.c
+++ b/analyzer/render.c
@@ -81,6 +81,8 @@ int item_type_to_color(ItemType type) {
return COLOR_WHITE;
case DRIF:
return COLOR_YELLOW;
+ case ORB:
+ return COLOR_GOLD;
case SYNG:
return COLOR_RED;
case SET:
diff --git a/analyzer/render.h b/analyzer/render.h
index 97958d1..843cea5 100644
--- a/analyzer/render.h
+++ b/analyzer/render.h
@@ -4,6 +4,8 @@
#include "parser/fight_results.h"
// ANSI escape sequence colors
+#define COLOR_GOLD 33
+#define COLOR_GRAY 90
#define COLOR_RED 91
#define COLOR_GREEN 92
#define COLOR_YELLOW 93
@@ -34,24 +36,24 @@
#define TABLE_COLUMN_NAMES {"Nick (LVL)", "EXP", "Gold", "Psycho", "Saturation", "Splinters"}
#define TABLE_COLUMN_COLORS {COLOR_WHITE, COLOR_WHITE, COLOR_YELLOW, COLOR_AQUA, COLOR_GREEN, COLOR_BLUE}
#define TABLE_COLUMN_WIDTHS { \
- TABLE_NAME_LVL_WIDTH, \
- TABLE_EXP_WIDTH, \
- TABLE_GOLD_WIDTH, \
- TABLE_PSYCHO_WIDTH, \
+ TABLE_NAME_LVL_WIDTH, \
+ TABLE_EXP_WIDTH, \
+ TABLE_GOLD_WIDTH, \
+ TABLE_PSYCHO_WIDTH, \
TABLE_SATURATION_WIDTH, \
- TABLE_SPLINTERS_WIDTH \
+ TABLE_SPLINTERS_WIDTH, \
}
#define TABLE_LINE_WIDTH ( \
TABLE_LINE_START_WIDTH + \
- TABLE_NAME_LVL_WIDTH + \
- TABLE_EXP_WIDTH + \
- TABLE_GOLD_WIDTH + \
- TABLE_PSYCHO_WIDTH + \
+ TABLE_NAME_LVL_WIDTH + \
+ TABLE_EXP_WIDTH + \
+ TABLE_GOLD_WIDTH + \
+ TABLE_PSYCHO_WIDTH + \
TABLE_SATURATION_WIDTH + \
- TABLE_SPLINTERS_WIDTH + \
+ TABLE_SPLINTERS_WIDTH + \
(TABLE_COLUMN_COUNT - 1) * TABLE_LINE_SEPARATOR_WIDTH + \
- TABLE_LINE_END_WIDTH \
+ TABLE_LINE_END_WIDTH \
)
// clang-format on
diff --git a/analyzer/utils/roman.c b/analyzer/utils/roman.c
new file mode 100644
index 0000000..9ea2bbb
--- /dev/null
+++ b/analyzer/utils/roman.c
@@ -0,0 +1,16 @@
+#include "utils/roman.h"
+
+#include <stddef.h>
+#include <string.h>
+
+void to_roman(char *buffer, int number) {
+ buffer[0] = '\0';
+ int nums[ROMAN_CHAR_COUNT] = ROMAN_NUMS;
+ char *chars[ROMAN_CHAR_COUNT] = ROMAN_CHARS;
+ for (size_t i = 0; i < ROMAN_CHAR_COUNT; i++) {
+ for (size_t j = 0; j < number / nums[i]; j++) {
+ strcat(buffer, chars[i]);
+ }
+ number %= nums[i];
+ }
+}
diff --git a/analyzer/utils/roman.h b/analyzer/utils/roman.h
new file mode 100644
index 0000000..b4f5d3f
--- /dev/null
+++ b/analyzer/utils/roman.h
@@ -0,0 +1,12 @@
+// utils/roman.h
+// functions for roman numbers
+
+#define ROMAN_CHAR_COUNT 13
+#define ROMAN_NUMS {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
+#define ROMAN_CHARS {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
+
+// convert a arabic number to roman number
+// params:
+// buffer - buffer to save the roman number to
+// number - arabic number to convert
+extern void to_roman(char *buffer, int number);
diff --git a/csv/artifact_sizes.csv b/csv/artifact_sizes.csv
new file mode 100644
index 0000000..a9af916
--- /dev/null
+++ b/csv/artifact_sizes.csv
@@ -0,0 +1,5 @@
+id,artifact_size
+1,Sub
+2,Bi
+3,Magni
+4,Arcy
diff --git a/csv/orbs.csv b/csv/orbs.csv
new file mode 100644
index 0000000..02dfde4
--- /dev/null
+++ b/csv/orbs.csv
@@ -0,0 +1,3 @@
+id,orb_name
+21,Ha'at
+12,Se'at