prak112 / TournamentTracker

Building a windows forms app using help of freeCodeCamp tutorial

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Tournament Tracker

Source : C# Application from Start to Finish, freeCodeCamp tutorial

FYI : This is an ongoing README and Project Report. Documents will be seperated at the end of the project.

Scenario

  • Stakeholder requests to build a Tournament tracker using bracket tournament system where application decides the opponents in a single-elimination style. At the end, tournament winner is identified.

  • The tournament model is based on March Madness Seeding (Best v Worst in a division)

  • March Madness Seeding March Madness Seeding (Best v Worst in a division)
    • Divisions are broken into pools (e.g., North, South, East, West) and within each pool teams are ranked.
    • The top seed plays the worst seed, the second best seed plays the 2nd worst seed within the pool, etc., until all teams play their first round.
    • If the pool has an odd (not divisible by 2) number of teams, there will be a "play in" game of the worst vs the 2nd worst team. Such a seeding system produces a wide variety of matches, but requires many games to determine an outcome.



Table Of Contents




PLAN

Requirements

  • Identifying the opponents and the winner
  • Multiple competitors
  • Define which competitors are competing and when
  • Schedule games (how to, needs more specifics)
  • Single loss elimination
  • Identify last competitor standing as winner

Questions

  1. What if there are uneven number of competitors ?
    • Randomly advance the odd competitor to next round, a.k.a "Byes"
  2. Is the total number of competitors fixed or variable ?
    • Variable
  3. Are the opponents chosen randomly or based on any key factors?
    • Random
  4. Are the games scheduled or played whenever possible ?
    • Whenever
  5. If played whenever, could/should we include a pre-round/qualifiers to directly move to round 2 ?
    • No. Consequential rounds
  6. Is there scoring or just the winner ?
    • Each player with a score as 1 or 0
  7. User interface - form or webpage or app ? (never assume!)
    • form for now, later website or app
  8. Data storage location ?
    • Microsoft SQL Server, also a text file backup
  9. Are the Payins to the game(entry fee) or Payouts to the competitors(prizes) handled or nothing at all ?
    • Yes, option to charge payins and payouts. Payout for top 3 teams as a percentage of the tournament income, but definetely the sum of payouts < tournament income
  10. Reporting type - results announced in detail or just brief?
    • Send Overall rounds outcomes, each competitor stats to admin and users
  11. Game results entered by whom ?
    • Anyone
  12. Levels of access - Admin, User ?
    • Single-User access. No varying levels, but competitors get only email reports and notifications, admin only accesses form
  13. Notificaton to users about upcoming games ?
    • Yes, competitors are notified by email
  14. Tracker tracks Players and Teams or only Teams ?
    • Every member of the team must be tracked individually for game notifications and reports

Overview

Big Picture Design

  • Structure : Windows Forms application and Class Library
  • Data Storage : SQL and/or Text File
  • Users : One user at a time or single-user access

Key Concepts to Learn

NOTE : Always research the requirements to know what is lacking and to understand them

  • Email : How to send emails through application using C#
  • Custom Events : How to identify end of rounds, report round outcomes and notify users about upcoming games
  • Error Handling : How to handle possible erroneous user input
  • Interfaces : What are they and How to use them
  • Random Ordering : How to randomize opponents and choosing Byes
  • Texting : BONUS How to capture key user information for notification purposes

DESIGN

Map Data Relations

  • ALWAYS build Pseudocode.

  • ALWAYS okay to miss some details.

  • Define Objects/Classes by identifying unique categories to record data

    • Person
    • Team
    • Tournament
    • Prize
    • Match (in tutorial, Matchup)
    • MatchRegistry (in tutorial, MatchupEntry)

  • Map Relations between Objects/Classes
    • Person -> Team <-> Tournament
    • Tournament <- Prize
    • Tournament <- Match
    • Match <-> MatchRegistry <-> Team

  • Define Object/Class structure
Object/Class Property (datatype)
Person
  • FirstName (string)
  • LastName (string)
  • PhoneNumber (string)
  • Email (string)
Team
  • Name (string)
  • Members (List<Person>)
Tournament
  • Name (string)
  • EntryFee (decimal)
  • Teams (List<Team>)
  • Match (List<Match>)
  • Prizes (List<Prizes>)
  • Rounds (List<List<Match>)
Prize
  • Position (int)
  • PositionName (string)
  • PrizeAmount (decimal)
  • PrizePercentage (double)
Match
  • Entries (List<MatchRegistry>)
  • WinnerId (Team)
  • MatchRound (int)
MatchRegistry
  • CompetingTeam (Team)
  • Score (int)
  • ParentMatchId (Match)

User Interface Design

  • RECOMMENDED : Lay down the most possible UI layout on paper
  • Focus on UI layout only, Backend layout will be figured out later
  • Possible Forms to be designed and built as follows :
Form Type Calling Form Function
Tournament Dashboard Home Page/Main Form None Application - Start, End
Tournament Viewer Pop Up Form Tournament Dashboard Load Tournament
Create Tournament Pop Up Form Tournament Dashboard Create Tournament
Create Team Pop Up Form Create Tournament Create/Add Team, Members
Create Prize Pop Up Form Create Tournament Create Prize

  • NOTE :
    • Main Form or Tournament Dashboard must be open at the times for the application to be active
    • Main Form or Tournament Dashboard must be functionally detached from other Forms for the application to perform multiple tasks simultaneously, such as :
      • Create Tournament for an upcoming Tournament
      • Create/Add Teams to new Tournament
      • Create Prize for new Tournament
      • Load Tournament for viewing and updating status of an active Tournament on Tournament Viewer

Logic Plan - Wiring Frontend and Backend

  • Evaluate HOW :
    • Forms are interconnected
    • Forms are navigated, back and forth
      • For example : In Create Tournament, to create a new team and for that team to show up in the Teams/Players section, an Interface will be required
    • Items from Dropdown lists, such as Teams/Players and Prizes, are displayed :
      • Removed after selection
      • Added after deletion from display sections
      • Shown in the related display sections
    • Fields with required text values cannot be empty
    • Fields with decimal values cannot be negative
    • Create XYZ Form button - determines the Logic to randomize Teams into Rounds and Byes
    • Post completing Form function, Form closes returns to Calling Form
    • Information related to Tournament Viewer :
      • Tournament Name
      • Current Round and Rounds completed
      • Matches played and unplayed
      • Scoring only for current Round Matches
      • Email notifications on submitting scores
    • Data storage and access
    • Trigger for updating current Match outcomes and next Match details

SQL Database Design

  • SQL Server Developer Edition 2022 - includes all enterprise features except for a production environment
  • SSMS (SQL Server Management Studio) - GUI for managing databases, tables, relationships and connections
  • Database Design built using SSMS : Database Design
  • Stored Procedures :
    • Secure protocols to minimze SQL-Injection hacking attempts
    • Used to display data from Database tables in the application through simple query results

IMPLEMENTATION

Wiring Prize Form to Backend

  • How to validate incoming data ?
    • Verify if they are in the required format
  • How to save the received data ?
    • Create methods to save data to SQL Database and Text file
  • How to connect to SQL Database ?
    • Use the connection string in a Global Static Class
  • Where to store the incoming data ?
    • SQL Database or Text file or both
  • How to save the received data to both data storage points ?
    • Through an Interface

      What is an Interface ?
      • In simple terms, it is a calling card for structurally and functionally different classes under one umbrella
      • For Example: Let us consider health care costs in a family with adults, children and pets. Each category has their own issues but expenses would be paid with the same money.
      • Above example can be expressed in an Interface as :
      •   	// Health Record
          	class HealthInfo
          	{
          		// properties
          	}
          	
          	// Interfaces for health information and expenses
          	public interface IHealthCare 
          	{
          		double GetHealthExpenses();
          	}
          	
          	public interface IHealthInfo
          	{
          		List<HealthInfo> GetHealthInfo();
          	}
        
      • In the above Interface, an abstract method (method without implementation) is defined.
      • If a Class or Struct implements the Interface IHealthCare, it must define the method implementation of the interface member
      • In our example, above it is defined as follows :
      •   	// Adult Healthcare
          	class AdultHealthCare : IHealthInfo, IHealthCare
          	{
          		public List<HealthInfo> GetHealthInfo()
          		{
          			// code
          		}
          		
          		public double GetHealthExpenses()
          		{
          			// code
          		}
          	}
          	
          	// Pet Healthcare
          	class PetHealthCare : IHealthInfo, IHealthCare
          	{
          		public List<HealthInfo> GetHealthInfo()
          		{
          			// code
          		}
          		
          		public double GetHealthExpenses()
          		{
          			// code
          		}
          	}
        
      • In the above example, since the categories differ their health expense calculation also differs.
      • Hence, a full-abstract class/Interface supports building multiple Inheritance to better connect these categories.

Connecting SQL Server to Backend

  • To setup the backend connection to a database, in our case SQL Server, we need an ORM (Object-Relational Mapping) Tool.

    What is an ORM tool
    WHAT is an ORM Tool ?
    • ORM or Object-Relational Mapping is the process of handling database access and operations through
      Object-oriented paradigm
    • An ORM Tool is a library or a framework used to implement ORM functionality in an application, such as define database schema, perform CRUD operations, etc.
    • ORM Tools help by abstracting the low-level database handling events. For ex. Dapper and Entity Framework
    ORM Alternative
    • The namespace System.Data.SqlClient contains classes for accessing data from a SQL Servere database.
    • Nevertheless, this makes database access handling laborious, as every low-level database interaction must be manually managed.
  • Suitable ORM library/frameworks - ADO.NET, Dapper, Entity Framework (EF Core)

Feature ADO.NET Dapper EF Core
Performance Fast Faster than ADO.NET and EF Core Based on usage and configuration
Database Access Handling Manual Semi-Automated Automated
Generates Class model No No Yes
Generates Queries No No Yes
Object Tracking No No Yes
  • For this project, we chose Dapper as the ORM tool for the following reasons :

    • Basic Mapping between database tables and C# objects
    • Managing database connections
    • Control over SQL Queries
    • Enhanced performance
  • In the Frontend, App.config file needs to be configured with SQL Server Connection string

  • In the Backend, Models use ORM tool to perform CRUD operations to their respective tables in SQL Server Database

Data Processing To and From Text File

  • Similar to the database having a table for every Model, a text file for every Model is ideal.

  • Pseudo code :

    • Load text file,
    • Convert text file data to List
    • Read and Find max(ID)
    • Assign ID = max+1 for new prize data
    • Save List data
    • Convert List to text file
  • To generalize and automate this process for all the Models would be possible by an external library called, AutoMapper

  • AutoMapper is an Object-Object Mapper which could work ideally for our current Models,

  • In the current scenario, we explicitly :

    • convert text data to specific data types,
    • process the data
    • revert them back
    • and finally save them as text files
  • Hence, AutoMapper would be an efficient tool to refine the process.

Wiring Prize & Team Form to Tournament Form

  • In CreateTournamentForm there are two different options :
    • Call CreatePrizeForm to create a new prize
    • Call CreateTeamForm to create a new team/player
  • An Interface class ICreateRequestor is defined to act as an intermediate between
    • CreatePrizeForm <-> CreateTournamentForm through PrizeComplete member,
    • CreateTeamForm <-> CreateTournamentForm through TeamComplete member
  • In CreatePrizeForm and CreateTeamForm classes, this interface is declared in the constructor as a class variable
  • In their respective class methods which signify the process completion (createPrizeButton_Click and createTeamButton_Click) the Interface Members are called and model data is forwarded to the calling class, CreateTournamentForm.
  • In the calling class (CreatTournamentForm), the Interface Members(PrizeComplete and TeamComplete) are implemented
    • ListBox display list (availablePrizes) and Dropdown teams list (availableTeams) are updated.



Personal Takeaways

  • To figure out when to choose what kind of project model in Visual Studio. For example in this project :
    • ClassLibrary project model was chosen to build Backend (Data Models & Data Access configurations)
    • WindowsForms project was added as StartUp project to build Frontend (Forms)
  • Solution is built from the project. Hence, the final product should be signified in the Solution name.
ALWAYS follow this order of project development:
  • Break down logically complex tasks into smaller chunks
  • PLAN -> DESIGN -> Test IMPLEMENTATION -> DEBUG -> Repeat
  • Start simple and Build towards complex.
    For example, Interconnected UIs require data to test the connection. 
    Hence, start as follows : 
    populate data -> store data -> data interaction
  • Application Development Layout, as understood from Lessons so far (till Lesson10-SQL Connection) Application Development Layout

  • Post organizing files into directories, ALWAYS verify and modify namespaces

  • this modifier :

    • A parameter in a method is preceded by the above modifier

    • Used in Extension methods

    • Extension methods are in scope when explicitly imported with the respective namespaces into source code with a using directive

      Example Implementation
       // EXTENSION METHOD DEFINITION -
       namespace ExtensionMethods
       {
       	public static class MyExtension
       	{
       		public static int WordCount(this string str)
       		{
       			int count = str.Split(new char[] { ' ', '.', '?' }, 
       									StringSplitOptions.RemoveEmptyEntries).Length;
       			return count;
       		}
       	}
       }
       
      
       // SOURCE CODE - 
       // call with Instance method syntax as follows
       
       using ExtensionMethods;
      
       string s = "Hello Extension Method";
       int i = s.WordCount();
      
       
       // OR call with Static method syntax, by passing arguments
       
       string s = "Hello Extension Method";
       int i = MyExtension.WordCount(s);
  • Cases for data type casting :

    • VALID Case : string to int/double/decimal, i.e., from string to a numerical format
    • INVALID Case : int to double, viceversa, or to any other numerical format
      • Possible data loss and inefficient outputs
  • With current level of logical understanding, the following seems complex and hard to follow:

Debugging Code

  • Most likely errors, NullReferenceException
  • Start with Data storage format
  • Retrace to 'Save' and 'Load' methods
  • Dive into 'Helper-Save' or 'Helper-Load' methods, if any
  • Check that the proper methods are called in the right places
    • For ex. Text file storage
    • Calling the right files inside the corresponding 'Save/Load' methods alone is not enough
    • Make sure to supply the filepath as well
     public static void SaveEntryToTournamentsFile(this MatchRegistryModel entry, string MatchRegistryDataFile)
     {
     	//code
     	.
     	.
     	File.WriteAllLines(MatchRegistryDataFile.GetFilePath(), modelsData);
     }

About

Building a windows forms app using help of freeCodeCamp tutorial

License:MIT License


Languages

Language:C# 100.0%