Algorithms & Data Structures

Narrative & Reflection

CS 360 Version

The original application with basic list display and no data processing.

Original Capabilities

  • Basic linear search only
  • No sorting functionality
  • No data visualization
  • Static data presentation

CS 499 Enhanced Version

The enhanced application with custom sorting, graphing, and predictive logic.

Enhanced Capabilities

  • In-memory TimSort (O(N log N))
  • Custom Linear Interpolation Graphing
  • Predictive Burn-Rate Analysis
  • Real-time filtering logic
  • Optimized data aggregation

Reflection on the Process

Learning & Challenges: A key challenge was mapping the time (X-axis) and quantity (Y-axis) to the device's screen pixels for the graph. Before writing the Java code, I used pseudocode to segment the graphing functionality, determining how to map time-series data to screen coordinates. This approach allowed me to solve the logic problem of dynamic scaling on paper first, ensuring the implementation was efficient.

Course Outcomes Met:


Dynamic Sorting Implementation

Instead of asking the database to sort the list every time (which is slow), I used Java's built-in sorting tool to do it in the phone's memory. This makes the list sort instantly when you click the headers.


// InventoryViewModel.java

/**
 * Sorts the items based on the given criteria.
 * Toggles sort order if the same criteria is selected again.
 * Cycle: ASC -> DESC -> NONE -> ASC.
 *
 * @param criteria The criteria to sort by (Name, Quantity, etc.).
 */
public void sortItems(SortCriteria criteria) {
    if (currentSortCriteria == criteria) {
        // Cycle: ASC -> DESC -> NONE -> ASC
        switch (currentSortOrder) {
            case ASC: currentSortOrder = SortOrder.DESC; break;
            case DESC: currentSortOrder = SortOrder.NONE; break;
            case NONE: currentSortOrder = SortOrder.ASC; break;
        }
    } else {
        currentSortCriteria = criteria;
        currentSortOrder = SortOrder.ASC; // Default to ascending for new criteria
    }
    processList();
}
            

Custom Graphing Logic

To show the history graph, I didn't use a heavy 3rd-party library. Instead, I wrote a custom math formula. It calculates exactly where to draw lines on the screen based on the time and the quantity of items, so it looks good on any screen size.

The Logic:
x_pixel = (timestamp - min_time) / (max_time - min_time) * view_width
y_pixel = view_height - ((quantity - min_qty) / (max_qty - min_qty) * view_height)

Predicting Future Needs

To show I can solve complex problems, I wrote a "burn rate" calculator. It looks at how many items were used in the last 24 hours and calculates how fast they are being used.

Design Trade-offs: I chose to perform the aggregation (summing usage) via SQL rather than fetching all raw logs into memory. This reduces the memory footprint of the application significantly, especially as the history grows. Letting the database engine handle the math is more efficient than iterating through objects in Java.

Validation & Edge Cases: I validated the algorithm by simulating different usage patterns, such as sudden spikes in consumption versus steady usage. I also handled edge cases like "sparse logs" (where an item hasn't been used in days) by defaulting to a safe state to prevent division-by-zero errors.

How it works: The app asks the database for the total usage over the last day. It then does the math to guess when the stock will hit zero. This helps the user order more items before they run out.


// InventoryRepository.java

for (InventoryItem item : items) {
    // ...
    if (!recommendationAdded) {
        long totalConsumed = usageMap.containsKey(item.getId()) ? usageMap.get(item.getId()) : 0;
        // Calculate rate per minute based on the 24-hour window
        double minuteRate = totalConsumed / (double) (24 * 60);

        // If we have usage, check if stock is critically low based on rate
        if (minuteRate > 0) {
            double minutesOfStockLeft = (item.getQuantity() > 0) ? item.getQuantity() / minuteRate : 0;

            // If less than 24 hours (1440 mins) of stock remaining, recommend ordering
            if (minutesOfStockLeft < 1440.0) {
                long suggestedOrder = (long) ((minuteRate * 2880) - item.getQuantity()); // Target 48 hours stock
                if (suggestedOrder <= 0) suggestedOrder = (long) (minuteRate * 1440); // Ensure positive order

                recommendations.add(/* ... formatted string ... */);
            }
        }
    }
}
            
View Full Source