<file_sep>﻿using System;
using System.Diagnostics;
using Windows.Storage;

namespace workout7RT.Helpers
{
    /// <summary>
    /// Class responsible for managing application settings.
    /// Cannot be static, because static classes couldn't possess constructors
    /// </summary>
    class SettingsManager
    {
        ApplicationDataContainer settingsManager;

        // key names 
        const string currentStreakKeyName = "currentStreak";
        const string recentDayOfWorkoutKeyName = "recentDayOfWorkout";
        
        // default values
        const int currentStreakDefaultValue = 0;
        DateTimeOffset recentDayOfWorkoutDefaultValue = DateTime.Parse("2008-05-01T07:34:42-5:00");   // for sure?

        /// <summary>
        /// In the constructor class tries to fetch settings from application storage.
        /// </summary>
        public SettingsManager()
        {
            try
            {
                // get current settings of the application 
                settingsManager = ApplicationData.Current.LocalSettings;
            }
            catch (Exception e)
            {
                // if you can get current settings show toast
#if DEBUG
                Debug.WriteLine("Exception while loading settings: " + e.ToString());
#endif
            }
        }

        /// <summary>
        /// Update application setting of given key. If setting does not exist - create one
        /// </summary>
        /// <param name="keyName">setting name (key)</param>
        /// <param name="value">setting (value) of facultative type to save</param>
        /// <returns>originally it shourd return true if the operation succeeds</returns>
        private void AddOrUpdateValue(string keyName, Object value)
        {
            // bool valueChanged = false; 

            if (settingsManager != null)
            {
                if (settingsManager.Values.ContainsKey(keyName))
                {
                    if (settingsManager.Values[keyName] != value)
                    {
                        settingsManager.Values[keyName] = value;
                        // valueChanged = true;
                    }
                }
                else
                {
                    settingsManager.Values.Add(keyName, value);
                    // valueChanged = true;
                }
            }

            // return valueChanged;
        }

        /// <summary>
        /// Get the setting value from app settings. If the value does not exist - get default one
        /// </summary>
        /// <param name="keyName">setting name (key) to get</param>
        /// <param name="defaultValue">default value of the setting</param>
        private ValueType GetValueOrDefault<ValueType>(string keyName, ValueType defaultValue)
        {
            ValueType value;

            // If key exists - retrieve the value
            if (settingsManager.Values.ContainsKey(keyName))
            {
                value = (ValueType)settingsManager.Values[keyName];
            }
            else
            {
                value = defaultValue;
            }
            return value;
        }

        /// <summary>
        /// Save the settings (obsolete in Windows Store app; in WP 7/8 - arbitrary)
        /// </summary>
        private void SaveSettings() {}

        /// <summary>
        /// Gets or sets current streak count
        /// </summary>
        public int CurrentStreakSetting
        {
            get
            {
                return GetValueOrDefault<int>(currentStreakKeyName, currentStreakDefaultValue);
            }
            set
            {
                AddOrUpdateValue(currentStreakKeyName, value);
                // SaveSettings();
            }
        }

        public DateTimeOffset RecentDayOfWorkout
        {
            get
            {
                return GetValueOrDefault<DateTimeOffset>(recentDayOfWorkoutKeyName, recentDayOfWorkoutDefaultValue);
            }
            set
            {
                AddOrUpdateValue(recentDayOfWorkoutKeyName, value);
                // SaveSettings();
            }
        }

        public bool FirstRun
        {
            get
            {
                return GetValueOrDefault<bool>("firstRun", true);
            }
            set
            {
                AddOrUpdateValue("firstRun", value);
            }
        }
    }
}
<file_sep>﻿using System;
using System.Diagnostics;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using workout7RT.Helpers;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace workout7RT
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        SettingsManager settings;

        private const int TOTAL_EXERCISES = 12;

        private TimeSpan timeSpan;
        private DispatcherTimer dispatcherTimer;
        private DateTime endTime;

        private bool timerLocked;   // simple method, but still does the job ;-) 

        private int exerciseIndex;
        private readonly string[] exerciseNames;
        private readonly string[] imageNames;
        private readonly bool[] switchSides;

        enum Activity
        {
            GettingReady,
            Exercise,
            Rest
        };

        private Activity currentActivity;

        public MainPage()
        {
            this.InitializeComponent();

            settings = new SettingsManager();

            if (settings.FirstRun)
            {
                TileHelper.ShowToastNotification("The live tile will update once you finish your first workout.");
                settings.FirstRun = false;
            }

            this.exerciseNames = new string[]{
                "jumping jacks",
                "wall-sit",
                "push up",
                "abdominal crunch",
                "step up on chair",
                "squat",
                "triceps dip",
                "plank",
                "high knees running",
                "lunge",
                "push up and rotation",
                "side plank",
                ""
            };

            this.switchSides = new bool[]
            {
                false,
                false,
                false,
                false,
                false,
                false,
                false,
                false,
                false,
                true,
                true,
                true
            };

            this.imageNames = new string[] {
                "exercise.jacks.png", 
                "exercise.wall-sit.png",
                "exercise.push-up.png",
                "exercise.crunch.png",
                "exercise.step-up.png", 
                "exercise.squat.png", 
                "exercise.triceps-dip.png", 
                "exercise.plank.png",
                "exercise.running.png", 
                "exercise.lunge.png", 
                "exercise.push-up-rotate.png", 
                "exercise.side-plank.png",
                ""
            };

            currentActivity = Activity.GettingReady;

            // prepare dispatcher timer
            if (this.dispatcherTimer == null)
            {
                this.dispatcherTimer = new DispatcherTimer();
                this.dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
                this.dispatcherTimer.Tick += new EventHandler<object>(dispatcherTimer_Tick);
            }

            nextExerciseLabel.Text = "\u2192 jumping jacks";
        }

        ~MainPage()
        {
            this.dispatcherTimer = null;
            // to do - zezwól  na gaszenie ekranu
        }
        
        private void dispatcherTimer_Tick(object sender, object e)
        {
            TimeSpan tmps = (endTime - DateTime.Now);
            timerLabel.Text = String.Format("00:{1:00}", tmps.Minutes, tmps.Seconds + 1);

            if (this.currentActivity == Activity.Exercise)
            {
                if (tmps.Seconds + 1 != 30 && tmps.Seconds + 1 != 0) 
                    tickEffect.Play();

                if (this.switchSides[this.exerciseIndex] == true && tmps.Seconds == 15) 
                    switchSidesEffect.Play();
            }

            if (tmps <= TimeSpan.Zero)
            {
                this.dispatcherTimer.Stop();

                switch (this.currentActivity)
                {
                    case Activity.GettingReady:
                        this.currentActivity = Activity.Exercise;
                        break;
                    case Activity.Exercise:
                        if (this.exerciseIndex < TOTAL_EXERCISES)
                            this.currentActivity = Activity.Rest;
                        break;
                    case Activity.Rest:
                        this.currentActivity = Activity.Exercise;
                        this.exerciseIndex++;
                        beepEffect.Play();
                        break;
                }

                if (this.exerciseIndex < TOTAL_EXERCISES)
                    this.NextActivity();
            }
        }

        private void NextActivity()
        {
            if (this.dispatcherTimer != null)
            {
                switch (currentActivity)
                {
                    /* In case of practitioner is getting ready to workout just 
                     * set timespan to 5 seconds and label text.
                     */
                    case Activity.GettingReady:
                        this.timeSpan = new TimeSpan(0, 0, 5);
                        
                        currentExerciseLabel.Text = "get ready!";
                        currentExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/main.png", UriKind.Absolute));
                        nextExerciseLabel.Text = "\u2192 jumping jacks";
                        nextExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/exercise.jacks.png", UriKind.Absolute));
                        timerLabel.Text = "00:05";
                        beepEffect.Play();
                        break;

                    /* In case of activity is a workout set the timespan to 30 secs, label text
                     * and load image from Images/ folder. 
                     */
                    case Activity.Exercise:
                        this.timeSpan = new TimeSpan(0, 0, 30);

                        currentExerciseLabel.Text = exerciseNames[this.exerciseIndex];
                        nextExerciseLabel.Text = "\u2192 " + exerciseNames[exerciseIndex + 1];
                        currentExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/" + this.imageNames[this.exerciseIndex],
                            UriKind.Absolute));
                        nextExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/" + this.imageNames[this.exerciseIndex+1],
                            UriKind.Absolute));
                        timerLabel.Text = "00:30";

                        beepEffect.Play();
                        break;

                    /* In case of activity is a rest set the timespan to 10 secs 
                     * and the label to combined "rest" word [...]
                     */
                    case Activity.Rest:
                        if (this.exerciseIndex < TOTAL_EXERCISES - 1)
                        {
                            this.timeSpan = new TimeSpan(0, 0, 10);
                            currentExerciseLabel.Text = "rest";

                            
                            currentExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/rest.png",
                            UriKind.Absolute));
                            timerLabel.Text = "00:10";
                            beepEffect.Play();
                        }
                        else Finish();
                        break;
                }

                /* set endTime to time after [timeSpan] seconds 
                 */
                if (timerLocked == false)
                {
                    this.endTime = DateTime.Now;
                    this.endTime = this.endTime.Add(timeSpan);
                    this.dispatcherTimer.Start();
                }
            }
        }

        private void Finish()
        {
            this.dispatcherTimer.Stop();
            this.timerLocked = true;

            timerLabel.Text = "Workout 7";
            currentExerciseLabel.Text = "you've finished!";
            currentExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/Images/main.png", UriKind.Absolute));
            nextExerciseLabel.Text="";
            nextExerciseImage.Source = new BitmapImage(new Uri("ms-appx:///Assets/fake_uri.png", UriKind.Absolute));

            beepEffect.Play();

            IncreaseCurrentStreak();
        }

        /// <summary>
        /// Increases streak counter if there passed no more than 1 day.
        /// </summary>
        private void IncreaseCurrentStreak()
        {
            DateTimeOffset offset = new DateTimeOffset(DateTime.Today);
#if DEBUG
        Debug.WriteLine("Days passed: {0}", (DateTime.Today - settings.RecentDayOfWorkout).TotalDays);
#endif
            if ((DateTime.Today - settings.RecentDayOfWorkout.DateTime).TotalDays < 2.00)
            {
#if DEBUG
                Debug.WriteLine("Increasing streak");
#endif
                settings.CurrentStreakSetting = settings.CurrentStreakSetting + 1;
            }
            else
            {
#if DEBUG
                Debug.WriteLine("Streak goes to 1");
#endif
                settings.CurrentStreakSetting = 1;
            }
            settings.RecentDayOfWorkout = offset;
            TileHelper.SetUpTiles(settings.CurrentStreakSetting);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e) {}

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.timerLocked = false;
#if DEBUG
            exerciseIndex = 11;
#else
            this.exerciseIndex = 0;
#endif
            this.currentActivity = Activity.GettingReady;
            this.NextActivity();
        }
    }
}
<file_sep>﻿using Windows.UI.Notifications;

namespace workout7RT.Helpers
{
    static class TileHelper
    {//johny was here
        static public void SetUpTiles(int streak)
        {
            // wide tile 
            var largeTile = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideBlockAndText01);
            largeTile.GetElementsByTagName("text")[0].InnerText = "Workout 7";
            largeTile.GetElementsByTagName("text")[1].InnerText = "Your current streak is...";
            largeTile.GetElementsByTagName("text")[4].InnerText = streak.ToString();
            
            // medium tile
            var mediumTile = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareBlock);
            mediumTile.GetElementsByTagName("text")[0].InnerText = streak.ToString();
            mediumTile.GetElementsByTagName("text")[1].InnerText = "days in a row";

            var node = largeTile.ImportNode(mediumTile.GetElementsByTagName("binding").Item(0), true);
            largeTile.GetElementsByTagName("visual").Item(0).AppendChild(node);

            var tileNotification = new TileNotification(largeTile); // { ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(10) };    

            TileUpdateManager.CreateTileUpdaterForApplication().Update(tileNotification);
        }

        // TO DO
        ////static public void ShowToastNotification(int streak)
        ////{
        ////    // to do. 

        ////    var xml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
        ////    xml.GetElementsByTagName("text")[0].AppendChild(xml.CreateTextNode("Hello from toast!"));
        ////    ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(xml));
        ////}

        static public void ShowToastNotification(string s)
        {
            var xml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            xml.GetElementsByTagName("text")[0].AppendChild(xml.CreateTextNode(s));
            ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(xml));
        }


    }
}
<file_sep>workout7rt
==========

Workout 7 app for Windows Store (port from WP7)
