Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reservation #2

Merged
merged 22 commits into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 30 additions & 15 deletions ProjectB/Models/AbstractUser.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
using static BCrypt.Net.BCrypt;
using Newtonsoft.Json;

namespace ProjectB.Models;

using BCrypt.Net;
using ProjectB.Models;
using System;

/// <summary>
/// Blueprint for users, containing the fields shared by all user types. This class should be implemented by sub-classes,
/// which specify the type of user, and implement unique functionality and fields based on that type.
/// </summary>
/// <param name="username">The username assigned to the user.</param>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er zijn een aantal van mijn comments weggevallen tijdens je commits. Zou je die weer terug willen plaatsen?

/// <param name="role">The role assigned to a user, used to determine what functionality should be available to said user.</param>
public abstract class AbstractUser(string username, UserRole role) : IEquatable<AbstractUser>, IEntity<string>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deze wijziging is niet nodig.

public abstract class AbstractUser : IEquatable<AbstractUser>, IEntity<string>
{
[JsonProperty] protected readonly string Username = username;
[JsonProperty] protected readonly UserRole Role = role;
[JsonProperty] protected readonly string Username;
[JsonProperty] protected readonly UserRole Role;

public AbstractUser(string username, UserRole role)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aparte constructor is niet nodig, omdat we die effectief al definiëren direct naar de naam van de class.

{
Username = username;
Role = role;
}

/// <summary>
/// Gets the role assigned to the user.
Expand All @@ -36,7 +39,7 @@ public UserRole GetUserRole()
/// <param name="other">The object which will be checked for equality with the object this method is called on.</param>
/// <returns>True if the objects are equal, false if not.</returns>
public abstract bool Equals(AbstractUser? other);

/// <summary>
/// Provides a more generic way to check for equality between an AbstractUser-instance and an instance of an unknown
/// type.
Expand Down Expand Up @@ -65,9 +68,10 @@ public override int GetHashCode()
private class Builder
{
private string? _username;
private string? _password;
private int _ticketNumber; // Add ticketNumber field
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Een apart ticket-number field is niet nodig. We kunnen de _username gewoon gebruiken.

private UserRole _role;
private DateOnly _validForDate;
private string? _password; // Add password field

/// <summary>
/// Sets the username that will be set, when the Builder.Build()-method is called.
Expand All @@ -80,16 +84,27 @@ public Builder WithUsername(string username)
return this;
}

/// <summary>
/// Sets the ticket number for the guest user.
/// </summary>
/// <param name="ticketNumber">The ticket number of the guest user.</param>
/// <returns>This instance of the Builder-pattern.</returns>
public Builder WithTicketNumber(int ticketNumber)
{
_ticketNumber = ticketNumber;
return this;
}

/// <summary>
/// Sets the password that will be set, when the Builder.Build()-method is called. Before setting the password,
/// the given value is hashed, using BCrypt's EnhancedHashPassword-method. If the role of the user is
/// the given value is hashed, using BCrypt's HashPassword-method. If the role of the user is
/// UserRole.Guest, the password will be ignored.
/// </summary>
/// <param name="password">The password that will be set.</param>
/// <returns>This instance of the Builder.</returns>
public Builder WithPassword(string password)
{
_password = BCrypt.EnhancedHashPassword(password);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gelieve wel weer EnhancedHashPassword gebruiken. Anders werkt de verification ook niet meer.

_password = HashPassword(password); // Change to BCrypt.HashPassword
return this;
}

Expand Down Expand Up @@ -125,10 +140,10 @@ public AbstractUser Build()
{
if (_role == UserRole.Guest)
{
return new Guest(_username!, _validForDate);
return new Guest(_username!, _validForDate, _ticketNumber); // Include ticketNumber
}

return new Employee(_username!, _role, _password!);
}
}
}
}
36 changes: 23 additions & 13 deletions ProjectB/Models/Guest.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
using Newtonsoft.Json;

namespace ProjectB.Models;

public class Guest(string username, DateOnly validForDate) : AbstractUser(username, UserRole.Guest)
namespace ProjectB.Models
{
[JsonProperty] private readonly DateOnly _validForDate = validForDate;

public bool IsValid() => _validForDate.CompareTo(DateTime.Today) == 0;

public override bool Equals(AbstractUser? other)
public class Guest : AbstractUser
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Het wijzigen van de constructor is niet nodig, omdat ticketnumber geen nieuwe field hoeft te zijn. Gebruik username daarvoor.

{
if (ReferenceEquals(other, this)) return true;
if (ReferenceEquals(other, null)) return false;
if (other.GetType() != GetType()) return false;
return Username == other.GetId();
[JsonProperty]
private readonly DateOnly _validForDate;

public int TicketNumber { get; set; }

public Guest(string username, DateOnly validForDate, int ticketNumber) : base(username, UserRole.Guest)
{
_validForDate = validForDate;
TicketNumber = ticketNumber;
}

public bool IsValid() => _validForDate.CompareTo(DateTime.Today) == 0;

public override bool Equals(AbstractUser? other)
{
if (ReferenceEquals(other, this)) return true;
if (ReferenceEquals(other, null)) return false;
if (other.GetType() != GetType()) return false;
return Username == other.GetId();
}
}
}
}
16 changes: 0 additions & 16 deletions ProjectB/Program.cs

This file was deleted.

197 changes: 197 additions & 0 deletions ProjectB/Reservation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using ProjectB.Models;

class Reservation
{
static List<Tour> tours = new List<Tour>(); // List to store available tours
static string jsonFilePath = "signups.json";

static void Main(string[] args)
{
LoadParticipantsFromJson(); // Load sign-up data from JSON file, if exists

// Get the current hour
int currentHour = DateTime.Now.Hour;

// Create tours for each hour from the current hour to 8 PM
for (int hour = currentHour; hour <= 20; hour++)
{
DateTime tourTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, 0, 0);
Tour tour = new Tour(tourTime, "Your Tour Location", 13); // Initialize tours with default capacity of 13
tours.Add(tour);
}

// Register event handler to save sign-up data on application exit
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);

bool exit = false;
while (!exit)
{
Console.WriteLine("Welcome to our museum!");
Console.WriteLine("Please choose an option:");
Console.WriteLine("1. Sign up for a tour");
Console.WriteLine("2. Delete your sign-up for a tour");
Console.WriteLine("3. Exit");

int option;
while (!int.TryParse(Console.ReadLine(), out option) || (option < 1 || option > 3))
{
Console.WriteLine("Invalid input. Please enter a number between 1 and 3.");
}

switch (option)
{
case 1:
SignUpForTour();
break;
case 2:
DeleteSignUpForTour();
break;
case 3:
Console.WriteLine("Thank you for visiting our museum! Goodbye.");
exit = true;
break;
}
}
}

static void CurrentDomain_ProcessExit(object? sender, EventArgs e)
{
SaveParticipantsToJson(); // Save sign-up data on application exit
}

static void SignUpForTour()
{
Console.WriteLine("Available Tours:");
for (int i = 0; i < tours.Count; i++)
{
int spotsLeft = tours[i].Capacity - tours[i].Participants.Count;
Console.WriteLine($"{i + 1}. Tour at {tours[i].Time.ToString("HH:mm")}, {spotsLeft} spots left");
}
Console.WriteLine("0. Go back");

Console.Write("Enter the number of the tour you want to sign up for (or 0 to go back): ");
int tourNumber;
while (!int.TryParse(Console.ReadLine(), out tourNumber) || (tourNumber < 0 || tourNumber > tours.Count))
{
Console.WriteLine($"Invalid input. Please enter a number between 0 and {tours.Count}.");
}

if (tourNumber == 0)
{
return; // Go back to main menu
}

Tour selectedTour = tours[tourNumber - 1];

if (selectedTour.Participants.Count >= selectedTour.Capacity)
{
Console.WriteLine($"Sorry, the tour at {selectedTour.Time.ToString("HH:mm")} is already fully booked.");
return;
}

Console.Write("Enter your ticket number: ");
int ticketNumber;
while (!int.TryParse(Console.ReadLine(), out ticketNumber) || ticketNumber <= 0)
{
Console.WriteLine("Invalid input. Ticket number must be a positive integer.");
Console.Write("Enter your ticket number: ");
}

if (selectedTour.Participants.Any(p => p.TicketNumber == ticketNumber))
{
Console.WriteLine($"Ticket number {ticketNumber} is already signed up for a tour.");

Console.Write("Do you want to change your sign-up (Y/N)? ");
string? response = Console.ReadLine()!.Trim().ToUpper();
if (response == "Y")
{
var guestToRemove = selectedTour.Participants.FirstOrDefault(p => p.TicketNumber == ticketNumber);
if (guestToRemove != null)
{
selectedTour.Participants.Remove(guestToRemove); // Remove existing sign-up
}
}
else
{
return; // Go back to main menu
}
}

// Modify this line to create a Guest object instead of a Participant
Guest guest = new Guest("username", DateOnly.FromDateTime(DateTime.Today), ticketNumber);
selectedTour.Participants.Add(guest); // Add new sign-up

SaveParticipantsToJson(); // Save immediately after sign-up

Console.WriteLine($"You have successfully signed up for the tour at {selectedTour.Time.ToString("HH:mm")}.");
}

static void DeleteSignUpForTour()
{
Console.Write("Enter your ticket number to delete your sign-up: ");
int ticketNumberToDelete;
while (!int.TryParse(Console.ReadLine(), out ticketNumberToDelete) || ticketNumberToDelete <= 0)
{
Console.WriteLine("Invalid input. Ticket number must be a positive integer.");
}

foreach (var tour in tours)
{
var guestToRemove = tour.Participants.FirstOrDefault(p => p.TicketNumber == ticketNumberToDelete);
if (guestToRemove != null)
{
tour.Participants.Remove(guestToRemove); // Remove sign-up

SaveParticipantsToJson(); // Save immediately after deletion

Console.WriteLine($"Your sign-up for the tour at {tour.Time.ToString("HH:mm")} has been deleted.");
return;
}
}

Console.WriteLine($"No sign-up found for ticket number {ticketNumberToDelete}.");
}


static void LoadParticipantsFromJson()
{
if (File.Exists(jsonFilePath))
{
string json = File.ReadAllText(jsonFilePath);
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, List<int>>>(json); // Use JsonConvert.DeserializeObject from Newtonsoft.Json

foreach (var kvp in dictionary!)
{
DateTime tourTime = DateTime.Parse(kvp.Key);
Tour? tour = tours.FirstOrDefault(t => t.Time == tourTime);
if (tour != null)
{
foreach (var ticketNumber in kvp.Value)
{
// Modify this line to create a Guest object instead of a Participant
Guest guest = new Guest("username", DateOnly.FromDateTime(DateTime.Today), ticketNumber);
tour.Participants.Add(guest); // Add guest to existing tour
}
}
}
}
}

static void SaveParticipantsToJson()
{
var dataToSerialize = new Dictionary<string, List<int>>();

foreach (var tour in tours)
{
dataToSerialize.Add(tour.Time.ToString(), tour.Participants.Select(p => p.TicketNumber).ToList());
}

string json = JsonConvert.SerializeObject(dataToSerialize); // Use JsonConvert.SerializeObject from Newtonsoft.Json
File.WriteAllText(jsonFilePath, json); // Write sign-up data to JSON file
}
}
Loading