0

I'm starting to program in C# .NET. I've made a web calendar for workers where they can view how many days they didn't go to work due a disease, holidays, etc. At first I did it with 2 arrays. One for a full calendar with these dimensions:

calendar[person_code][month][day][6 items] -> calendar[int][int][int][object (starting absence date, type of absence, etc.)]

The other one is an array with one worker definition like

person[person_code][13 items] -> person[int][13 string (name, surname, etc.)]

I'd like to do this with classes to improve my code. I've thinking about the classes above:

public class absence 
{ 
  public int absenceCode { get; set; }
  public int typeAbsence { get; set; }
  public DateTime startingDate { get; set; }
  public DateTime endingDate { get; set; }
  public string description { get; set; }
  public string state { get; set; }

  public constructors...
}

public class calendar 
{
  public int day { get; set; }
  public int month { get; set; }
  public absence absen { get; set; }

  public contructors....
}

public class person 
{
  public int personCode { get; set; }
  public string surname { get; set; }
  public string name { get; set; }
  public string address { get; set; }
  public int maxHolidayDays { get; set; }
  public calendar calend { get; set; }
 
  public constructors....
}

That is my code but I don't know how to handle to set and retrieve information like working with arrays. I can create a new instance of person for each one but I'd need to create some absences in a unique day. (One worker could absent from work some times in a day) I had though about using a List(T) class like

List<person> = new List<person>(), and List<absence> = new List<absence>()

but how could I set a List<absence>() nested in a one day of "calendar" class? I need to set that List inside a calendar day which has below a person from a List.

List<person> -> calendar -> List<absence>

I hope it's enough clear for you. Regards.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Grefu
  • 1
  • 1
    Side note: You need to start following the naming conventions: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions – Zein Makki Jun 13 '17 at 08:00
  • 1
    Could you be clearer? Like making a hierarchy of the wanted data-structure you want to make? As far as i understand, you could make a list of `calendar` in `person`, to hold every absence your worker has. – Alex Ferretti Jun 13 '17 at 08:02
  • As to me, you don't need `calendar` class to be able to get all absences of person. – Maciej Los Jun 13 '17 at 08:28
  • As I said I'm learning C# so I used arrays cause is easiest for me. Hiercharchy structure should be: One person has a calendar asociated wich has or hasn't some absences per day. P. ej. John Doe has a calendar wich has a absence on 3rd. January and two absences on 6th June. I could define a person class with a List absence property wich would has all those absence but I think that not correct at all. I think is pretty clear to have a class for person, a class for calendar and a class for absences. What do you think? – Grefu Jun 13 '17 at 08:53

2 Answers2

0

I would do it like this. 1.Skip calendar class 2.In person class add collection of absences (e.g. List) 3.If you have IEnumerable (e.g. List, person[]) you can search for data you need

public class absence
{
    public int absenceCode { get; set; }
    public int typeAbsence { get; set; }
    public DateTime startingDate { get; set; }
    public DateTime endingDate { get; set; }
    public string description { get; set; }
    public string state { get; set; }
}

public class person
{
    public int personCode { get; set; }
    public string surname { get; set; }
    public string name { get; set; }
    public string address { get; set; }
    public int maxHolidayDays { get; set; }
    // Initialize in constructor if you have an error
    public List<absence> absences { get; set; } = new List<absence>();
}

As for searching it would be quite easy. Lets say you need people absent at specific date:

IEnumerable<person> Persons = GetPersonsList();
DateTime dateToCheck = GetAbsentDate();

var absentPersons = Persons.Where(x=>x.absences.Any(a=>a.startingDate>= dateToCheck&&a.endingDate<= dateToCheck));
Pablo notPicasso
  • 3,031
  • 3
  • 17
  • 22
  • Oh! very nice!! It's clearer by this way. I didn't think about using Linq – Grefu Jun 13 '17 at 09:02
  • Think of it. What kind of relationship is becoming between person and absence? One person my have several absences... So, absence should be a part of person or otherwise? – Maciej Los Jun 13 '17 at 09:15
  • It should be a 1:n relationship. It could be that 2 workers absent from work at same day for the same reason. There would be 2 equal absences but each one be belonging to someone else. There is a "person code" property for it, but I think working with classes it's no neccesary, isn't it? – Grefu Jun 13 '17 at 09:40
  • @Grefu, please use a [`@Login`] convention on the beginning of reply to be sure that OP will be notified about it. – Maciej Los Jun 13 '17 at 11:21
0

First of all, as user3185569 mentioned in the comment to the question, you have change your code using this instruction: Capitalization Conventions

Secondly, you have to think about data representation. What kind if relationship becomes between person and absence? One person may have several absences (a 1:N relationship). So, you have to store data about absences and a person related with this absence.

Classes:

public class Person 
{
    public int PersonCode { get; set; }
    public string Surname { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    //constructor, etc.

    public override string ToString()
    {
        return string.Format("{0} {1} {2} {3}", PersonCode, Surname, Name, Address);
    }

}

public class Absence 
{ 
    public int AbsenceCode { get; set; }
    public int TypeAbsence { get; set; }
    public DateTime StartingDate { get; set; }
    public DateTime EndingDate { get; set; }
    public string Description { get; set; }
    public string State { get; set; }
    //"a link" to person
    public Person Person { get; set; }

    //constructor, etc.

    public override string ToString()
    {
        return string.Format("{0}\t|\t{1}\t{2}\t{3}", Person.ToString(), TypeAbsence.ToString(), 
            StartingDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture),
            EndingDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture));

    }
}

Usage:

List<Person> persons = new List<Person>()
    {
        new Person() {PersonCode = 1, Surname = "Los", Name = "Maciej", Address = "Poland, ..."},
        new Person() {PersonCode = 2, Surname = "Doe", Name = "John", Address = "USA, ..."},
        new Person() {PersonCode = 3, Surname = "McAlister", Name = "Fred", Address = "UK, ..."},
        new Person() {PersonCode = 4, Surname = "Sommer", Name = "Anna", Address = "Canada, ..."},
    };

List<Absence> absences = new List<Absence>()
    {
        new Absence(){AbsenceCode = 1, TypeAbsence=1, StartingDate = new DateTime(2017,5,11), EndingDate = new DateTime(2017,5,15),
            Description = "whatever", State = "A", Person = persons[0]},
        new Absence(){AbsenceCode = 2, TypeAbsence=1, StartingDate = new DateTime(2017,5,18), EndingDate = new DateTime(2017,6,8),
            Description = "whatever", State = "A", Person = persons[1]},
        new Absence(){AbsenceCode = 3, TypeAbsence=2, StartingDate = new DateTime(2017,6,1), EndingDate = new DateTime(2017,6,12),
            Description = "whatever", State = "B", Person = persons[2]},
        new Absence(){AbsenceCode = 4, TypeAbsence=2, StartingDate = new DateTime(2017,6,1), EndingDate = new DateTime(2017,6,5),
            Description = "whatever", State = "B", Person = persons[0]},
        new Absence(){AbsenceCode = 5, TypeAbsence=1, StartingDate = new DateTime(2017,6,2), EndingDate = new DateTime(2017,6,5),
            Description = "whatever", State = "A", Person = persons[2]}
    };

//define date-range to filter Absences data 
DateTime dfrom = new DateTime(2017,6,5);
DateTime dTo = new DateTime(2017,6,9);

var LastWeekAbsencesByPerson = absences
    .Where(x=> (x.StartingDate<=dTo) && (x.EndingDate>=dfrom))
    .OrderBy(x => x.Person.Surname)
    .ThenBy(x => x.StartingDate)
    .ToList();

foreach(var lwabp in LastWeekAbsencesByPerson)
{
    Console.WriteLine("{0}", lwabp.ToString());
    Console.WriteLine("{0}", new string('-', 60));
}

On the same manner, you can filter data by date, person, type of absence, etc.

As to the date filter, i'd strongly recommend to read this: Determine Whether Two Date Ranges Overlap

There's a lot of things to do, to improve, but this is your job.

Good luck!

Maciej Los
  • 8,468
  • 1
  • 20
  • 35