Commit 8d3a6f0c authored by Stojcheska Teodora's avatar Stojcheska Teodora
Browse files

and

parent dd091539

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31229.75
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Scheduler", "Scheduler.csproj", "{1F6FE665-3863-440A-97E8-12B5F87E0078}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F6FE665-3863-440A-97E8-12B5F87E0078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F6FE665-3863-440A-97E8-12B5F87E0078}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F6FE665-3863-440A-97E8-12B5F87E0078}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F6FE665-3863-440A-97E8-12B5F87E0078}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7F49CCE7-A332-47C1-9A48-AADACCDE928E}
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
\ No newline at end of file
using System;
using System.Collections.Generic;
using static System.Console;
[Serializable]
public class Calendar
{
public List<Day> days { get; set; }
public DateTime currentDate { get; set; }
public (int, int) defaultWorkingHoursInterval { get; set; }
public int defaultWorkingHours { get; set; }
public Calendar()
{
this.days = new List<Day>();
this.currentDate = DateTime.Now; // format dd.mm.yyyy hh:mm:ss
}
public Calendar(List<Day> days)
{
this.days = days;
this.currentDate = DateTime.Now; // format dd.mm.yyyy hh:mm:ss
}
/* ----------------------------- Utilities ------------------------------ */
private static int numberOfDaysInRange(DateTime startingDate, DateTime endDate) => (endDate.Date - startingDate.Date).Days + 1;
private bool isDateValid(DateTime startingDate, DateTime endDate) => numberOfDaysInRange(startingDate, endDate) > 0;
private bool shouldAddDay(Task task) => days[days.Count - 1].hoursToShift * -1 < task.duration;
public Day getDayByDate(DateTime date)
{
foreach(Day day in days)
{
if(day.date.Date == date.Date)
{
return day;
}
}
WriteLine("Day has not been added -> check for error");
return null;
}
public static bool isDateValid(string date)
{
DateTime val;
if (DateTime.TryParse(date, out val))
{
if (numberOfDaysInRange(DateTime.Now, val) > 0)
{
return true;
}
}
return false;
}
public List<Day> getRangeOfDaysForTask(Task task)
{
List<Day> validDays = new List<Day>();
Day newDay;
if (days.Count == 0)
{
newDay = new Day(currentDate, new List<Task>(), defaultWorkingHoursInterval, defaultWorkingHours);
days.Add(newDay);
validDays.Add(newDay);
return validDays;
}
if (shouldAddDay(task))
{
newDay = new Day(days[days.Count - 1].date.AddDays(1), new List<Task>(), defaultWorkingHoursInterval, defaultWorkingHours);
newDay.prevDay = days[days.Count - 1];
days[days.Count - 1].nextDay = newDay;
days.Add(newDay);
}
int numberOfValidDaysInRange = numberOfDaysInRange(currentDate, task.deadline);
if (numberOfValidDaysInRange == 0)
{
WriteLine("The date is not valid!");
}
for (int i = 0; i < numberOfValidDaysInRange; ++i)
{
if (days.Count <= i)
{
break;
}
validDays.Add(days[i]);
}
return validDays;
}
/* ---------------------------------- Exception Handling ----------------------------------- */
public void errorCheck(Task task, List<Day> validDays, ref Day d)
{
for (int i = 0; i < validDays.Count; ++i)
{
if (!validDays[i].isDayFull(0))
{
break;
}
d = validDays[i];
}
int hours = 0;
Day cur = d;
while (cur != null && validDays.Contains(cur))
{
hours += cur.hoursToShift * -1;
cur = cur.nextDay;
}
if (hours < task.duration)
{
WriteLine("No space to add task");
validDays[validDays.Count - 1].addTask(task, validDays[validDays.Count - 1].tasks.Count);
throw new NoSpaceForTaskExeption("There is no space to add the task which needs to be added as the last task in the calendar", d, task, hours - task.duration);
}
}
/* ------------------------------- Add Task --------------------------------- */
public void addTask(Task task)
{
try
{
if(task.type == Type.NORMAL)
{
_addTask(task);
}
else if(task.type == Type.FIXED)
{
addFixedTask(task);
}
}
catch (NoSpaceForTaskExeption exception)
{
Day day = getDayByDate(task.deadline);
day.removeTask(task);
deleteReorderCalendar(exception.day.nextDay, day.hoursToShift * -1, day);
}
}
public void addFixedTask(Task task)
{
if (days.Count == 0)
{
days.Add(new Day(currentDate, new List<Task>(), defaultWorkingHoursInterval, defaultWorkingHours));
}
Day day;
if (numberOfDaysInRange(task.deadline, days[days.Count - 1].date) > 0){
day = getDayByDate(task.deadline);
day.addTask(task, 0);
reorderCalendar(day, task.duration, true, null);
}
else
{
while(numberOfDaysInRange(task.deadline, days[days.Count - 1].date) <= 0)
{
Day newDay = new Day(days[days.Count - 1].date.AddDays(1), new List<Task>(), defaultWorkingHoursInterval, defaultWorkingHours);
days[days.Count - 1].nextDay = newDay;
newDay.prevDay = days[days.Count - 1];
days.Add(newDay);
}
day = getDayByDate(task.deadline);
day.addTask(task, 0);
}
}
public void _addTask(Task task)
{
List<Day> validDays = getRangeOfDaysForTask(task);
foreach (Day day in validDays)
{
for (int i = 0; i < day.tasks.Count; ++i)
{
if (numberOfDaysInRange(day.tasks[i].deadline, task.deadline) <= 0 && day.tasks[i].type != Type.FIXED)
{
day.addTask(task, i);
if (day.isDayFull(0))
{
reorderCalendar(day, day.hoursToShift, true, null);
}
return;
}
}
}
Day d = validDays[0];
errorCheck(task, validDays, ref d);
d.addTask(task, d.tasks.Count);
if (d.isDayFull(0))
{
reorderCalendar(d, d.hoursToShift, true, null);
}
}
private void reorderCalendar(Day day, int hours, bool next, Day returnPoint)
{
Day dirDay = day.nextDay;
if (dirDay == null || day.hoursToShift <= 0) { return; }
List<Task> tasks = new List<Task>();
for (int i = day.tasks.Count - 1; i >= 0; --i)
{
if (day.tasks[i].type != Type.FIXED)
{
if (hours == 0) { break; }
Task curTask = day.tasks[i];
if (!isDateValid(dirDay.date, curTask.deadline))
{
foreach (Task task in tasks) { day.addTask(task, day.tasks.Count); }
throw new NoSpaceForTaskExeption("There is no space to add the task, error occured during shifting the tasks", day, curTask, hours);
}
if (curTask.duration > hours)
{
int additionalHours = 0;
if (curTask.isSplit)
{
additionalHours = curTask.splitTaskPtr.duration;
dirDay.removeTask(curTask.splitTaskPtr);
curTask.mergeTasks(curTask, curTask.splitTaskPtr);
}
int[] splitHours = { curTask.duration - hours - additionalHours, hours + additionalHours };
curTask.splitTask(splitHours, 0, curTask, day);
hours = 0;
tasks.Add(curTask.splitTaskPtr);
}
else
{
int curTaskHours = curTask.duration;
if (curTask.isSplit)
{
dirDay.removeTask(curTask.splitTaskPtr);
curTask.mergeTasks(curTask, curTask.splitTaskPtr);
}
else
{
tasks.Add(curTask);
}
hours -= curTaskHours;
day.removeTask(curTask);
}
}
}
foreach (Task task in tasks) { dirDay.addTask(task, 0); }
reorderCalendar(dirDay, dirDay.hoursToShift, next, null);
}
/* ------------------------------- Delete Task ----------------------------------- */
private void deleteReorderCalendar(Day day, int hours, Day returnPoint)
{
int h = hours;
Day dirDay = day.prevDay;
if (dirDay == null || day.Equals(returnPoint)) { return; }
List<Task> tasks = new List<Task>();
for (int i = 0; i < day.tasks.Count; ++i)
{
if (day.tasks[i].type != Type.FIXED)
{
if (hours == 0) { break; }
Task curTask = day.tasks[i];
if (curTask.duration > hours)
{
Task shiftSplitTask = new Task(curTask.name, curTask.deadline, hours, curTask.type, true);
shiftSplitTask.splitTaskPtr = curTask;
curTask.duration -= hours;
tasks.Add(shiftSplitTask);
hours = 0;
}
else
{
int curTaskHours = curTask.duration;
tasks.Add(curTask);
hours -= curTaskHours;
day.removeTask(curTask);
i--;
}
}
}
if (dirDay.tasks.Count != 0 && dirDay.tasks[dirDay.tasks.Count - 1].isSplit)
{
dirDay.tasks[dirDay.tasks.Count - 1].isSplit = tasks[0].isSplit;
dirDay.tasks[dirDay.tasks.Count - 1].splitTaskPtr = tasks[0].splitTaskPtr;
dirDay.tasks[dirDay.tasks.Count - 1].duration += tasks[0].duration;
tasks.RemoveAt(0);
}
for (int i = 0; i < tasks.Count; ++i)
{
dirDay.addTask(tasks[i], dirDay.tasks.Count);
}
deleteReorderCalendar(dirDay, h, returnPoint);
}
public void deleteTask(Day day, Task task)
{
if (task.isSplit)
{
day.nextDay.removeTask(task.splitTaskPtr);
task.isSplit = false;
deleteReorderCalendar(days[days.Count - 1], task.splitTaskPtr.duration, day.nextDay);
}
day.removeTask(task);
deleteReorderCalendar(days[days.Count - 1], task.duration, day);
}
}
\ No newline at end of file
using System.Windows.Forms;
namespace Scheduler.Controls
{
public partial class DatePicker : UserControl
{
/* ------------------------------ Private Variables ------------------------------*/
private HintTextBox day;
private HintTextBox month;
private HintTextBox year;
/* ------------------------------ Public Variables ------------------------------*/
public int Day { get => day.IsHintDisplayed ? 0 : int.Parse(day.Text); }
public int Month { get => month.IsHintDisplayed ? 0 : int.Parse(month.Text); }
public int Year { get => year.IsHintDisplayed ? 0 : int.Parse(year.Text); }
public string Date { get => $"{this.Day}/{this.Month}/{this.Year}"; }
/* ------------------------------ Private Methods ------------------------------*/
private void InitializeComponent()
{
this.day = new HintTextBox();
this.month = new HintTextBox();
this.year = new HintTextBox();
this.SuspendLayout();
//
// day
//
this.day.ForeColor = System.Drawing.Color.DarkGray;
this.day.Hint = "dd";
this.day.Location = new System.Drawing.Point(5, 5);
this.day.Margin = new Padding(5);
this.day.MaxLength = 2;
this.day.Name = "day";
this.day.Size = new System.Drawing.Size(35, 29);
this.day.TabIndex = 0;
this.day.Text = "dd";
this.day.TextAlign = HorizontalAlignment.Center;
//
// month
//
this.month.ForeColor = System.Drawing.Color.DarkGray;
this.month.Hint = "mm";
this.month.Location = new System.Drawing.Point(50, 5);
this.month.Margin = new Padding(5);
this.month.MaxLength = 2;
this.month.Name = "month";
this.month.Size = new System.Drawing.Size(35, 29);
this.month.TabIndex = 1;
this.month.Text = "mm";
this.month.TextAlign = HorizontalAlignment.Center;
//
// year
//
this.year.ForeColor = System.Drawing.Color.DarkGray;
this.year.Hint = "yyyy";
this.year.Location = new System.Drawing.Point(95, 5);
this.year.Margin = new Padding(5);
this.year.MaxLength = 4;
this.year.Name = "year";
this.year.Size = new System.Drawing.Size(45, 29);
this.year.TabIndex = 2;
this.year.Text = "yyyy";
this.year.TextAlign = HorizontalAlignment.Center;
//
// DatePicker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.Transparent;
this.Controls.Add(this.year);
this.Controls.Add(this.month);
this.Controls.Add(this.day);
this.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
this.Margin = new Padding(0);
this.Name = "DatePicker";
this.Size = new System.Drawing.Size(147, 40);
this.ResumeLayout();
}
private void HintTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = !char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar);
if(e.Handled)
{
return;
}
HintTextBox box = (HintTextBox)sender;
if (!box.IsHintDisplayed && e.KeyChar != (char)Keys.Back && e.KeyChar != (char)Keys.Delete)
{
if (box.Text.Length + 1 == box.MaxLength)
{
this.SelectNextControl(box, true, true, true, false);
}
}
}
/* ------------------------------ Constructors ------------------------------*/
public DatePicker()
{
InitializeComponent();
this.day.KeyPress += HintTextBox_KeyPress;
this.month.KeyPress += HintTextBox_KeyPress;
this.year.KeyPress += HintTextBox_KeyPress;
}
/* ------------------------------ Public Methods ------------------------------*/
public System.DateTime GetDate()
{
try
{
return new System.DateTime(this.Year, this.Month, this.Day);
}
catch(System.Exception)
{
return new System.DateTime();
}
}
public void SetDate(System.DateTime date)
{
this.day.SetText(date.Day.ToString());
this.month.SetText(date.Month.ToString());
this.year.SetText(date.Year.ToString());
}
}
}
namespace Scheduler.Controls
{
public class HintTextBox : System.Windows.Forms.TextBox
{
private enum TextBoxStyle { Normal, Hint }
/* ------------------------------ Private Variables ------------------------------ */
private string hint;
public string Hint
{
get
{
return hint;
}
set
{
hint = value;
if(this.Text.Length == 0)
{
IsHintDisplayed = true;
SetStyle(TextBoxStyle.Hint);
this.Text = value;
}
}
}
/* ------------------------------ Public Variables ------------------------------ */
public bool IsHintDisplayed { get; private set; } = false;
/* ------------------------------ Private Methods ------------------------------ */
private void SetStyle(TextBoxStyle style)
{
switch (style)
{
case TextBoxStyle.Normal:
this.ForeColor = System.Drawing.Color.Black;
break;
case TextBoxStyle.Hint:
this.ForeColor = System.Drawing.Color.DarkGray;
break;
}
}
private void HintTextBox_Enter(object sender, System.EventArgs e)
{
if(this.IsHintDisplayed)
{
this.Text = "";
this.IsHintDisplayed = false;
SetStyle(TextBoxStyle.Normal);
}
}
private void HintTextBox_Leave(object sender, System.EventArgs e)
{
if(this.Text.Length == 0 && this.Hint.Length > 0)
{
this.IsHintDisplayed = true;
SetStyle(TextBoxStyle.Hint);
this.Text = Hint;
}
}
/* ------------------------------ Constructors ------------------------------ */
public HintTextBox()
{
this.Enter += HintTextBox_Enter;
this.Leave += HintTextBox_Leave;
}
/* ------------------------------ Public Methods ------------------------------ */
public void SetText(string text)
{
IsHintDisplayed = false;
SetStyle(TextBoxStyle.Normal);
this.Text = text;
}
}
}
using System;
using System.Collections.Generic;
using static System.Console;
[Serializable]
public class Day
{
public DateTime date { get; set; }