Sprint3Final - Moviles20242-Grupo32/MovilesSprint1 GitHub Wiki
Sprint 3
Link repo Swift: https://github.com/Moviles20242-Grupo32/SwiftSprint2.git
Link repo Kotlin: https://github.com/Moviles20242-Grupo32/KotlinSprint2.git
Swift project and kanvan board: https://github.com/orgs/Moviles20242-Grupo32/projects/6
Kotlin project and kanvan board: https://github.com/orgs/Moviles20242-Grupo32/projects/7
Kotlin apk file: https://github.com/Moviles20242-Grupo32/KotlinSprint2/blob/main/foodies.apk
1. Correction of Sprint 2
Analytics pipeline
As you can see our data source layer is Firebase, which is integrated with Big query in GCP. Then, the collections are imported to a bucket of cloud storage in GCP. After, the information from the bucket is extracted to Big Query. In Big Query, tables are created and queries are made. Depending on the business question, in Looker studio the tables, result from a query are imported.
2. Connectivity strategies
2.1 Strategies
In general, for the cart, we implemented an always offline strategy, as the items of the cart are just uploaded to Firebase when an order is placed. So, the cart is saved in the cache and in local storage. When there is no connectivity and then it is recovered, the information is updated from the cache and the local storage. A more in depth explanation would be provided in the cache and local storage section bellow.
For the items, there is an always online strategy implementation. As the offering of boxes changes all the time, it makes no sense to display to the user or to save outdated information. When connection is recovered, there is always a fetch of items from Firebase.
2.2 Scenarios
- Title/ID: Displaying boxes under no connection
o Event description: In the home view, the available boxes are showed. The information related to this boxes is fetched from Firebase.
o System response: Taking into consideration that boxes are updated every 30 seconds (because the inventory changes all the time), if there is no internet, the user would not be able to view the boxes. Instead, a spinner and a message informing the user that the boxes can't be displayed because there is no internet connection.
o Possible antipatterns: Non informative messages -> It could happen, but we displayed a message that specifies why the user isn't able to view the boxes
o Caching and retrieving strategy: When there is no internet connection, the available boxes shouldn't be displayed, as the content of the available boxes is changing all the time. That's why we considered wrong that the user views the last version, as a selected item might not be available when the connection is recovered. That's why there isn't caching or retrieving strategies.
o Storage type: not used for the previous explained reason
o Stored data type: not used for the previous explained reason
- Title/ID: Create or cancel orders under no connection
o Event description: A user shouldn't be allowed to create or cancel an order, as this information has to be received by the system and communicated to the restaurant in real time.
o System response: The system doesn't allow to create or cancel an order, as a result, an alert as a notification, would be displayed to the user. The users won't be able to perform the action until the connection is recovered.
o Possible anti patterns: Blocked app -> the app could block if the user presses the button to create or cancel multiple times. We managed this by displaying the alert really fast, avoiding this problem.
o Caching and retrieving strategy: There is no caching or retrieving of the action of the user but, when an item is added to the cart, it is saved to the cache. When the user exists the app, the cache is saved in local storage. Meaning that if during a no internet scenario de user exits or closes the app, the information of the cart isn't lost.
o Storage type: Cache and local storage
o Stored data type: Swift-> NSCache (objects) and SQLite (elements) Kotlin-> LRUCache (shopping cart) and MySQL (items)
- Title/ID: The user shouldn't be allowed to log in or register under no connection
o Event description: A user shouldn't be allowed to log in or register when there is no connection.
o System response: The system doesn't allow to log in or register, as a result, an alert as a notification (in case of register) and a message (in case of the log in), would inform the user that the action can't be completed as there is no connection.
o Possible anti patterns: Non informative message -> The log in and register would fail if there is no internet but, we managed this by generating an specific alert and a specific message specific for this situation.
o Caching and retrieving strategy: There is no caching or retrieving of the action of the information that the user has typed won't be lost if there is no internet.
o Storage type: not used for the previous explained reason
o Stored data type: not used for the previous explained reason
- Title/ID: User's location
o Event description: When there is no connection the user's location isn't lost
o System response: The system keeps displaying the last location found. Because there is no internet, the order cannot be placed. When the internet recovers, the location is searched again.
o Possible anti patterns: Blocked app-> If the connection is lost, location cannot be found, so the app would block. In this case, the app keeps working and the cart can't be ordered.
o Caching and retrieving strategy: The last location is displayed and when the internet is recovered the location is searched again. That's why it makes no sense to save the location, as during the no connection period the user's location could have changed.
o Storage type: not used for the previous explained reason
o Stored data type: not used for the previous explained reason
- Title/ID: Cart functioning
o Event description: The items of the cart and the state of the cart isn't lost when there is no connection.
o System response: The system keeps the items in the cart, the user can add or remove items of the cart and when the connection is recovered, the state of the cart remains the same.
o Possible anti patterns: Blocked app-> If the connection is lost, the user might not be able to use the cart's functions. Nevertheless, the cart functions keep working.
o Caching and retrieving strategy: When an items is added to the cart of removed, the cache is updated and the local storage as well. When the connection is recovered the cache and then the cart, are updated with the information of the local storage.
o Storage type: Cache and local storage
o Stored data type: A table with the information of the items that are in the cart, with the quantity as well.
2.3 How app behaves in them
Swift
- https://github.com/user-attachments/assets/042ac4e5-4ced-4bda-8624-ecada7d9f5fd
- https://github.com/user-attachments/assets/35f1ac65-5d4a-4705-9768-368e4b45a525
- https://github.com/user-attachments/assets/3aaf8a88-25e2-44cb-b536-438f0d77640b
- https://github.com/user-attachments/assets/49dd478e-07fe-44e1-ad9b-91baf6642100
Kotlin
- https://github.com/user-attachments/assets/022fbf6d-bee8-463b-9158-a535ed6ad9e0
- https://github.com/user-attachments/assets/8e76162d-5aa9-4f57-aae2-e49d969f4b8a
- https://github.com/user-attachments/assets/87a91044-689c-4558-986c-ac40a33d42d6
- https://github.com/user-attachments/assets/c846f168-1cab-4d97-8bef-37b3873b6bc0
3. Business questions
Business questions from Sprint 2: Type2: 2 Type3: 2 Type4: 1
Business questions from Sprint 3: Type2: 2 Type3: 2 Type4: 2
Total business questions: Type2: 4 Type3: 4 Type4: 3
Looker studio dashboard link: https://lookerstudio.google.com/reporting/39517ad3-1145-4436-b807-8f79cbf5265b
3.1 What is the historical average amount of money spent by each user in our app? Type4
3.1.1 Why this type?
This is a type 4 question because it provides the company with valuable information about user spending habits. This information can be sold to third party companies for lucrative purposes and also used within the company for strategic planning.
3.1.3 Pipeline: When a user places an order, the monetary amount of the order, along with a timestamp and the user id is saved in a collection in firebase, which is then exported to GCP (Google Cloud) and into Big Query, where the data analysis takes place.
3.2 Which is the most ordered restaurant by users? Type4
3.2.1 Why this type?
It is Type 4 because it provides valuable information about user behavior that companies or third-party businesses can use for strategic planning. This question, offers insights into user preferences and trends, enabling businesses to tailor their marketing strategies, enhance their services, and form strategic partnerships. The data gained is strategic, helping businesses make informed decisions to improve their market position and respond effectively to customer demands.
3.1.3 Pipeline:
Order Placement in Firebase: When a user places an order, the order details, including information about the food item (such as item_name, item_cost, item_quantity), are stored in a Firebase collection. Each order typically includes a user ID and other relevant information.
Exporting Data to Google Cloud Platform (GCP):Firebase data is exported to GCP. This was done using Firebase’s integration features that transfer data to BigQuery.
Data in BigQuery:The exported data is loaded into a BigQuery table, where it can be analyzed using SQL queries. In this case, the ordered_food field contains information about each food item, including the item_name, which represents the restaurant.
Analysis Using SQL Query:To find the most ordered restaurant, I used an SQL query that counts how many times each restaurant appears in the ordered_food field and then selects the one with the highest count.
3.3 In the last month what was the time time slot with the most amount of orders? Type 4
3.3.1 Why this type? It is type 4 because gives valuable information about the users that can be used by the company or third-party companies in their strategic planning.
3.3.3 Pipeline
When a user places an order, the monetary amount of the order, along with a timestamp and the user id is saved in a collection in firebase, which is then exported to GCP (Google Cloud) and into Big Query, where the data analysis takes place.
3.4 In the last month, what was the percentage of users that used the button to filter the 5 star ranked boxes? Type3
3.4.1 Why this type? It is type 3 because evaluates the utilization of a feature, indicating the developers how it is used and how could they make better the app features.
3.4.2 Functioning of the feature
https://github.com/user-attachments/assets/c0c0e7de-6449-45e9-b259-511aa3e4261f
3.4.3 Pipeline The users that use the filter, are registered in a collection with their id and their timestamp.
3.5 Which is the cheapest mistery box offered on the market? Type 2
3.5.1 Why this type?
Is a Type 2 business question because it seeks specific information about the pricing of a product category (mystery boxes) in the market. The benefit of this question is that can be answer to each user, through the app interface.
3.5.2 Functioning of the feature
Original sort:
Cheaper items sort:
3.6 In the last month, what was the percentage of users that used the button to filter the boxes that match the last search from the user?Type3
3.6.1 Why this type? It is type 3 because evaluates the utilization of a feature, indicating the developers how it is used and how could they make better the app features.
3.6.2 Functioning of the feature
https://github.com/user-attachments/assets/85b33a74-9b41-4830-bd89-7e632f830dcc
3.6.3 Pipeline The users that use the filter, are registered in a collection with their id and their timestamp.
4. Multithreading
4.1 For fetching items: nested threads The items showed in the main page are the boxes available. These boxes change all the time as they depend on the restaurants' offer. Therefore, the boxes from Firebase should be fetched all the time. In order to avoid performance bugs, a thread in background would be executed nested to a thread of type user interactive, this to paint the boxes in the UI.
SS from Swift
SS from Kotlin
4.2 For CAS features The context aware feature is to check the user's location all the time, so if the user is 5km or less close to a Foodies restaurant, he/she would receive a notification indicating him/her this. In order to do this, there is a thread in background running every 5 minutes.
SS from Swift
SS from Kotlin
4.3 For checking connection status * Just in Swift
To check for the connection status, there is a thread that checks this all the time. When the connection status changes, it fetches data and restores the cart. Also, when there is connection, the location is updated.
SS from Swift
4.4 Not order create check *Just in Kotlin
To check if the the user haven't make an order when it have items on the shopping cart. This execution runs every 15 minutes, and if the user have items in their cart without completing an order, the app will send a push notification to remind them to place their order.
SS from Kotlin
5. Local storage
Swift
5.1 Local DB
The local db is used to save the cache that has the cart items. SQLite is used.
5.2 Firebase
Firebase saves data locally on a device using offline persistence, which allows your app to access and interact with data even when it has no internet connection. Here’s how it works:
5.3 Preferences
Preferences are used to save the user's last search, which is then used for the latest search filter.
Kotlin
5.1 Local DB
5.2 Preferences home icon
5.3 Preferences user info
6. Connectivity for features
6.1 Feature: display boxes Managing of lack of connectivity: a message explaining that there is no connection and that that's why boxes can't be displayed, is showed.
6.2 Feature: add and remove items from cart Managing of lack of connectivity: items can be added or removed and the cart is saved in cache and local storage
6.3 Feature: filters Managing of lack of connectivity: filters can be used but the message of lack of connectivity would also be displayed
6.4 Feature: text to speech Managing of lack of connectivity: it would keep working but it won't read any items in the home page as the message of lack of connectivity is being displayed. In the cart, it keeps working normally.
6.5 Feature: increasing and decreasing quantity in the cart Managing of lack of connectivity: it would keep working and the state of the cart would be saved in the cache and local storage
6.6 Feature: placing an order Managing of lack of connectivity: the order won't be placed and the user would receive a message explaining that there is no connecitivity, so the order can't be placed
6.7 Feature: viewing the profile Managing of lack of connectivity: the user would still be able to view her/ his profile
6.8 Feature: log out Managing of lack of connectivity: the user can still log out
6.9 Feature: log in Managing of lack of connectivity: the user can type in the view but cannot log in, a message would be presented to the user indicating that he/she can't log in as there is no connectivity
6.10 Feature: register Managing of lack of connectivity: the user can type in the view but cannot register, an would be presented to the user indicating that he/she can't register as there is no connectivity
7. Caching strategy
Swift
In the first place, a CacheManager class is built for controlling everything related to caching in the application. The class is instantiated following a singleton pattern, enforced by a static access to the instance and a private initialization.
Cache Manager class:
7.1 Cart
Swift:
Items added to the cart are cached with the built-in NSCache (a mutable collection used to temporarily store transient key-value pairs that are subject to eviction when resources are low). Items are cached the moment they are added to the cart and they are retrieved from cache each time the data is fetched.
Definition of the Cart-cache in the CacheManager:
Fetching of the data (happens every 2 minutes to account for possible updates in product availability).
data fetching function:
Cached items retrieval function:
Function in the CacheManager instance to revtrieve all items stored in cache:
The CacheManager instance provides additional methods to add, get, remove and clear items in the cart. For a more detailed approach resort to the class definition in App13/Model/CacheManager.swift.
The cart items cache is manually cleared when a user logs out of the application.
7.2 Home check:
The Home Checkmark toggle is used to show the user which items have been added to the cart. When items are restored from cache to the cart view, the Home Checkmark has to be updated to properly show consistency between views. To achieve this, a reasignation of the cached item to the items list is done in order to ensure the home view is properly updated. The same logic is used to properly update the cart view when a chached item has is order quantity changed:
7.3 Favorites
The favorite item is stored in cache in a similar way as to how the cart items are stored. Storing the favorite item in cache optimizes the app's mobile Cpu usage because the algorithm to find the favorite item doesn't have to be run on every data fetch.
Algorithm to manually calculate the favorite item (before storing the item in cache, this algorithm was executed every 2 minutes along with every data fetch) time complexity is O(n):
Now, with the cache strategy, the favorite item algorithm is executed once (with the initial data fetch) and the resulting item is stored in cache, so the next time the app fetches data, the algorithm won´t be executed again.
Definition of the favorite item cache in the Cache-Manager:
It's stored with a default, previously known key, to facilitate the item's retrieval from the cache.
Methods to manipulate the favorite item stored in cache:
Use of the favorite item cache in the data fetching method:
Both the favorite item cache and the cart items cache are manually cleared when a user logs out of the application.
7.4 Images
The implementation of a Cache for the images was done manually (not relying on the NSCache) mainly for the following reason: after some reseach we found out that the AsyncImage view provided by apple asynchronously loads and displays an image but does not store it in cache. So in order to store our images in cache we would need to either extend the functionality of AsyncImage or use a third party library like KingFisher (which we cosidered to be an overkill given our app's requirements). Therefore, we decided to extend the functionality of AsyncImage by building our own CachedAsyncImage manager, which relies on the AsyncImage view and adds the caching functionality we desired.
CachedAsyncImage struct definition:
The caching strategy is as follows: first, the manager initialization logic is the same as the one for AsyncImage so that our new struct can be seamlessly integrated into the rest or our App views using AsyncImage without much manipulation. Second, the view asks first if the requested image is stored in cache (using the image url as key) if its stored then no need to fetch it. If it isn't, then AsyncImage is called in order to fetch in from its remote source, after which the fetched image is stored in a cache called ImageCache:
Image cache in use in ItemView:
Kotlin
7.1 Firebase
7.2 Cart
The cart is cash on the LRU Cache as json for having a direct access of the cart state. In this way, the order worker access to this cart and know if the user have items on the cart and not placed orders.
LRU Cache Manager as singleton:
_cart Mutable Live Data object configuration for being observed constantly:
Reset cart function:
Order worker access to cart state:
On Stopped Order Worker fucntion:
7.4 Images
8. Explanations in Viva Voce
9. List functionalities
9.a Functionalities:
Sprint2:
Sensor: user's location
Type 2 question: indicate the box that was the most ordered in the past month by all users. The data about the orders would be collected in Firebase and then, the information is retrieved to search for the most ordered box.It would be showed as a banner on top of the box. Context aware: when a users is within a 2km distance of a restaurant that publishes boxes in Foodies, the user would receive a push notification.
Smart feature: text to speech that reads the available boxes and the content of the cart. This happens when the users presses on a megaphone-like button.
Authentication: the app is connected to the authentication service of Firebase
External services: the app retrieves information of the boxes from Firestore and sends the completed orders
Business questions: registers events to complete business questions
Add and remove items from the cart in the home and in the cart view
Increase and decrease the quantity of a box in the cart
Place an order
View profile
Filter by a query
Log in and out out
Register
Sprint3:
Filter by the 5 star ranked boxes
Filter by the the latest search
9.b BQs: referred in the Wiki in literal 3
9.c Connectivity: referred in the Wiki in literal 2 and 6
Saving cart in cache and local storage
Alerts avoiding to place an order or register
Message of error indicating the user can't log in
Not displaying the items, instead an informative message
9.d Local storage: referred in the Wiki in literal 5
Use of Firebase
Use of preferences
Use of SQLite for the cart items
9.f Caching strategies: referred in the Wiki in literal 7
Save the cart
Save images
Save the favorite item
Save items added to the cart
10. Real devices
SS Swift
SS Kotlin
11. Bugs
12. Ethics component
https://www.youtube.com/watch?v=i4MWCMJGxdE
13. Collaboration
Gitflow
Swift
Kotlin
Issues When a pull request is send a milestone is associated. Also, the reviewers are associated.
14. Individual
14.1 Milestones
Swift
Kotlin
14.2 Boards
An issue is always assigned to a milestone and a team member.
Swift
Kotlin