diff --git a/src/item/inventory.c b/src/item/inventory.c index 797a375..e1cb5ca 100644 --- a/src/item/inventory.c +++ b/src/item/inventory.c @@ -169,10 +169,52 @@ bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item) { return inventoryGetCount(inventory, item) == ITEM_STACK_QUANTITY_MAX; } -void inventorySortById(inventory_t *inventory) { +// Sorters +int_t inventorySortById(const void *a, const void *b) { + const inventorystack_t *stackA = (const inventorystack_t*)a; + const inventorystack_t *stackB = (const inventorystack_t*)b; + if(stackA->item < stackB->item) return -1; + if(stackA->item > stackB->item) return 1; + return 0; +} + +int_t inventorySortByIdReverse(const void *a, const void *b) { + const inventorystack_t *stackA = (const inventorystack_t*)a; + const inventorystack_t *stackB = (const inventorystack_t*)b; + if(stackA->item < stackB->item) return 1; + if(stackA->item > stackB->item) return -1; + return 0; +} + +int_t inventorySortByType(const void *a, const void *b) { + const inventorystack_t *stackA = (const inventorystack_t*)a; + const inventorystack_t *stackB = (const inventorystack_t*)b; + const itemtype_t typeA = ITEMS[stackA->item].type; + const itemtype_t typeB = ITEMS[stackB->item].type; + if(typeA < typeB) return -1; + if(typeA > typeB) return 1; + return 0; +} + +int_t inventorySortByTypeReverse(const void *a, const void *b) { + const inventorystack_t *stackA = (const inventorystack_t*)a; + const inventorystack_t *stackB = (const inventorystack_t*)b; + const itemtype_t typeA = ITEMS[stackA->item].type; + const itemtype_t typeB = ITEMS[stackB->item].type; + if(typeA < typeB) return 1; + if(typeA > typeB) return -1; + return 0; +} + +void inventorySort( + inventory_t *inventory, + const inventorysort_t sortBy, + const bool_t reverse +) { assertNotNull(inventory, "Inventory pointer is NULL."); assertNotNull(inventory->storage, "Storage pointer is NULL."); assertTrue(inventory->storageSize > 0, "Storage too small."); + assertTrue(sortBy < INVENTORY_SORT_COUNT, "Invalid sort type."); // Get count of used stacks size_t count = 0; @@ -185,13 +227,25 @@ void inventorySortById(inventory_t *inventory) { if(count == 0) return; // Nothing to sort - int_t comparator(const void *a, const void *b) { - const inventorystack_t *stackA = (const inventorystack_t*)a; - const inventorystack_t *stackB = (const inventorystack_t*)b; - if(stackA->item < stackB->item) return -1; - if(stackA->item > stackB->item) return 1; - return 0; + // Comparator + sortcompare_t comparator = NULL; + switch(sortBy) { + case INVENTORY_SORT_BY_ID: { + comparator = reverse ? inventorySortByIdReverse : inventorySortById; + break; + }; + + case INVENTORY_SORT_BY_TYPE: { + comparator = reverse ? inventorySortByTypeReverse : inventorySortByType; + break; + }; + + default: + assertUnreachable("Invalid sort type."); + break; } + assertNotNull(comparator, "Comparator function is NULL."); + sort((void*)inventory->storage, count, sizeof(inventorystack_t), comparator); } \ No newline at end of file diff --git a/src/item/inventory.h b/src/item/inventory.h index 2a30fba..c802f90 100644 --- a/src/item/inventory.h +++ b/src/item/inventory.h @@ -10,6 +10,13 @@ #define ITEM_STACK_QUANTITY_MAX UINT8_MAX +typedef enum { + INVENTORY_SORT_BY_ID, + INVENTORY_SORT_BY_TYPE, + + INVENTORY_SORT_COUNT +} inventorysort_t; + typedef struct { itemid_t item; uint8_t quantity; @@ -103,15 +110,14 @@ bool_t inventoryIsFull(const inventory_t *inventory); bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item); /** - * Sorts the inventory by item ID in ascending order. + * Sorts the inventory based on the specified criteria. * * @param inventory The inventory to sort. + * @param sortBy The sorting criteria. + * @param reverse Whether to sort in reverse order. */ -void inventorySortById(inventory_t *inventory); - -/** - * Sorts the inventory by item type in ascending order. - * - * @param inventory The inventory to sort. - */ -void inventorySortByType(inventory_t *inventory); \ No newline at end of file +void inventorySort( + inventory_t *inventory, + const inventorysort_t sortBy, + const bool_t reverse +); \ No newline at end of file diff --git a/src/item/item.c b/src/item/item.c index e8a53f3..5c93681 100644 --- a/src/item/item.c +++ b/src/item/item.c @@ -19,11 +19,11 @@ const item_t ITEMS[] = { // Potato [ITEM_ID_POTATO] = { - .type = ITEM_TYPE_INGREDIENT + .type = ITEM_TYPE_FOOD }, // Apple [ITEM_ID_APPLE] = { - .type = ITEM_TYPE_INGREDIENT + .type = ITEM_TYPE_FOOD } }; \ No newline at end of file diff --git a/src/item/itemtype.h b/src/item/itemtype.h index 9defc8e..c63d246 100644 --- a/src/item/itemtype.h +++ b/src/item/itemtype.h @@ -13,6 +13,7 @@ typedef enum { ITEM_TYPE_MEDICINE, ITEM_TYPE_INGREDIENT, + ITEM_TYPE_FOOD, ITEM_TYPE_KEYITEM, ITEM_TYPE_COUNT diff --git a/test/item/test_inventory.c b/test/item/test_inventory.c index c8d6349..0af63a2 100644 --- a/test/item/test_inventory.c +++ b/test/item/test_inventory.c @@ -326,7 +326,7 @@ static void test_inventoryItemFull(void **state) { inventory.storageSize = 2; } -static void test_inventorySortById(void **state) { +static void test_inventorySort(void **state) { (void)state; inventorystack_t storage[5]; @@ -339,24 +339,42 @@ static void test_inventorySortById(void **state) { inventorySet(&inventory, ITEM_ID_POTION, 2); // Sort by ID - inventorySortById(&inventory); + inventorySort(&inventory, INVENTORY_SORT_BY_ID, false); // Check order assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); assert_int_equal(inventory.storage[2].item, ITEM_ID_APPLE); + // Sort by ID reverse + inventorySort(&inventory, INVENTORY_SORT_BY_ID, true); + assert_int_equal(inventory.storage[0].item, ITEM_ID_APPLE); + assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); + assert_int_equal(inventory.storage[2].item, ITEM_ID_POTION); + + // Sort by type + inventorySort(&inventory, INVENTORY_SORT_BY_ID, false); + assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); + assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); + assert_int_equal(inventory.storage[2].item, ITEM_ID_APPLE); + + // Sort by type reverse + inventorySort(&inventory, INVENTORY_SORT_BY_ID, true); + assert_int_equal(inventory.storage[0].item, ITEM_ID_APPLE); + assert_int_equal(inventory.storage[1].item, ITEM_ID_POTATO); + assert_int_equal(inventory.storage[2].item, ITEM_ID_POTION); + // Should fail when given NULL inventory pointer - expect_assert_failure(inventorySortById(NULL)); + expect_assert_failure(inventorySort(NULL, INVENTORY_SORT_BY_ID, false)); // Should fail when given NULL storage pointer inventory.storage = NULL; - expect_assert_failure(inventorySortById(&inventory)); + expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false)); inventory.storage = storage; // Should fail when given zero storage size inventory.storageSize = 0; - expect_assert_failure(inventorySortById(&inventory)); + expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false)); inventory.storageSize = 5; } @@ -370,7 +388,7 @@ int main(int argc, char** argv) { cmocka_unit_test(test_inventoryGetCount), cmocka_unit_test(test_inventoryIsFull), cmocka_unit_test(test_inventoryItemFull), - cmocka_unit_test(test_inventorySortById) + cmocka_unit_test(test_inventorySort), }; return cmocka_run_group_tests(tests, NULL, NULL);