System Design



Seamless Experience - User-Flow Led By Intuition

The most important aspect in designing an accessibility-driven app was crafting something that is led by intuition rather than the set of mechanical instruction the user needs to follow. The approach was to not think like a developer, but like an every-day user, who would use this app extensively. We asked ourselves and others, what would be the most natural way to use a fitness tracker? That led us to the following feedback-oriented design and sequence diagrams, where each element of the user-flow was carefully chosen and implemented into a cohesive structure we have today.

System Architecture Diagram

To briefly describe each component, we would need to differentiate 4 main layers in the application: user, front-end, back-end and storage.

  • User: an actor which interacts with the app, records workouts, checks insights. Design of the app was oriented around the user which required moving the complexity further away and presenting the user with only what’s needed and useful.

  • Front-end: a bridge between the user and the background processes, uses XAML to compile UI elements and present them in the best way possible to the user. In order to help connecting these user elements with the rest of the app, use of C# Code Behind helped in bridging the gap, this time between front-end and back-end solutions.

  • Back-end: this is where all the important processes like Speech Recognition, Text-To-Speech, Bluetooth connections, as well as everything else the app has to offer, actually happen.

  • Storage: in order to save workouts and insights we had to implement a storage system for storing the relevant data for its repeated use. We opted for using CSV text files, and you can find more about this in our section Data Storage, on this website page.


Sequence Diagrams

Since the app is developed in .NET MAUI framework, all processes, such as compiling XAML code containing layout and appearance information, into platform-specific UI elements are done in the background, allowing for only a single point of contact between the user and the app. Due to the complexity of the project, and considering the fact that the app was built from the ground up in this new framework, we will define more high-level aspects here, while going more into details within the Implementation tab on our website.

Technical Decisions

Following from the above technology research, we came to a conclusion on the devlopment tools to be used in Project-Velocity

Term Definition
XAML Page Extensible Application Markup Language page, mainly used to define the visual contents of the app.
C# Code Behind C# code corresponding to the XAML Page, used mainly for background processes.
Speech Recognition API Speech-To-Text API adding a new layer of interaction within the app.
Text-To-Speech API Text-To-Speech API which allows additional functionalities, going beyond those of a screen reader.
Bluetooth API Bluetooth API conformed to .NET MAUI framework, without its own prior integrated capability.

The following is the overall sequence diagram which describes how user interacts with the screen and how our functionalities are accomplished in the background.

Overall Sequence Diagram

User’s view only consists of the UI components generated by XAML files and edited by their corresponding C# Code Behind files. Together they allow for seamless updates, navigation, transitions and much more. Code Behind files further allow adding valuable concepts such as Speech Recognition, making use of Android’s own native features, which combined with Text-To-Speech and adapted to our implementation work to provide Virtual Coach experience for our users. With respect to Bluetooth integration, we had to conform to the .NET MAUI framework, due to prior inexistence of its own integrated capability.


Data storage


Adaptability-Oriented Approach

To guarantee maintainability and simplify future upgrades, we decided to use highly efficient and straightforward form of persistent data storage, text files. More specifically, text files in CSV (Comma Separated Values) format. Some of the benefits to this approach were the following:


Adaptability

Text files in CSV format are compatible and hence supported by wide variety of platforms and programming languages, allowing for greater simplicity when shifting towards future technologies or demands.


Readability

Files in this format are inherently much more readable than other storage alternatives, enabling future app developers to effortlessly perform modifications, upgrades, as well as resolve any issues that may arise in the process.


Simple Parsing

Using CSV text files allows for quick data transformation, such as filtering, sorting and similar. The intrinsic simplicity of the parsing also means that we have much lower computational overhead unlike other storage systems. All of this leads to faster execution times of data-related tasks, as well as more optimised use of device resources, which fits great in our implementation.


Data Schema Design

Following the aforementioned benefits of using CSV files, such as adaptability, readability and simple parsing, we agreed on keeping them valuable when designing our data schema, which we used for storing workouts and insights about finished exercises. Both workouts and insights are being stored in App Data Directory, with an extension of “.workout.txt” and “.insight.txt” respectively.


Workout Data Schema
          Workout:
          Name,ActivityType,TrainingIntent
          
          Workout Object:
          Name: String
          ActivityType: string
          TrainingIntent: string
      

Insight Data Schema
        Insight: (using the Workout schema for first field)
        Workout|hour,minute,second|heartRateData|cadenceData
        
        Within Insight, heartRateData/cadenceData:
        data1,data2,data3... (for bpm/rpm corresponding to each second of the exercise)
        
        Insight Object:
        WorkoutName: string
        WorkoutActivityType: string
        WorkoutTrainingIntent: string
        Duration: TimeOnly(hour,minute,second)
        HeartRateData: List(int)
        CadenceData: List(int)