DungeonCrawl
Loading...
Searching...
No Matches
item_database.c
Go to the documentation of this file.
1
5#include "item_database.h"
6
8
9#include <string.h>
10
11#define SQL_SELECT_COUNT_POTIONS "SELECT COUNT(*) FROM potion"
12#define SQL_SELECT_ALL_POTIONS "SELECT PO_TYPE, PO_NAME, PO_VALUE FROM potion"
13#define SQL_SELECT_COUNT_GEARS "SELECT COUNT(*) FROM gear"
14#define SQL_SELECT_ALL_GEARS "WITH SplitAbilities AS (SELECT GR_ID, " \
15 "AB_NUMBER, " \
16 "ROW_NUMBER() OVER (PARTITION BY GR_ID ORDER BY AB_ID) AS RowNum, " \
17 "COUNT(*) OVER (PARTITION BY GR_ID) AS TotalAbilities " \
18 "FROM ability, " \
19 "gear " \
20 "JOIN gear_involves_ability ON main.ability.AB_ID = gear_involves_ability.GA_AB_ID AND " \
21 "gear_involves_ability.GA_GR_ID = gear.GR_ID), " \
22 "GroupedAbilities AS (SELECT GR_ID, " \
23 "TotalAbilities, " \
24 "MAX(CASE WHEN RowNum = 1 THEN AB_NUMBER END) AS Ability_1, " \
25 "MAX(CASE WHEN RowNum = 2 THEN AB_NUMBER END) AS Ability_2, " \
26 "MAX(CASE WHEN RowNum = 3 THEN AB_NUMBER END) AS Ability_3, " \
27 "MAX(CASE WHEN RowNum = 4 THEN AB_NUMBER END) AS Ability_4 " \
28 "FROM SplitAbilities " \
29 "GROUP BY GR_ID) " \
30 "SELECT GR_NAME, " \
31 "GR_IDENT, " \
32 "SL_NUMBER, " \
33 "GR_ARMOR, " \
34 "GR_MAGICRESIST, " \
35 "ST_STRENGTH, " \
36 "ST_DEXTERNITY, " \
37 "ST_INTELLIGENCE, " \
38 "ST_CONSTITUTION, " \
39 "coalesce(TotalAbilities, 0) AS TotalAbilities, " \
40 "coalesce(Ability_1, 0) AS Ability_1, " \
41 "coalesce(Ability_2, 0) AS Ability_2, " \
42 "coalesce(Ability_3, 0) AS Ability_3, " \
43 "coalesce(Ability_4, 0) AS Ability_4 " \
44 "FROM gear, " \
45 "slot, " \
46 "stats " \
47 "JOIN gear_located_slot ON main.slot.SL_ID = gear_located_slot.GL_SL_ID AND main.gear.GR_ID = gear_located_slot.GL_GR_ID " \
48 "JOIN gear_has_stats ON stats.ST_ID = gear_has_stats.GT_ST_ID AND gear.GR_ID = main.gear_has_stats.GT_GR_ID " \
49 "LEFT JOIN GroupedAbilities ON GroupedAbilities.GR_ID = main.gear.GR_ID"
50
52 // Check if the database connection is open
53 if (!db_is_open(db_connection)) {
54 log_msg(ERROR, "Potion", "Database connection is not open");
55 return NULL;
56 }
57
58 // Prepare the SQL statement to select all potions
59 sqlite3_stmt* stmt;
60 int rc = sqlite3_prepare_v2(db_connection->db, SQL_SELECT_ALL_POTIONS, -1, &stmt, NULL);
61 if (rc != SQLITE_OK) {
62 log_msg(ERROR, "Potion", "Failed to prepare statement: %s", sqlite3_errmsg(db_connection->db));
63 return NULL;
64 }
65 // Count the number of potions in the database
66 const int potion_counted = count_potions_in_db(db_connection);
67 // Allocate memory for the potion table
68 if (potion_counted <= 0) {
69 log_msg(ERROR, "Potion", "No potions found in the database");
70 sqlite3_finalize(stmt);
71 return NULL;
72 }
73 potion_init_t* potion_init_table = malloc(sizeof(potion_init_t) * potion_counted);
74 if (potion_init_table == NULL) {
75 log_msg(ERROR, "Potion", "Failed to allocate memory for potion table");
76 sqlite3_finalize(stmt);
77 return NULL;
78 }
79 // Execute the statement and fetch the results
80 int index = 0;
81 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && index < potion_counted) {
82 potion_init_table[index].potion_type = sqlite3_column_int(stmt, 0);
83 potion_init_table[index].name = strdup((const char*) sqlite3_column_text(stmt, 1));
84 potion_init_table[index].value = sqlite3_column_int(stmt, 2);
85 index++;
86 }
87 if (rc != SQLITE_DONE) {
88 log_msg(ERROR, "Potion", "Failed to execute statement: %s", sqlite3_errmsg(db_connection->db));
89 free(potion_init_table);
90 sqlite3_finalize(stmt);
91 return NULL;
92 }
93 // Finalize the statement
94 sqlite3_finalize(stmt);
95 return potion_init_table;
96}
97
98void free_potion_table_from_db(potion_init_t* potion_init_table, const db_connection_t* db_connection) {
99 if (potion_init_table == NULL) { return; }
100
101 for (int i = 0; i < count_potions_in_db(db_connection); i++) {
102 free(potion_init_table[i].name);
103 potion_init_table[i].name = NULL;
104 }
105 free(potion_init_table);
106}
107
108int count_potions_in_db(const db_connection_t* db_connection) {
109 // Check if the database connection is open
110 if (!db_is_open(db_connection)) {
111 log_msg(ERROR, "Potion", "Database connection is not open");
112 return 0;
113 }
114 // Prepare the SQL statement
115 sqlite3_stmt* stmt_count;
116 int rc = sqlite3_prepare_v2(db_connection->db, SQL_SELECT_COUNT_POTIONS, -1, &stmt_count, NULL);
117 if (rc != SQLITE_OK) {
118 log_msg(ERROR, "Potion", "Failed to prepare statement: %s", sqlite3_errmsg(db_connection->db));
119 return 0;
120 }
121 // Execute the statement
122 rc = sqlite3_step(stmt_count);
123 if (rc != SQLITE_ROW) {
124 log_msg(ERROR, "Potion", "Failed to execute statement: %s", sqlite3_errmsg(db_connection->db));
125 sqlite3_finalize(stmt_count);
126 return 0;
127 }
128 // Get the count of potions
129 const int potion_count = sqlite3_column_int(stmt_count, 0);
130 sqlite3_finalize(stmt_count);
131 // Check if there are any potions
132 if (potion_count == 0) {
133 log_msg(ERROR, "Potion", "No potions found in the database");
134 return 0;
135 }
136 return potion_count;
137}
138
140 // Check if the database connection is open
141 if (!db_is_open(db_connection)) {
142 log_msg(ERROR, "Gear", "Database connection is not open");
143 return NULL;
144 }
145 // Prepare the SQL statement to select all gears
146 sqlite3_stmt* stmt;
147 int rc = sqlite3_prepare_v2(db_connection->db, SQL_SELECT_ALL_GEARS, -1, &stmt, NULL);
148 if (rc != SQLITE_OK) {
149 log_msg(ERROR, "Gear", "Failed to prepare statement: %s", sqlite3_errmsg(db_connection->db));
150 return NULL;
151 }
152 // Count the number of gears in the database
153 const int gear_counted = count_gear_in_db(db_connection);
154 // Allocate memory for the gear table
155 if (gear_counted <= 0) {
156 log_msg(ERROR, "Gear", "No gears found in the database");
157 sqlite3_finalize(stmt);
158 return NULL;
159 }
160 gear_init_t* gear_init_table = malloc(sizeof(gear_init_t) * gear_counted);
161 if (gear_init_table == NULL) {
162 log_msg(ERROR, "Gear", "Failed to allocate memory for gear table");
163 sqlite3_finalize(stmt);
164 return NULL;
165 }
166 // Execute the statement and fetch the results
167 int index = 0;
168 while ((rc = sqlite3_step(stmt)) == SQLITE_ROW && index < gear_counted) {
169 gear_init_table[index].name = strdup((const char*) sqlite3_column_text(stmt, 0));
170 gear_init_table[index].gear_identifier = sqlite3_column_int(stmt, 1);
171 gear_init_table[index].slot = (gear_slot_t) sqlite3_column_int(stmt, 2);
172 gear_init_table[index].defenses.armor = sqlite3_column_int(stmt, 3);
173 gear_init_table[index].defenses.magic_resist = sqlite3_column_int(stmt, 4);
174 gear_init_table[index].stats.strength = sqlite3_column_int(stmt, 5);
175 gear_init_table[index].stats.dexterity = sqlite3_column_int(stmt, 6);
176 gear_init_table[index].stats.intelligence = sqlite3_column_int(stmt, 7);
177 gear_init_table[index].stats.constitution = sqlite3_column_int(stmt, 8);
178 gear_init_table[index].num_abilities = sqlite3_column_int(stmt, 9);
179 gear_init_table[index].ability_names[0] = sqlite3_column_int(stmt, 10);
180 gear_init_table[index].ability_names[1] = sqlite3_column_int(stmt, 11);
181 gear_init_table[index].ability_names[2] = sqlite3_column_int(stmt, 12);
182 gear_init_table[index].ability_names[3] = sqlite3_column_int(stmt, 13);
183 index++;
184 }
185 if (rc != SQLITE_DONE) {
186 log_msg(ERROR, "Gear", "Failed to execute statement: %s", sqlite3_errmsg(db_connection->db));
187 free(gear_init_table);
188 sqlite3_finalize(stmt);
189 return NULL;
190 }
191 // Finalize the statement
192 sqlite3_finalize(stmt);
193 return gear_init_table;
194}
195
196void free_gear_table_from_db(gear_init_t* gear_init_table, const db_connection_t* db_connection) {
197 if (gear_init_table == NULL) { return; }
198
199 for (int i = 0; i < count_gear_in_db(db_connection); i++) {
200 free(gear_init_table[i].name);
201 gear_init_table[i].name = NULL;
202 }
203 free(gear_init_table);
204}
205
206int count_gear_in_db(const db_connection_t* db_connection) {
207 // Check if the database connection is open
208 if (!db_is_open(db_connection)) {
209 log_msg(ERROR, "Gear", "Database connection is not open");
210 return 0;
211 }
212 // Prepare the SQL statement
213 sqlite3_stmt* stmt_count;
214 int rc = sqlite3_prepare_v2(db_connection->db, SQL_SELECT_COUNT_GEARS, -1, &stmt_count, NULL);
215 if (rc != SQLITE_OK) {
216 log_msg(ERROR, "Gear", "Failed to prepare statement: %s", sqlite3_errmsg(db_connection->db));
217 return 0;
218 }
219 // Execute the statement
220 rc = sqlite3_step(stmt_count);
221 if (rc != SQLITE_ROW) {
222 log_msg(ERROR, "Gear", "Failed to execute statement: %s", sqlite3_errmsg(db_connection->db));
223 sqlite3_finalize(stmt_count);
224 return 0;
225 }
226 // Get the count of gears
227 const int gear_count = sqlite3_column_int(stmt_count, 0);
228 sqlite3_finalize(stmt_count);
229 // Check if there are any gears
230 if (gear_count == 0) {
231 log_msg(ERROR, "Gear", "No gears found in the database");
232 return 0;
233 }
234 return gear_count;
235}
int db_is_open(const db_connection_t *db_connection)
This function is to check if the database is open.
Definition database.c:27
gear_init_t * init_gear_table_from_db(const db_connection_t *db_connection)
Get the gear table from the database.
potion_init_t * init_potion_table_from_db(const db_connection_t *db_connection)
Get the potion table from the database.
void free_gear_table_from_db(gear_init_t *gear_init_table, const db_connection_t *db_connection)
Clean up the gear table Call this function to free the memory allocated for the gear table.
int count_potions_in_db(const db_connection_t *db_connection)
Count the number of potions in the database.
int count_gear_in_db(const db_connection_t *db_connection)
Count the number of gears in the database.
void free_potion_table_from_db(potion_init_t *potion_init_table, const db_connection_t *db_connection)
Clean up the potion table Call this function to free the memory allocated for the potion table.
Declares functions to load and free potion and gear tables from the game database,...
void log_msg(const log_level_t level, const char *module, const char *format,...)
Logs a formatted message with a specified log level and module.
Definition logger.c:246
Header file for logging functionality of the game.
This struct is used for the database connection in SQLite.
Definition database.h:22
To get gear table from the database, we need to define a struct This struct is for the initialization...
To get potion table from the database, we need to define a struct This struct is for the initializati...