Объектное представление системы – диаграмма классов.




Задание на курсовое проектирование.

Одна запись в списке запланированных дел представляет собой структуру 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 с.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-08-08 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: