From 01509e372bfa71d09ea2227d810d89c66afde600 Mon Sep 17 00:00:00 2001 From: Joel Date: Wed, 29 Jul 2026 21:25:04 +0100 Subject: [PATCH] Add Coding tracker project --- Coding-Tracker/.vscode/launch.json | 20 +++ .../Coding-Tracker/Coding tracker.txt | 77 +++++++++++ .../Coding-Tracker/Coding-Tracker.csproj | 28 ++++ .../Coding-Tracker/Coding-Tracker.db | Bin 0 -> 12288 bytes .../Coding-Tracker/CodingController.cs | 123 ++++++++++++++++++ .../Coding-Tracker/CodingSession.cs | 15 +++ Coding-Tracker/Coding-Tracker/Program1.cs | 18 +++ Coding-Tracker/Coding-Tracker/UserInput.cs | 118 +++++++++++++++++ Coding-Tracker/Coding-Tracker/Validation.cs | 37 ++++++ .../Coding-Tracker/appsettings.json | 5 + 10 files changed, 441 insertions(+) create mode 100644 Coding-Tracker/.vscode/launch.json create mode 100644 Coding-Tracker/Coding-Tracker/Coding tracker.txt create mode 100644 Coding-Tracker/Coding-Tracker/Coding-Tracker.csproj create mode 100644 Coding-Tracker/Coding-Tracker/Coding-Tracker.db create mode 100644 Coding-Tracker/Coding-Tracker/CodingController.cs create mode 100644 Coding-Tracker/Coding-Tracker/CodingSession.cs create mode 100644 Coding-Tracker/Coding-Tracker/Program1.cs create mode 100644 Coding-Tracker/Coding-Tracker/UserInput.cs create mode 100644 Coding-Tracker/Coding-Tracker/Validation.cs create mode 100644 Coding-Tracker/Coding-Tracker/appsettings.json diff --git a/Coding-Tracker/.vscode/launch.json b/Coding-Tracker/.vscode/launch.json new file mode 100644 index 000000000..af41789e1 --- /dev/null +++ b/Coding-Tracker/.vscode/launch.json @@ -0,0 +1,20 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "External Terminal, .NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "${defaultBuildTask}", + "program": "C:/Users/j_men/Coding-Tracker/Coding-Tracker/bin/debug/net10.0/Coding-Tracker.dll", + "args": [], + "cwd": "${workspaceFolder}/Coding-tracker", + "stopAtEntry": false, + "console": "externalTerminal" + } + ], + +} \ No newline at end of file diff --git a/Coding-Tracker/Coding-Tracker/Coding tracker.txt b/Coding-Tracker/Coding-Tracker/Coding tracker.txt new file mode 100644 index 000000000..4d102d5c4 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/Coding tracker.txt @@ -0,0 +1,77 @@ +Coding tracker + +I was tasked with creating a coding tracker, an application that allows the user to Create, View/Read, Update and Delete any record that users enter. + +I needed four classes and a program file that acts as the entry point for the program. + +The coding tracker differs from the habit tracker in a few areas, the habit tracker used ADO.NET to write to the databse and to view the database we used an external terminal. + +The habit tracker also holds all the data in one class (program.cs) whereas the coding tracker uses separation of concerns to split the different functions into classes. + +An appsettings.json file was created so I could place the database connectionstring inside of it, to access the string I created a configuration builder which adds the file and builds it + +we store our new configuration as connectionstring, so whenever our database needs accessing we call on "connectionstring" which holds the data source of our database. + + +CodingController +The coding controller class is responsible for database operations this is where we make use of Dapper and Spectre. +Dapper is used to simplify the commands we need to communicate with our database. +Spectre was used in this project to present our data in a table in the terminal which makes viewing our user input neater and more presentable. + + +I created a CreateTable Method that uses the Dapper syntax to execute the SQL to create the table with the variables I chose, ID, StartTime, EndTime and duration. We use the connectionstring we created to create a variable that will communicate with the database. + +Create table is called as we need to create the table before anything happens. +I needed to create a method called viewRecords that contained my initial record viewer method GETallrecords as I faced issues with user input. +The method calls get all records then asks the user to "Press any key to return to main menu" followed by a readkey that exits the method. + +Getallrecords clears the console, uses connectionstring to create connectionString to create a connection to the SQLite database. It maps each row from the table to the coding tracker object. + +The returned collection is converted into a List and stored in the tableData variable. + +I created a new table and added columns for each variable where each variable would go. +we use a foreach loop to add rows, we convert the output tostring and write them to the table. + +The Insert, Delete and update methods in coding controller rely on variables being passed in. + +The insert method needs two variables startime and endtime as we need the two to calculate duration +The delete method needs an id to delete so we must pass in an id. +The update method needs id , startTime and datetime to overwrite the initial values. + +The variables being passed into the controller methods rely on user input. + +UserInput + +User input has methods that take the users input and pass them into our controller class methods to do calculations and to insert, delete or update records before putting them into the database. + +GeTimeInput - used to gather users input for StartTime and End Time methods. +The method is designed to write a question, collect users input and return the input after being validated. +The ValidateTime method from the Validation class is used here + +The variable we use to gather the users input is passed into ValidateTime + +This method has a string parameter that asks the user what to enter +When called upon we must write the question we are asking the user for example in InsertInput; + +startTime = GeTimeInput("Please enter the start Time Format: (HH:mm), Or enter 0 to exit."); +endTime = GeTimeInput("Please enter the end Time Format: (HH:mm), Or enter 0 to exit."); + +Then inside InsertInput when we call input " CodingController.Insert(startTime, endTime);" + +startTime and EndTime were passed into the method. + +InsertInput - Used to pass user input into the insert method + +DeleteInput - Used to pass user input into the delete method +clear the console +call the records +ask the record that we want to delete +collect it pass the input into our validation method +pass the collected input into the delete method. + + + + + + + diff --git a/Coding-Tracker/Coding-Tracker/Coding-Tracker.csproj b/Coding-Tracker/Coding-Tracker/Coding-Tracker.csproj new file mode 100644 index 000000000..b69b465e3 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/Coding-Tracker.csproj @@ -0,0 +1,28 @@ + + + + Exe + net10.0 + Coding_Tracker + enable + enable + + + + + + Always + + + + + + + + + + + + + + diff --git a/Coding-Tracker/Coding-Tracker/Coding-Tracker.db b/Coding-Tracker/Coding-Tracker/Coding-Tracker.db new file mode 100644 index 0000000000000000000000000000000000000000..d5a541b130a62c6ed80cc1ed3177b6d1836882ce GIT binary patch literal 12288 zcmeI&O-{l<6bJAb@FOw7DjQZNv(eZHrgSXGtVEp{qM~ArvN9E_X_OLcJ%BDef|qjZ zF+7B?5S5Y`H?H*mGVOF``rb6Zt_VFo+6!V|T=t`$7YoVe80Tz52*%hV9a%a)g44ys z$AJ1|{8KEl)h9DYcV%W@nXyDC1Oy-e0SG_<0uX=z1Rwwb2teSM1P(J(g_RZFj=hT; z|L*pNe&C+p`M39e*cl&Yw_3XHYT?#5_p}(hcRBQWevvZGhf_XXFirj#3~F}z-5|U= zk0Y;h?MLZRCRH)LCYEzEVk8<}(P+AQN4LabtFd2iwZ*P(i~5Os&}dSfecg16>6GKx zi()tE`NGv_t@8PA4i6zKv10SG_<0uX=z1Rwwb z2tWV=5cuZ;GC#?rT(B*>QnIQgyCy7KITdADqf-?n9h$PFk~Qk({78~hve!jfs tabledata = connection.Query("SELECT * FROM coding_tracker").ToList(); + + var table = new Table(); + + table.AddColumn("Id"); + table.AddColumn("Start Time"); + table.AddColumn("End Time"); + table.AddColumn("Duration"); + + foreach (var session in tabledata) + { + table.AddRow( + session.Id.ToString(), + session.StartTime.ToString(), + session.EndTime.ToString(), + session.Duration.ToString() + ); + } + + AnsiConsole.Write(table); + } + + } + + public static void Insert(DateTime startTime, DateTime endTime) + { + + string duration = (endTime - startTime).ToString(); + + using (var connection = new SqliteConnection(connectionString)) + { + int rowsAffected = connection.Execute("INSERT INTO coding_tracker (StartTime, EndTime, Duration) VALUES (@StartTime, @EndTime, @Duration)", + new { StartTime = startTime, EndTime = endTime, Duration = duration }); + Console.WriteLine("Record Inserted.\nPress any key to return to main menu."); + Console.ReadKey(); + } + } + + public static void Delete(int id) + { + + using (var connection = new SqliteConnection(connectionString)) + { + int rowsAffected = connection.Execute("DELETE FROM coding_tracker WHERE Id = @Id", new { Id = id }); + + if (rowsAffected == 0) + Console.WriteLine("No record found with that ID."); + else + Console.WriteLine("Record Deleted.\nPress any key to return to main menu."); + + Console.ReadKey(); + } + } + + public static void Update(int ID, DateTime startTime, DateTime endTime) + { + + + using (var connection = new SqliteConnection(connectionString)) + { + + int rowsAffected = connection.Execute("UPDATE coding_tracker SET StartTime = @StartTime, EndTime = @EndTime WHERE ID = @Id", + new { Id = ID, StartTime = startTime, EndTime = endTime }); + + if (rowsAffected == 0) + { + Console.WriteLine("No record found with that ID."); + } + else + Console.WriteLine("Record Updated.\nPress any key to return to main menu."); + + Console.ReadKey(); + + } + } +} + + + + + + diff --git a/Coding-Tracker/Coding-Tracker/CodingSession.cs b/Coding-Tracker/Coding-Tracker/CodingSession.cs new file mode 100644 index 000000000..33f222a13 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/CodingSession.cs @@ -0,0 +1,15 @@ +// CodingSession.cs — the model + +public class Codingtracker +{ + public int Id { get; set; } + + public DateTime StartTime { get; set; } + + public DateTime EndTime { get; set; } + + public string Duration { get; set; } + +} + + diff --git a/Coding-Tracker/Coding-Tracker/Program1.cs b/Coding-Tracker/Coding-Tracker/Program1.cs new file mode 100644 index 000000000..d4f3f92e9 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/Program1.cs @@ -0,0 +1,18 @@ +using Microsoft.Data.Sqlite; +using Dapper; +using Spectre.Console; + +class Program1 +{ + static string connectionString = @"Data Source=habit-Tracker.db"; + + static void Main(string[] args) + { + { + CodingController.CreateTable(); + Input.GetUserInput(); + Console.ReadLine(); + } + } + +} diff --git a/Coding-Tracker/Coding-Tracker/UserInput.cs b/Coding-Tracker/Coding-Tracker/UserInput.cs new file mode 100644 index 000000000..9ead22ae8 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/UserInput.cs @@ -0,0 +1,118 @@ +using System.Runtime.ConstrainedExecution; + +public class Input +{ + public static void GetUserInput() + { + DateTime startTime; + DateTime endTime; + + bool end = false; + while (end == false) + { + Console.Clear(); + Console.WriteLine("Welcome to the coding tracker!\n"); + Console.WriteLine("What would you like to do?"); + Console.WriteLine("Press 0 to close the console."); + Console.WriteLine("Press 1 to view Records."); + Console.WriteLine("Press 2 to Insert a Record."); + Console.WriteLine("Press 3 to Delete a Record."); + Console.WriteLine("Press 4 to Update a Record."); + + string command = Console.ReadLine(); + + switch (command) + { + case "0": + end = true; + Console.WriteLine("Goodbye\nPress any key to quit."); + Console.ReadLine(); + Environment.Exit(0); + break; + + case "1": + CodingController.ViewRecords(); + break; + + case "2": + InsertInput(); + break; + + case "3": + DeleteInput(); + break; + + case "4": + UpdateInput(); + break; + + default: + Console.WriteLine("Please enter an option between 1 and 4."); + break; + } + + } + } + + public static DateTime GeTimeInput(string message) + { + Console.WriteLine(message); + string getTime = Console.ReadLine(); + + if (getTime == "0") GetUserInput(); + + return Validation.ValidateTime(getTime); + } + + public static void InsertInput() + { + Console.Clear(); + + DateTime startTime; + DateTime endTime; + + startTime = GeTimeInput("Please enter the start Time Format: (HH:mm), Or enter 0 to exit."); + endTime = GeTimeInput("Please enter the end Time Format: (HH:mm), Or enter 0 to exit."); + + CodingController.Insert(startTime, endTime); + + } + + public static void DeleteInput() + { + Console.Clear(); + CodingController.GetAllRecords(); + + Console.WriteLine("Please enter a record ID to delete.\n\n"); + + int id = Validation.ValidateId(Console.ReadLine()); + + CodingController.Delete(id); + + } + + + public static void UpdateInput() + { + Console.Clear(); + CodingController.GetAllRecords(); + + Console.WriteLine("Please type Id of the record you want to update. Type 0 to return to main menu.\n\n"); + + int ID = Validation.ValidateId(Console.ReadLine()); + + Console.WriteLine("Please enter a Start Time ID to Update."); + + DateTime startTime = Validation.ValidateTime(Console.ReadLine()); + + Console.WriteLine("Please enter a End Time ID to Update."); + + DateTime endTime = Validation.ValidateTime(Console.ReadLine()); + + CodingController.Update(ID, startTime, endTime); + + } + + + +} \ No newline at end of file diff --git a/Coding-Tracker/Coding-Tracker/Validation.cs b/Coding-Tracker/Coding-Tracker/Validation.cs new file mode 100644 index 000000000..4583a4764 --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/Validation.cs @@ -0,0 +1,37 @@ +using System.Globalization; + +class Validation +{ + public static DateTime ValidateTime(string getTime) + { + + DateTime result; + while (!DateTime.TryParseExact(getTime, "HH:mm", null, DateTimeStyles.None, out result)) + { + Console.WriteLine("Invalid format. Try again (HH:mm): "); + getTime = Console.ReadLine(); + } + + return result; + } + + + public static int ValidateId(string Input) + { + // Console.WriteLine($"Input received: '{Input}'"); + + int result; + + while (!int.TryParse(Input, out result) || (result <= 0)) + { + Console.WriteLine("Please enter a valid id"); + Input = Console.ReadLine(); + } + + return result; + + } + + + +} \ No newline at end of file diff --git a/Coding-Tracker/Coding-Tracker/appsettings.json b/Coding-Tracker/Coding-Tracker/appsettings.json new file mode 100644 index 000000000..9fdb8f5fe --- /dev/null +++ b/Coding-Tracker/Coding-Tracker/appsettings.json @@ -0,0 +1,5 @@ +{ + "ConnectionStrings": { + "DefaultConnection": "Data Source=Coding-Tracker.db" + } +} \ No newline at end of file