Задание на курсовое проектирование.
Одна запись в списке запланированных дел представляет собой структуру DailyItem, которая содержит время начала и окончания работы, описание и признак выполнения. Реализовать класс DailySchedule – план работ на день. Реализовать методы добавления, удаления и изменения планируемой работы. При добавлении проверять корректность временных рамок (они не должны пересекаться с уже запланированными мероприятиями). Реализовать метод поиска свободного промежутка времени. Условие поиска задаёт размер искомого интервала, а также временные рамки, в которые он должен попадать. Метод поиска возвращает структуру DailyItem с пустым описанием вида работ. Реализовать операцию генерации объекта Redo (ещё раз), содержащего список дел, не выполненных в течение дня, из объекта типа DailySchedule. Реализовать операцию объединения двух объектов типа DailySchedule (в объединённом объекте не должно быть одинаковых работ, выполняемых в разное время, а также разных работ, выполняемых в одно время).
Описание разрабатываемой программной системы с точки зрения пользователя.
С точки зрения пользователя программа представляет собой однооконное приложение с несколькими диалоговыми формами. После запуска программы пользователя встречает основное окно приложения, где проводятся все операции по планированию своей деятельности.
Рисунок 1 Пользовательский интерфейс
Основные возможности, которые предоставляет приложение пользователю:
- добавление, удаление, обновление запланированных дел на выбранный день
- перенос данных расписания одного дня в расписание другого
- отображение списка незавершенных дел на выбранный день
- контроль вводимой информации на наличие дубликатов
- контроль вводимой информации на соответствие временным рамкам суток
Перечисленные возможности функционально предоставляет группа кнопок в левой части интерфейса приложения. Вправой части интерфейса располагаются поля отвечающие за данные запланированных дел.
Выбор запланированной работы осуществляется в два этапа:
- выбор необходимого дня
- выбор работы из списка
Описание разрабатываемой программной системы с точки зрения программиста.
Составные части приложения:
- исполняемый модуль Notebook.exe, с помощью которого осуществляется запуск приложения
- библиотеки Lirbrary.dll, которая содержит в себе все разработанные классы для работы приложения
Рисунок 2Обобщенная схема приложения
Notebook.exe содержит:
- форма Menu.cs: основная форма приложения
- форма UnioDailyItem.cs: форма для копирования расписания из другого дня
- форма NotFinishedWork.cs: форма для отображения незавершенных дел
Library.dll содержит:
- класс DailyItem: описывает единицу работы – запланированное дело
- класс DailySchedule: описывает расписание состоящее из запланированных работ
- перечисление FormMode: содержит режимы работы формы
- делегат SendSelectedDate: используется для передачи даты из формы UnioDailyItem в форму Menu
Объектное представление системы – диаграмма классов.
События.
Обработчики стандартных событий формы Menu.cs:
private void dateTimePicker_CurrentDay_ValueChanged(object sender, EventArgs e)
private void button_CreateDailyItem_Click(object sender, EventArgs e)
private void button_DeleteDailyItem_Click(object sender, EventArgs e)
private void button_UnionDailyItem_Click(object sender, EventArgs e)
private void button_ViewIsNotFinished_Click(object sender, EventArgs e)
private void button_Cancel_Click(object sender, EventArgs e)
private void button_Edit_Click(object sender, EventArgs e)
private void button_Save_Click(object sender, EventArgs e)
Событие определенные разработчиком:
public event SendSelectedDate SelectedDate;
public delegate void SendSelectedDate(DateTime? Date);
Генерация события
private void button_OK_Click(object sender, EventArgs e)
{
DateTime Date = monthCalendar.SelectionStart;
if (SelectedDate!=null)
SelectedDate(Date);
Close();
}
Подписка на событие
private void UnionDailyWork()
{
UnionDailyItem Form = new UnionDailyItem();
Form.SelectedDate += UnionDailyItem;
Form.ShowDialog();
}
Содержимое метода UnionDailyItem можно просмотреть в листинге программы
Текст программы.
Menu.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Library;
namespace Notebook
{
public partial class Menu: Form
{
public Menu()
{
InitializeComponent();
UpdateBindings_DailyItem(DateTime.Now);
SetFormMode(FormMode.List);
}
#region Свойства
List<DailySchedule> m_Schedule = new List<DailySchedule>();
DailySchedule m_CurrentDailySchedule = null;
int m_BindingPosition = -1;
FormMode m_FormMode=FormMode.List;
#endregion Свойства
#region Обработчики
private void dateTimePicker_CurrentDay_ValueChanged(object sender, EventArgs e)
{
UpdateBindings_DailyItem(dateTimePicker_CurrentDay.Value);
}
private void button_CreateDailyItem_Click(object sender, EventArgs e)
{
CreateDailyItem();
}
private void button_DeleteDailyItem_Click(object sender, EventArgs e)
{
DelleteDailyItem();
}
private void button_UnionDailyItem_Click(object sender, EventArgs e)
{
UnionDailyWork();
}
private void button_ViewIsNotFinished_Click(object sender, EventArgs e)
{
ViewDailyItems_IsNotFinished();
}
private void button_Cancel_Click(object sender, EventArgs e)
{
CancelDailyItem();
}
private void button_Edit_Click(object sender, EventArgs e)
{
EditDailyItem();
}
private void button_Save_Click(object sender, EventArgs e)
{
SaveDailyItem();
}
#endregion Обработчики
#region Методы
private void UpdateBindings_DailyItem(DateTime Date)
{
m_CurrentDailySchedule = null;
foreach (DailySchedule CurrentDailySchedule in m_Schedule)
{
if (CurrentDailySchedule.Date.Date == Date.Date && m_CurrentDailySchedule == null)
{
m_CurrentDailySchedule = CurrentDailySchedule;
}
}
if (m_CurrentDailySchedule == null)
{
m_CurrentDailySchedule = new DailySchedule(Date);
m_Schedule.Add(m_CurrentDailySchedule);
}
if (m_CurrentDailySchedule.ListDailyItem == null)
{
m_CurrentDailySchedule.ListDailyItem = new List<DailyItem>();
}
bindingSource_DailyItem.DataSource = m_CurrentDailySchedule.ListDailyItem;
}
private void SetEnable_MainPanel(bool IsEnabled)
{
MainPanel.Panel1.Enabled
= textBox_Name.ReadOnly
= textBox_Description.ReadOnly
= IsEnabled;
dateTimeBegin.Enabled
= dateTimeEnd.Enabled
= checkBox_IsFifnished.Enabled
=!IsEnabled;
}
private void SetVisible_Button(bool Cancel, bool Edit, bool Save)
{
button_Cancel.Visible = Cancel;
button_Edit.Visible = Edit && m_CurrentDailySchedule.ListDailyItem.Any();
button_Save.Visible = Save;
}
private void SetFormMode(FormMode Mode)
{
switch (Mode)
{
case FormMode.Edit:
if (m_FormMode == FormMode.List)
SetFormMode_Edit();
break;
case FormMode.Insert:
if (m_FormMode == FormMode.List)
SetFormMode_Insert();
break;
case FormMode.List:
//if (m_FormMode == FormMode.Edit || m_FormMode == FormMode.Insert)
SetFormMode_List();
break;
}
}
private void SetFormMode_Edit()
{
SetEnable_MainPanel(false);
SetVisible_Button(true,false,true);
m_FormMode = FormMode.Edit;
DailyItem Item= ControlsToDailyItem();
m_BindingPosition = bindingSource_DailyItem.Position;
bindingSource_DailyItem.SuspendBinding();
DailyItemToControls(Item);
}
private void SetFormMode_Insert()
{
SetEnable_MainPanel(false);
SetVisible_Button(true, false, true);
m_FormMode = FormMode.Insert;
m_BindingPosition = -1;
bindingSource_DailyItem.SuspendBinding();
}
private void SetFormMode_List()
{
DailyItem Item = ControlsToDailyItem();
if (m_FormMode == FormMode.Edit)
{
//bindingSource_DailyItem.ResumeBinding();
//bindingSource_DailyItem.Position = m_BindingPosition;
//DailyItemToControls(Item);
//bindingSource_DailyItem.EndEdit();
m_CurrentDailySchedule.ListDailyItem[m_BindingPosition] = Item;
bindingSource_DailyItem.ResumeBinding();
bindingSource_DailyItem.Position = m_BindingPosition;
}
if (m_FormMode == FormMode.Insert)
{
m_CurrentDailySchedule.AddDailyItem(Item);
bindingSource_DailyItem.ResumeBinding();
bindingSource_DailyItem.MoveLast();
}
SetEnable_MainPanel(true);
SetVisible_Button(false, true, false);
m_FormMode = FormMode.List;
}
private void CreateDailyItem()
{
DailyItem Item = m_CurrentDailySchedule.GetFirstFreeSlot();
if (Item!= null)
{
SetFormMode(FormMode.Insert);
DailyItemToControls(Item);
}
else
{
MessageBox.Show("Нет свободного времени для планирования");
}
}
private void EditDailyItem()
{
//SetModeEdit(false);
SetFormMode(FormMode.Edit);
}
private void DelleteDailyItem()
{
if (bindingSource_DailyItem.Current!=null)
bindingSource_DailyItem.RemoveCurrent();
SetVisible_Button(false, true, false);
}
private void SaveDailyItem()
{
string Error = String.Empty;
DailyItem Item = ControlsToDailyItem();
switch (m_FormMode)
{
case FormMode.Edit:
if (m_CurrentDailySchedule.CheckDailyItem(Item,m_BindingPosition, out Error))
{
SetFormMode(FormMode.List);
}
else
{
MessageBox.Show(Error);
}
break;
case FormMode.Insert:
if (m_CurrentDailySchedule.CheckDailyItem(Item, out Error))
{
SetFormMode(FormMode.List);
}
else
{
MessageBox.Show(Error);
}
break;
}
}
private void CancelDailyItem()
{
bindingSource_DailyItem.ResumeBinding();
bindingSource_DailyItem.MoveFirst();
SetEnable_MainPanel(true);
SetVisible_Button(false, true, false);
m_FormMode = FormMode.List;
}
private void UnionDailyWork()
{
UnionDailyItem Form = new UnionDailyItem();
Form.SelectedDate += UnionDailyItem;
Form.ShowDialog();
}
private void UnionDailyItem(DateTime? Date)
{
if (Date.HasValue)
{
DailySchedule Schedule = null;
foreach (DailySchedule CurrentDailySchedule in m_Schedule)
{
if (CurrentDailySchedule.Date.Date == Date.Value.Date && Schedule == null)
{
Schedule = CurrentDailySchedule;
}
}
if (Schedule!= null && Schedule.ListDailyItem!=null && Schedule.ListDailyItem.Any())
{
String Error= String.Empty;
bindingSource_DailyItem.SuspendBinding();
foreach (DailyItem Item in Schedule.ListDailyItem)
{
if (m_CurrentDailySchedule.CheckDailyItem(Item,out Error))
m_CurrentDailySchedule.AddDailyItem(Item);
}
bindingSource_DailyItem.ResumeBinding();
}
else
{
MessageBox.Show("На данный день расписания не было обнаружено");
}
if (Schedule == null)
{
m_CurrentDailySchedule = new DailySchedule(Date.Value);
m_Schedule.Add(m_CurrentDailySchedule);
}
if (m_CurrentDailySchedule.ListDailyItem == null)
{
m_CurrentDailySchedule.ListDailyItem = new List<DailyItem>();
}
}
}
private void ViewDailyItems_IsNotFinished()
{
NotFinishedWork FormNotFinished = new NotFinishedWork()
{
DataSourceForm = m_CurrentDailySchedule.Redo
};
FormNotFinished.ShowDialog();
}
private void DailyItemToControls(DailyItem Item)
{
dateTimeBegin.Value=Item.TimeBegin;
dateTimeEnd.Value=Item.TimeEnd;
textBox_Name.Text=Item.Name;
textBox_Description.Text=Item.Description;
checkBox_IsFifnished.Checked=Item.IsFinished;
}
private DailyItem ControlsToDailyItem()
{
DailyItem Item = new DailyItem()
{
TimeBegin = dateTimeBegin.Value,
TimeEnd = dateTimeEnd.Value,
Name = textBox_Name.Text,
Description = textBox_Description.Text,
IsFinished = checkBox_IsFifnished.Checked
};
return Item;
}
#endregion Методы
}
}
NotFinishedWork.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Library;
namespace Notebook
{
public partial class NotFinishedWork: Form
{
public NotFinishedWork()
{
InitializeComponent();
}
List<DailyItem> m_DataSourceForm=new List<DailyItem>();
public List<DailyItem> DataSourceForm
{
get { return m_DataSourceForm; }
set { m_DataSourceForm = value; }
}
private void NotFinishedWork_Load(object sender, EventArgs e)
{
bindingSource_NotFinished.DataSource = m_DataSourceForm;
}
private void button_Exit_Click(object sender, EventArgs e)
{
Close();
}
}
}
UnionDailyItem.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Library;
namespace Notebook
{
public partial class UnionDailyItem: Form
{
public UnionDailyItem()
{
InitializeComponent();
}
private void button_Cancel_Click(object sender, EventArgs e)
{
if (SelectedDate!= null)
SelectedDate(null);
Close();
}
private void button_OK_Click(object sender, EventArgs e)
{
DateTime Date = monthCalendar.SelectionStart;
if (SelectedDate!=null)
SelectedDate(Date);
Close();
}
public event SendSelectedDate SelectedDate;
}
}
DailyItem.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Library
{
/// <summary>
/// Класс описывающий запланированное дело
/// </summary>
public class DailyItem:IEquatable<DailyItem>
{
public DailyItem() { }
public DailyItem(DateTime timeBegin, DateTime timeEnd, string description, bool isFinished)
{
m_TimeBegin = timeBegin;
m_TimeEnd = timeEnd;
m_Description = description;
m_IsFinished = isFinished;
}
DateTime m_TimeBegin = DateTime.MinValue;
/// <summary>
/// Время начала работы
/// </summary>
public DateTime TimeBegin
{
get { return m_TimeBegin; }
set { m_TimeBegin = value; }
}
DateTime m_TimeEnd = DateTime.MinValue;
/// <summary>
/// Время окончания работы
/// </summary>
public DateTime TimeEnd
{
get { return m_TimeEnd; }
set { m_TimeEnd = value; }
}
string m_Description = String.Empty;
/// <summary>
/// Описание работы
/// </summary>
public string Description
{
get { return m_Description; }
set { m_Description = value; }
}
bool m_IsFinished = false;
/// <summary>
/// Признак выполнения работы
/// </summary>
public bool IsFinished
{
get { return m_IsFinished; }
set { m_IsFinished = value; }
}
string m_Name = String.Empty;
/// <summary>
/// Краткое наименование запланированной работы
/// </summary>
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
public bool Equals(DailyItem Other)
{
return (this.Name == Other.Name
&& this.Description == Other.Description
&& this.TimeBegin.TimeOfDay == Other.TimeBegin.TimeOfDay
&& this.TimeEnd.TimeOfDay == Other.TimeEnd.TimeOfDay);
}
}
}
DailySchedule.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Library
{
public class DailySchedule
{
#region Конструкторы
public DailySchedule()
{
RefreshFreeTime();
}
public DailySchedule(DateTime date, List<DailyItem> listDailyItem)
{
m_Date = date;
m_ListDailyItem = listDailyItem;
RefreshFreeTime();
}
public DailySchedule(DateTime date)
{
m_Date = date;
RefreshFreeTime();
}
#endregion Конструкторы
#region Свойства
DateTime m_Date = DateTime.MinValue;
public DateTime Date
{
get { return m_Date; }
set { m_Date = value; }
}
List<DailyItem> m_ListDailyItem = new List<DailyItem>();
public List<DailyItem> ListDailyItem
{
get { return m_ListDailyItem; }
set { m_ListDailyItem = value; }
}
public List<DailyItem> Redo
{
get { return m_ListDailyItem.Where(x => x.IsFinished == false).ToList(); }
}
List<DailyItem> m_FreeSlot = new List<DailyItem>();
#endregion Свойства
#region Методы
public bool CheckDailyItem(DailyItem Item, out string Error)
{
bool Result = false;
StringBuilder SB = new StringBuilder();
if (Item!= null)
{
foreach (DailyItem CurrentItem in m_ListDailyItem)
{
if (CurrentItem.TimeBegin.TimeOfDay < Item.TimeBegin.TimeOfDay
&& Item.TimeBegin.TimeOfDay < CurrentItem.TimeEnd.TimeOfDay)
{
SB.Append(String.Format("Начало работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (CurrentItem.TimeBegin.TimeOfDay < Item.TimeEnd.TimeOfDay
&& Item.TimeEnd.TimeOfDay < CurrentItem.TimeEnd.TimeOfDay)
{
SB.Append(String.Format("Окончание работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (Item.TimeBegin.TimeOfDay < CurrentItem.TimeBegin.TimeOfDay
&& CurrentItem.TimeBegin.TimeOfDay < Item.TimeEnd.TimeOfDay)
{
SB.Append(String.Format("Начало работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (Item.TimeBegin.TimeOfDay < CurrentItem.TimeEnd.TimeOfDay
&& CurrentItem.TimeEnd.TimeOfDay < Item.TimeEnd.TimeOfDay)
{
SB.Append(String.Format("Окончание работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (CurrentItem.Name == Item.Name && CurrentItem.Description == Item.Description)
{
SB.Append(String.Format("Работа с таким же именем и описанием уже существует\r\n"));
}
}
}
Error = SB.ToString();
if (String.IsNullOrEmpty(Error))
{
Result = true;
}
return Result;
}
public bool CheckDailyItem(DailyItem Item, int Position, out string Error)
{
bool Result = false;
List<DailyItem> CopyListDailyItem = m_ListDailyItem.ToList();
StringBuilder SB = new StringBuilder();
if (Item!= null)
{
CopyListDailyItem.RemoveAt(Position);
foreach (DailyItem CurrentItem in CopyListDailyItem)
{
if (CurrentItem.TimeBegin < Item.TimeBegin
&& Item.TimeBegin < CurrentItem.TimeEnd)
{
SB.Append(String.Format("Начало работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (CurrentItem.TimeBegin < Item.TimeEnd
&& Item.TimeEnd < CurrentItem.TimeEnd)
{
SB.Append(String.Format("Окончание работы пересекается с {0}\r\n", CurrentItem.Name));
}
if (CurrentItem.Name == Item.Name && CurrentItem.Description == Item.Description)
{
SB.Append(String.Format("Работа с таким же именем и описанием уже существует\r\n"));
}
}
}
Error = SB.ToString();
if (String.IsNullOrEmpty(Error))
{
Result = true;
}
return Result;
}
public void AddDailyItem(DailyItem Item)
{
string Error = String.Empty;
if (Item!= null)
m_ListDailyItem.Add(Item);
}
public void DellDailyItem(DailyItem Item)
{
if (Item!= null)
m_ListDailyItem.Remove(Item);
}
private void RefreshFreeTime()
{
m_FreeSlot = new List<DailyItem>();
List<DailyItem> SortedListDailyItem = m_ListDailyItem.OrderBy(x => x.TimeBegin).ToList();
DateTime OldTimeBegin = Date.Date;
DateTime OldTimeEnd = Date.Date;
foreach (DailyItem CurrentTime in SortedListDailyItem)
{
DailyItem FreeItem = new DailyItem()
{
TimeBegin = OldTimeEnd,
TimeEnd = CurrentTime.TimeBegin,
Description = String.Empty,
Name = String.Empty,
IsFinished = false
};
if (CheckFreeItem(FreeItem.TimeBegin, FreeItem.TimeEnd))
m_FreeSlot.Add(FreeItem);
OldTimeBegin = CurrentTime.TimeBegin;
OldTimeEnd = CurrentTime.TimeEnd;
}
DailyItem LastFreeItem = new DailyItem()
{
TimeBegin = OldTimeEnd,
TimeEnd = Date.Date.AddTicks(new TimeSpan(23, 59, 59).Ticks),
Description = String.Empty,
Name = String.Empty,
IsFinished = false
};
if (CheckFreeItem(LastFreeItem.TimeBegin, LastFreeItem.TimeEnd))
m_FreeSlot.Add(LastFreeItem);
}
private bool CheckFreeItem(DateTime TimeBegin, DateTime TimeEnd)
{
bool Output = false;
TimeSpan Diff = TimeEnd.TimeOfDay - TimeBegin.TimeOfDay;
if (Diff.Ticks >= TimeSpan.TicksPerMinute)
Output = true;
return Output;
}
public DailyItem GetFirstFreeSlot()
{
RefreshFreeTime();
return m_FreeSlot.FirstOrDefault();
}
public List<DailyItem> GetListFreeSlot()
{
RefreshFreeTime();
return m_FreeSlot;
}
#endregion Методы
}
}
FormMode.cs
using System;
namespace Library
{
public enum FormMode
{
Insert,
Edit,
List
}
public delegate void SendSelectedDate(DateTime? Date);
}
Тестирование программы.
1) Планирование, удаление, редактирование работы
Рисунок 3Введение данных для задачи
Рисунок 4 Сохранение задачи
Рисунок 5 Редактирование записи
Рисунок 6 Результат редактирования записи
Рисунок 7Удаленеие записи "Тест"
2) Отображение списка невыполненных задач
Рисунок 8 Список невыполненных задач
3) Перенос задач на другой день
Рисунок 9 Выбор расписания другого дня
Рисунок 10 Выбор расписания которое необходимо перенести
Рисунок 11 Результат переноса
Выводы
В результате выполнения курсового проекта я закрепил практические навыки:
· по разработке программ по принципу поэтапной разработки и отладки программ средней сложности
· по проектированию и разработке собственных классов
· по умению применять необходимые классы библиотеки NET Framework, создавать из них требуемые объекты и употреблять их в программе.
· по умению разрабатывать собственный интерфейс программы.
· по умению создавать необходимые события, делегаты и потоки и применять их для эффективного параллельного функционирования объектов и их взаимодействия.
· по умению описывать разработанный программный продукт как с точки зрения его пользователя, отражая его внешнюю сторону, так и с точки зрения программиста, отражая особенности его реализации.
Список используемой литературы.
1) Плохотников К.Э. Методы разработки курсовых работ. Моделирование, вычисления, программирование на С/С++ и МАТLAB, виртуализация, образцы лучших студенческих курсовых работ: учебное пособие. – М.: СОЛОН-ПРЕСС, 2006.
2) Программирование на алгоритмических языках. Лабораторный практикум /Артемьев И.Т./, ЧГУ: Чебоксары, 2005.
3) Пышкин, Е. В. Основные концепции и механизмы объектно-ориентированного программирования. Теория и технология программирования [текст]: учебное пособие / Е. В. Пышкин. - СПб: БХВ-Петербург, 2005.
4) Рихтер, Д. Windows Visual C/C++. Программирование на языке Visual C++ [текст]: пер. с англ. / Д. Рихтер, К. Назар. - М.: Русская Редакция; СПб.: Питер, 2008. - 878с.
5) Юрагов, Е. А. Объектное моделирование и программирование информационных систем [текст]: учеб. пособие / Е. А. Юрагов. - М.: Изд-во МГОУ, 2011. - 258 с.