Improve sorting
Some checks failed
Build Dusk / run-tests (push) Successful in 1m53s
Build Dusk / build-linux (push) Successful in 1m35s
Build Dusk / build-psp (push) Failing after 1m50s

This commit is contained in:
2026-01-06 11:30:26 -06:00
parent 0df7845f2c
commit 5e39097faa
5 changed files with 103 additions and 24 deletions

View File

@@ -169,10 +169,52 @@ bool_t inventoryItemFull(const inventory_t *inventory, const itemid_t item) {
return inventoryGetCount(inventory, item) == ITEM_STACK_QUANTITY_MAX; 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, "Inventory pointer is NULL.");
assertNotNull(inventory->storage, "Storage pointer is NULL."); assertNotNull(inventory->storage, "Storage pointer is NULL.");
assertTrue(inventory->storageSize > 0, "Storage too small."); assertTrue(inventory->storageSize > 0, "Storage too small.");
assertTrue(sortBy < INVENTORY_SORT_COUNT, "Invalid sort type.");
// Get count of used stacks // Get count of used stacks
size_t count = 0; size_t count = 0;
@@ -185,13 +227,25 @@ void inventorySortById(inventory_t *inventory) {
if(count == 0) return; // Nothing to sort if(count == 0) return; // Nothing to sort
int_t comparator(const void *a, const void *b) { // Comparator
const inventorystack_t *stackA = (const inventorystack_t*)a; sortcompare_t comparator = NULL;
const inventorystack_t *stackB = (const inventorystack_t*)b; switch(sortBy) {
if(stackA->item < stackB->item) return -1; case INVENTORY_SORT_BY_ID: {
if(stackA->item > stackB->item) return 1; comparator = reverse ? inventorySortByIdReverse : inventorySortById;
return 0; 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); sort((void*)inventory->storage, count, sizeof(inventorystack_t), comparator);
} }

View File

@@ -10,6 +10,13 @@
#define ITEM_STACK_QUANTITY_MAX UINT8_MAX #define ITEM_STACK_QUANTITY_MAX UINT8_MAX
typedef enum {
INVENTORY_SORT_BY_ID,
INVENTORY_SORT_BY_TYPE,
INVENTORY_SORT_COUNT
} inventorysort_t;
typedef struct { typedef struct {
itemid_t item; itemid_t item;
uint8_t quantity; 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); 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 inventory The inventory to sort.
* @param sortBy The sorting criteria.
* @param reverse Whether to sort in reverse order.
*/ */
void inventorySortById(inventory_t *inventory); void inventorySort(
inventory_t *inventory,
/** const inventorysort_t sortBy,
* Sorts the inventory by item type in ascending order. const bool_t reverse
* );
* @param inventory The inventory to sort.
*/
void inventorySortByType(inventory_t *inventory);

View File

@@ -19,11 +19,11 @@ const item_t ITEMS[] = {
// Potato // Potato
[ITEM_ID_POTATO] = { [ITEM_ID_POTATO] = {
.type = ITEM_TYPE_INGREDIENT .type = ITEM_TYPE_FOOD
}, },
// Apple // Apple
[ITEM_ID_APPLE] = { [ITEM_ID_APPLE] = {
.type = ITEM_TYPE_INGREDIENT .type = ITEM_TYPE_FOOD
} }
}; };

View File

@@ -13,6 +13,7 @@ typedef enum {
ITEM_TYPE_MEDICINE, ITEM_TYPE_MEDICINE,
ITEM_TYPE_INGREDIENT, ITEM_TYPE_INGREDIENT,
ITEM_TYPE_FOOD,
ITEM_TYPE_KEYITEM, ITEM_TYPE_KEYITEM,
ITEM_TYPE_COUNT ITEM_TYPE_COUNT

View File

@@ -326,7 +326,7 @@ static void test_inventoryItemFull(void **state) {
inventory.storageSize = 2; inventory.storageSize = 2;
} }
static void test_inventorySortById(void **state) { static void test_inventorySort(void **state) {
(void)state; (void)state;
inventorystack_t storage[5]; inventorystack_t storage[5];
@@ -339,24 +339,42 @@ static void test_inventorySortById(void **state) {
inventorySet(&inventory, ITEM_ID_POTION, 2); inventorySet(&inventory, ITEM_ID_POTION, 2);
// Sort by ID // Sort by ID
inventorySortById(&inventory); inventorySort(&inventory, INVENTORY_SORT_BY_ID, false);
// Check order // Check order
assert_int_equal(inventory.storage[0].item, ITEM_ID_POTION); 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[1].item, ITEM_ID_POTATO);
assert_int_equal(inventory.storage[2].item, ITEM_ID_APPLE); 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 // 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 // Should fail when given NULL storage pointer
inventory.storage = NULL; inventory.storage = NULL;
expect_assert_failure(inventorySortById(&inventory)); expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false));
inventory.storage = storage; inventory.storage = storage;
// Should fail when given zero storage size // Should fail when given zero storage size
inventory.storageSize = 0; inventory.storageSize = 0;
expect_assert_failure(inventorySortById(&inventory)); expect_assert_failure(inventorySort(&inventory, INVENTORY_SORT_BY_ID, false));
inventory.storageSize = 5; inventory.storageSize = 5;
} }
@@ -370,7 +388,7 @@ int main(int argc, char** argv) {
cmocka_unit_test(test_inventoryGetCount), cmocka_unit_test(test_inventoryGetCount),
cmocka_unit_test(test_inventoryIsFull), cmocka_unit_test(test_inventoryIsFull),
cmocka_unit_test(test_inventoryItemFull), cmocka_unit_test(test_inventoryItemFull),
cmocka_unit_test(test_inventorySortById) cmocka_unit_test(test_inventorySort),
}; };
return cmocka_run_group_tests(tests, NULL, NULL); return cmocka_run_group_tests(tests, NULL, NULL);