Crux Gaming

Disc Golf Buddy General Details

In development for iOS and Android devices, Disc Golf Buddy is a way for disc golf clubs and it's members to quickly calculate tag sorting at the end of a round, as well as provide a web portal to easily access club standings.

Technical Details

- Developed in Xamarin Forms for Visual Studio and programmed in C#.
- Utilizes Amazon Web Services for user authentication and remote database and storage functions.
- A custom Developer Authentication Mechanism developed using a serverless approach by taking advantage of AWS Lambda, DynamoDB and Cognito along with other AWS services.
- Local data stored using SQLite.
- Soon to be published on Apple's App Store and Google Play.


                    /**
                    * LoadPage.xaml
                    * LoadPage XAML layout.
                    * NicholusHuber@gmail.com
                    */
                    <?xml version="1.0" encoding="utf-8" ?>
                    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                                 x:Class="DGB.LoadPage">

                        <StackLayout x:Name="_stackLayoutMain" Orientation="Vertical" HorizontalOptions="Center" >

                            <Image x:Name="_imageTextLogo" Source="intropagetextlogo.jpg" />

                            <Grid x:Name="_gridMainLabels" ColumnSpacing="5" BackgroundColor="Black" >
                                <Label x:Name="_labelName" Text="GAME NAME" Grid.Column="0" HorizontalTextAlignment="Start" HorizontalOptions="StartAndExpand" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"/>
                                <Label x:Name="_labelDate" Text="LAST MODIFIED" Grid.Column="1"  VerticalOptions="Center" TextColor="White" FontAttributes="Bold"/>
                            </Grid>

                            <ListView x:Name="_listViewMain" />

                            <Button x:Name="_buttonLoad" Text="Load Game" Clicked="LoadButton_OnClicked" IsEnabled="False"/>
                            <Button x:Name="_buttonDelete" Text="Delete Game" Clicked="DeleteButton_OnClicked" IsEnabled="False"/>
                            <Button x:Name="_buttonCancel" Text="Cancel" Clicked="CancelButton_OnClicked" />
                        </StackLayout>
                    </ContentPage>

                

            

                        /**
                        * LoadPage.xaml.cs
                        * Underlying functionality for the LoadPage XAML form.
                        * NicholusHuber@gmail.com
                        */
                        using System;
                        using System.Collections.Generic;
                        using System.Collections.ObjectModel;
                        using Xamarin.Forms;

                        namespace DGB
                        {
                            public partial class LoadPage
                            {
                                private List<GameInfo> _gameList;
                                private readonly IntroPage _introPage;
                                private readonly List<VisualElement> _buttons;

                                public LoadPage(IntroPage introPage)
                                {
                                    InitializeComponent();
                                    _introPage = introPage;
                                    _gameList = Player.GetSaveGameInfo();
                                    _buttons = new List<VisualElement> { _buttonLoad, _buttonDelete, _buttonCancel };
                                    SetUiScale();
                                }

                                /// <summary>
                                /// Sets local UI elements sizes to scale with device resolution.
                                /// </summary>
                                private void SetUiScale()
                                {
                                    if(Device.OS == TargetPlatform.iOS) Padding = new Thickness(0,10,0,0);

                                    _imageTextLogo.HeightRequest = App.ScreenHeight * 0.116f;
                                    _stackLayoutMain.Margin      = App.MarginSize;

                                    _buttonLoad.HeightRequest    = App.ButtonHeight;
                                    _buttonLoad.WidthRequest     = App.ButtonWidth;
                                    _buttonLoad.FontSize         = App.FontSizeLarge;

                                    _buttonDelete.HeightRequest  = App.ButtonHeight;
                                    _buttonDelete.WidthRequest   = App.ButtonWidth;
                                    _buttonDelete.FontSize       = App.FontSizeLarge;

                                    _buttonCancel.HeightRequest  = App.ButtonHeight;
                                    _buttonCancel.WidthRequest   = App.ButtonWidth;
                                    _buttonCancel.FontSize       = App.FontSizeLarge;

                                    SetMainListView();
                                }

                                /// <summary>
                                /// Sets any options for the main ListView and its header area.
                                /// </summary>
                                private void SetMainListView()
                                {
                                    _gridMainLabels.HeightRequest = App.ButtonHeight;
                                    _gridMainLabels.Padding = new Thickness(App.MarginSize, 0, App.MarginSize, 0);
                                    _labelName.FontSize = App.FontSizeLarge;
                                    _labelDate.FontSize = App.FontSizeLarge;
                                    var gridCols = new ColumnDefinitionCollection
                                    {
                                        new ColumnDefinition {Width = new GridLength(App.ScreenWidth * 0.65f, GridUnitType.Absolute)},
                                        new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)}
                                    };
                                    _gridMainLabels.ColumnDefinitions = gridCols;
                                    _listViewMain.RowHeight = (int)(App.ButtonHeight * 0.75f);
                                    _listViewMain.ItemsSource = _gameList;
                                    _listViewMain.ItemTemplate = CreateDgbTemplate(gridCols);
                                    _listViewMain.ItemTapped += ListView_OnItemTapped;
                                }

                                /// <summary>
                                /// Create and return a custom DataTemplate with x number of columns.
                                /// </summary>
                                /// <param name="columns">A column collection in either Main or Calculated layout style.</param>
                                /// <returns></returns>
                                private DataTemplate CreateDgbTemplate(ColumnDefinitionCollection columns)
                                {
                                    return new DataTemplate(() =>
                                    {
                                        var grid = new Grid { ColumnDefinitions = columns, Padding = new Thickness(App.MarginSize, 0, App.MarginSize, 0), ColumnSpacing = 5 };

                                        var nameLbl = new Label { FontSize = App.FontSizeMedium, VerticalOptions = LayoutOptions.Center };
                                        nameLbl.SetBinding(Label.TextProperty, "SessionName");
                                        grid.Children.Add(nameLbl, 0, 0);

                                        var tagLbl = new Label { FontSize = App.FontSizeMedium, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center };
                                        tagLbl.SetBinding(Label.TextProperty, "CreationTime");
                                        grid.Children.Add(tagLbl, 1, 0);
                                        return new ViewCell { View = grid };
                                    });
                                }

                                /// <summary>
                                /// Called when the load button is clicked.
                                /// Attempts to load the selected game data and closes the load window.
                                /// </summary>
                                /// <param name="sender"></param>
                                /// <param name="e"></param>
                                private async void LoadButton_OnClicked(object sender, EventArgs e)
                                {
                                    var gi = _listViewMain.SelectedItem as GameInfo;
                                    if (gi == null) return;
                                    App.EnableElements(_buttons, false);
                                    _introPage.StartTagRound(Player.LoadGameSession(gi.SessionName));
                                    await Navigation.PopModalAsync();
                                    App.EnableElements(_buttons, true);
                                }

                                /// <summary>
                                /// Called when the cancel button is clicked.
                                /// Closes the load game window.
                                /// </summary>
                                /// <param name="sender"></param>
                                /// <param name="e"></param>
                                private async void CancelButton_OnClicked(object sender, EventArgs e)
                                {
                                    App.EnableElements(_buttons, false);
                                    await Navigation.PopModalAsync();
                                    App.EnableElements(_buttons, true);
                                }

                                /// <summary>
                                /// Called when a ListView item is tapped.
                                /// Enables the LoadGame Button.
                                /// </summary>
                                /// <param name="sender"></param>
                                /// <param name="e"></param>
                                private void ListView_OnItemTapped(object sender, ItemTappedEventArgs e)
                                {
                                    if (_listViewMain.SelectedItem != null)
                                    {
                                        _buttonLoad.IsEnabled   = true;
                                        _buttonDelete.IsEnabled = true;
                                    }
                                }

                                private async void DeleteButton_OnClicked(object sender, EventArgs e)
                                {
                                    var gi = _listViewMain.SelectedItem as GameInfo;
                                    if (gi == null) return;
                                    App.EnableElements(_buttons, false);
                                    var remove = await DisplayAlert("DELETE SAVED GAME", $"Are you sure you want to permanently delete the saved game \"{gi.SessionName}?", "Delete", "Cancel");
                                    if (!remove) return;
                                    Player.DeleteGameSession(gi.SessionName);
                                    await Navigation.PopModalAsync();
                                    App.EnableElements(_buttons, true);
                                }
                            }
                        }


                    
Copyright © Nicholus Huber / Crux Gaming