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:
- Outcome 3: Designing and evaluating algorithmic solutions for sorting and data visualization, balancing the trade-offs between memory usage and database I/O.
- Outcome 4: Using innovative techniques to implement a custom graphing engine, delivering a specific goal of visualizing inventory trends without external dependencies.
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