Improve sorting
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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);
|
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user