Don’t load data you dont really need.

In my previous posts, we discussed my load method and how to implement a picker resulting in the following method:


private async Task LoadData()
{
if (_isDataLoaded)
return;
ModelExercises.Clear();
_isDataLoaded = true;

var modelExercises = await _workoutStore.GetModelExercisesAsync();

foreach (var modelExercise in modelExercises)
{
ModelExercises.Add(await
ModelExerciseViewModel.CreateAsync(modelExercise, _workoutStore)
);

}

var muscles = await _workoutStore.GetMusclesAsync();

foreach (var muscle in muscles)
{
Muscles.Add(muscle);
}

if (SelectedMuscle != null)
{
var selectedMuscle = from m in Muscles
where m.Name == SelectedMuscle
select m;
Muscles.Clear();
Muscles.Add(selectedMuscle.SingleOrDefault());
}

foreach (var muscle in Muscles)
{
var currentMuscle = new ExerciseGroup(muscle.Name, muscle.Name);

var foundMuscles = from e in ModelExercises
where e.PrimaryMuscles.Contains(muscle, _compareMuscle)
select e;
currentMuscle.AddRange(foundMuscles);
GroupedExercises.Add(currentMuscle);
}

}

The primary problem with this approach is in:


foreach (var modelExercise in modelExercises)
{
ModelExercises.Add(await
ModelExerciseViewModel.CreateAsync(modelExercise, _workoutStore)
);

}

Which triggers the static async method (which replaces the constructor which itself cannot be async):


public static async Task<ModelExerciseViewModel> CreateAsync(ModelExercise exercise, IWorkoutStore workoutStore)
{
_workoutStore = workoutStore;

ModelExerciseViewModel exerciseViewModel = new ModelExerciseViewModel(exercise);
exerciseViewModel.PrimaryMuscles = await GetMuscles("Primary");
exerciseViewModel.SecondaryMuscles = await GetMuscles("Secondary");
return exerciseViewModel;
}

It works… but it is super slow, on my Galaxy A52016 it took ~6sec to generate the original list and ~2sec for each filtering. Unacceptable.

Then it dawned on me… Why do I generate objects I don’t need at this time?

The original logic was: I am going to create all the objects and then use the lists of muscles I build for them for filtering.

What seemed like a good plan was loading information I did not need into the application when I have a perfectly good simple object:


public class MuscleExerciseAssosiation
{
public int MuscleId { get; set; }
public int ModelExerciseId { get; set; }
public string MuslceType { get; set; }
}

In my database based on which I can use for filtering:


public async Task<IEnumerable<MuscleExerciseAssosiation>> GetMuscleExerciseAssosiations(string muscleType, int? muscleID = null)
{
List<MuscleExerciseAssosiation> assosiations = new List<MuscleExerciseAssosiation>();
if (muscleID == null)
{
assosiations = await _connection.Table<MuscleExerciseAssosiation>()
.Where(e=>e.MuslceType == muscleType).ToListAsync();
}
else
{
assosiations = await _connection.Table<MuscleExerciseAssosiation>()
.Where(e => e.MuscleId == muscleID && e.MuslceType == muscleType).ToListAsync();
}

return assosiations;
}

Now when I can pull at will either a filtered or full list of exercises I need I can simply:


if (SelectedMuscle != null)
{
var assosiatedExercises = await _workoutStore.GetMuscleExerciseAssosiations("Primary", SelectedMuscle.Id);
foreach (var assosiation in assosiatedExercises)
{
ModelExercises.Add(modelExercises.Where(e => e.Id == assosiation.ModelExerciseId).SingleOrDefault());
}
}
else
{
muscles = await _workoutStore.GetMusclesAsync();

foreach (var muscle in muscles)
{
Muscles.Add(muscle);
}
foreach (var exercise in modelExercises)
{
ModelExercises.Add(exercise);
}

}

And thats it. Perfomance to being unoticable for both the initial load and filtering, so I am preatty proud of myself 🙂

The full new ViewModel can be found on github.

A little guide on dealing Xamarin errors

So… I  sank around 3 hours into fixing this across 2 days… Turns out there is nothing wrong with the Picker, nothing wrong with my solution… The issue was within Xamarin.

Mono just got confused and was killing everything…

While digging thru the logs of the output I found out that the issue was linked to XamlFilePathAttribute so while there was no direct thread related to my issue I found this post, and it saved my life bottom line to fix a variety of issues with this class:

  • Cleanup solution
  • Close Xamarin Studio/VS
  • Remove all .bin and .obj folders in all projects.
  • Open Xamarin Studio/VS and rebuild the solution.

The Rebuild word is key be sure to

ReBuild

And not just try to debug it again like I did. Now everything works perfectly:

The simplest of things…

In Xamarin Forms 2.3.4 they added a Bindable picker to the XAML as per this documentation:
https://blog.xamarin.com/new-bindable-picker-control-for-xamarin-forms/

But cut my dick off and call me daisy but I cannot get it to work… I made a list dedicated to it:


public ObservableCollection<string> MuscleGroups { get; private set; } = new ObservableCollection<string>();

Filling it in nice and proper


var muscles = await _workoutStore.GetMusclesAsync();
foreach (var muscle in muscles)
{
MuscleGroups.Add(muscle.Name);
}

Bound it in XAML:


<Picker ItemsSource="{Binding MuscleGroups}" SelectedItem="{Binding SelectedMuscle}" />

But it crashes as soon as I try to load the page, its been two hours after a long day of doing Python in the office, I need a break… Going to fix it tommorow.

Removing HTML tags from a string

Problem:

Screenshot_1493145278.png

The HTML from the API is in the exercise description. It looks like shit and is a potential security threat!

There a couple of ways you can tackle this particular beast:

  • Use REGEX:
    
    using System.Text.RegularExpressions;
    ...
    const string HTML_TAG_PATTERN = "<.*>";
    
    static string StripHTML (string inputString)
    {
     return Regex.Replace
     (inputString, HTML_TAG_PATTERN, string.Empty);
    }
    

    Created by a StackOverflow use capdragon

  • HTML Agility Pack
     public static string StripTagsCharArray(string source)
     {
     HtmlDocument htmlDoc = new HtmlDocument();
     htmlDoc.LoadHtml(source);
     htmlDoc.DocumentNode.SelectNodes("//comment()")?.ForEach(c=> c.Remove());
     return htmlDoc.DocumentNode.InnerText;
     }
    

    Created by users Ssilas777 and Thierry_S

  • And lastly the simplest but fastest one:
     public static string StripTagsCharArray(string source)
     {
     char[] array = new char[source.Length];
     int arrayIndex = 0;
     bool inside = false;
     for (int i = 0; i &amp;lt; source.Length; i++)
     {
     char let = source[i];
     if (let == '<')
     {
     inside = true;
     continue;
     }
     if (let == '>')
     {
     inside = false;
     continue;
     }
     if (!inside)
     {
     array[arrayIndex] = let;
     arrayIndex++;
     }
     }
     return new string(array, 0, arrayIndex);
     }
    

    Shared by AuthorProxy in the same thread a capdragons solution.

I went for what is behind door no. 3. IT suites my needs does not require any additional libraries to be loaded does not process the HTML code, so any malicious code it will get its ass ignored by being treated as a string.

Screenshot_1493146922.png

Voila!

Builder Pattern – Creating a full set of exercise objects

Three things need to happen in order for me to have a full ModelExercise from the API:

  1. Muscle Groups need to be downloaded
  2. Exercises need to be downloaded
  3. An association table must be built between the two.

Normally I’d use Entity Framework for this sort of thing but with PCL at a time when I started the project, it had quite a lot of problems and SQLite.NET-PCL  was the recommended solution.
That is okay but it means I need to build everything myself so long:


public virtual List<Exercise> Exercises {get; set;}

I need to build this relationship myself, so first of a model class:


 public class MuscleExerciseAssosiation
 {
 public int MuscleId { get; set; }
 public int ModelExerciseId { get; set; }
 public string MuslceType { get; set; }
 }

How I get muscles and exercises you can see in my previous post the association is build:


public override List<MuscleExerciseAssosiation> AssosiationGet()
{
if (_wgerExercises.Count == 0 || _muscles.Count == 0)
{
return new List<MuscleExerciseAssosiation>();
}
foreach (var exercise in _wgerExercises)
{
foreach (var muscle in exercise.muscles)
{
_muscleAssosiations.Add(
new MuscleExerciseAssosiation
{
ModelExerciseId = exercise.id,
MuscleId = muscle,
MuslceType = "Primary"
}
);
}
foreach (var muscle in exercise.muscles_secondary)
{
_muscleAssosiations.Add(
new MuscleExerciseAssosiation
{
ModelExerciseId = exercise.id,
MuscleId = muscle,
MuslceType = "Secondary"
}
);
}
}
return _muscleAssosiations;
}

which I then simply load into the database:


private async Task FillMuscleExerciseAssosiations(AbstractSourceFactory factory)
{
List<MuscleExerciseAssosiation> assosiations = factory.AssosiationGet();
await _connection.InsertAllAsync(assosiations);
}

But it is private… so I cannot call it outside of the class… Thats where the builder pattern comes in, as mentioned at the top of the post all 3 things need to happen in a sequence and they all need to happen, hence a new public method:


public async Task BuildMuscleDatabase(AbstractSourceFactory factory)
{
await FillMusclesFromDataStore(factory);
await FillExercisesFromDataStore(factory);
await FillMuscleExerciseAssosiations(factory);
}

calling all 3 in a sequence with one call from the outside, we are always sure that we called are methods correctly, and with this method being part of the IWorkoutStore interface we opened another ease of work for the future.

Fitness Buddy – App analysis to find the best UI

Fitness Buddy popped up on my app store as a promotion for 0,5 zł (10 cents? +/-), why the hell not lets take a look 🙂

1

Nice exercise details, not going to do it because it would take quite a significant amount of time to collect this info and this project is not about data collection but coding.

2.png

This is just the way I want mine to be only I want to use the list view a little bit better and add a description of the workout below the name. Right now it does not give too much information at a first glance…

3

Workout details, perfect, a great thing I may put in late is the separation of workout parts I like it. Right now it’s a bit too much of a change for a part I am done with (well 1-3 hours of coding, but I just feel I can spend it better).

4

So far I was very positive but this is kind of meh to me:

  • You can’t put in individual weight for a rep, not everyone does 5×5…
  • It’s not very attractive is it now?
  • On a very much + side it is super intuitive!

5

Notes… Notes everywhere, it’s not facebook yo! This I like but because it gave me an idea on how to show progress in my app, so the weight will be on Y axis and a number of reps will be color coded (>50% of set reps RED, <=50%>75% AMBER, <=75%>=100% GREEN, >100% BLUE) Easy to read and gives a cool indication of whether you are not putting up too much weight :).

It’s again an OK app really, gave me some really good ideas!

JEFIT – App analysis to find the best UI

First annoyance the app requires you to log in as soon as you open it, please don’t do this… It’s a really shitty thing to do…

JEFIT at the start gives us kind of a main menu in a form of a tabbed view spanning across all the functionalities that you would need:

Screenshot_20170402-173555.png

We’ve got workouts exercises and logs. Overall + for having the main menu in my book!

Let’s go out of order and check out the exercises page:

Screenshot_20170402-173610.png

Now this to me is overdesigned. And having bane from batman as your model is not helping with me liking your app… Overall to some people it may look nice and can help out if you don’t know where your chest is… Well, then you can check out Bane’s sweet pecks to identify them.

Screenshot_20170402-173627.png

Now the exercise list I like, very cool way of using a tabbed view in your app to have multiple functionalities on one page, where most of them are only going to be useful to some of your customers + for that guys.

Looking at the workouts:

Screenshot_20170402-173605.png

Having pre-set workouts is always nice, and the UI here is very nice and clean, I wonder how it looks in terms of views… there is definitely a tabbed view like everywhere else, and the other one? List view with cool custom cells? Most likely, I hope they don’t generate each one of those in code-behind…

Screenshot_20170402-173722

Now so far it has been swing and miss but this is just bad, not only did I had problems understanding what is this asking me to do, it takes you to a different screen after you rest and pops you back again after it’s done (you can even see the navigation view UI elements on top). Most of the screen is covered in those weird scroll things that neither look good nor help out. So no not using anything from here.

Screenshot_20170402-173727

Why is this not a pop-up! Cmon! But thanks to you guys I now know that I need to make a pop-up with a timer :).

Screenshot_20170402-173741

And one more cool thing I am DEFINETLY stealing is this part where when you start a workout and go somewhere else in the app the two buttons display allowing you to immediately go back or close your session very nice!

Overall JEFIT is pretty good, but the most important screen of the app to me requires work :(.