Создается C#-приложение, которое генерирует диаграмму прихода пассажиров на остановку трамвая, например, на остановку Авиамоторная.
На практике такая диаграмма создается в результате сбора статистических данных о прибытии пассажиров на остановку в разные промежутки времени. Для каждого временного интервала на диаграмме указывается математическое ожидание числа пассажиров, приходящих на остановку.
Такие диаграммы создаются для каждой остановки маршрута.
В программе диаграмма генерируется автоматически по следующим данным:
Определение числа приходящих пассажиров (pasCome) для каждого временного интервала следующий:
Если интервал входит в часы пик, то
pasCome = случайное число из "диапазона пик";
иначе
pasCome = случайное число из "диапазона прочий";
Это число определяется для каждого интервала диаграммы и заносится в массив arrPasCome; начало временного интервала записывается в массив arrTimeInt.
Эти массивы используются для построения диаграммы и определения числа пассажиров, приходящих в заданный временной промежуток.
В частности, таким промежутком может быть интервал между прибытием на остановку трамваев j и j + 1. В этом случае вычисленное число – это количество пассажиров, которые хотели бы сесть в трамвай j + 1.
Они сядут в этот трамвай, если позволит его вместимость.
Форма, обеспечивающая задание входных данных, выбор типа диаграммы и отображение результата, показана на рис. 1.
Рис. 1. Диаграмма прихода пассажиров на остановку трамвая
Доступные типы диаграмм:
Тип проекта - Windows Form Application.
При нажатии на кнопку Генерировать создаются диаграммы для каждой остановки, сохраняемые в файлах stop*.txt.
Число файлов равно числу остановок.
Замечание. Аналогичным образом формируется и диаграмма выхода пассажиров на остановке из транспортного средства.
using System;
using System.IO; // StreamWriter
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplicationChart
{
public partial class FormDiag : Form
{
const string fileParams = "params.txt"; // Пишем в файл интервал, число интервалов диаграммы прихода и диапазоны часов пик
const string fileStop = "stop"; // Файлы диаграмм остановок (stop*)
const int tStart = 5 * 3600 + 20 * 60; // Время начала движения первого трамвая, с
const int tEnd = 25 * 3600 + 20 * 60; // Время начала движения последнего трамвая, с
const int tGoLast = 1 * 3600 + 40 * 60; // Время в пути (задается для последнего трамвая), с
int nStops = 24; // Число остановок
int nPas = 13000; // Число перевозимых пассажиров
// Начало и конец утреннего и вечернего интервалов часов пик (в мин при показе и в секундах при генерации)
int morn, morn2, ev, ev2;
// Диапазоны пассажиров, приходящих в часы пик и прочие часы
int pasPeak, pasPeak2, pasOth, pasOth2;
int[][] arrDiags; // Массив диаграмм прихода пасссажиров на остановки
private Random rnd = new Random();
StreamWriter sW;
public FormDiag()
{
InitializeComponent();
// Параметры диаграммы
chartIn.ChartAreas[0].AxisX.Title = "Временной интервал, мин";
chartIn.ChartAreas[0].AxisY.Title = "Число пассажиров";
// Шрифт для координатных осей диаграммы
Font fnt = new System.Drawing.Font("Microsoft Sans Serif", 10.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
chartIn.ChartAreas[0].AxisX.TitleFont = fnt;
chartIn.ChartAreas[0].AxisY.TitleFont = fnt;
chartIn.ChartAreas[0].BackColor = Color.WhiteSmoke; // Фон диаграммы
chartIn.Series[0].LegendText = "Пассажиры";
chartIn.Series[0].IsVisibleInLegend = false;
chartIn.Series[0].Color = Color.Red; // Цвет диаграммы
chartIn.Series[0].BorderWidth = 2; // Ширина линий диаграммы
numericUpDownPasPeak.Value = 20;
numericUpDownPasPeak2.Value = 25;
numericUpDownPasOth.Value = 3;
numericUpDownPasOth2.Value = 7;
numericUpDownNPas.Value = nPas;
numericUpDownNPas.Value = nStops;
arrDiags = new int[nStops][]; // Массив диаграмм прихода пасссажиров на остановки
ShowDiag(); // Показываем диаграмму
}
private void buttonClose_Click(object sender, EventArgs e)
{
this.Close();
}
// Показывает диаграмму
private void readParams(int coef) // 60 или 3600
{
// Начало и конец утреннего интервала часов пик (единица измерения зависиит от coef)
morn = (int)numericUpDownMorn.Value * coef;
morn2 = (int)numericUpDownMorn2.Value * coef;
if (morn2 <= morn) morn2 = morn + 3600; // Проверка
// Начало и конец вечернего интервала часов пик (единица измерения зависиит от coef)
ev = (int)numericUpDownEv.Value * coef;
ev2 = (int)numericUpDownEv2.Value * coef;
if (ev2 <= ev) ev2 = ev + 3600; // Проверка
// Диапазон пассажиров, приходящих в часы пик
pasPeak = (int)numericUpDownPasPeak.Value;
pasPeak2 = (int)numericUpDownPasPeak2.Value;
if (pasPeak2 <= pasPeak) pasPeak2 = pasPeak + 1; // Проверка
// Диапазон пассажиров, приходящих в прочие часы
pasOth = (int)numericUpDownPasOth.Value;
pasOth2 = (int)numericUpDownPasOth2.Value;
if (pasOth2 <= pasOth) pasOth2 = pasOth + 1; // Проверка
}
// Показывает диаграмму
private void ShowDiag()
{
// Очищаем диаграмму (серию 0)
chartIn.Series[0].Points.Clear();
// Тип диаграммы
if (radioButtonStepLine.Checked)
// Столбцы
chartIn.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.StepLine;
else
// Столбцы
chartIn.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column;
// Начало и конец движения (в мин)
int moveStart = (int)numericUpDownMove.Value * 60;
int moveEnd = (int)numericUpDownMove2.Value * 60;
int intLen = (int)numericUpDownInt.Value; // Длина интервала диаграммы прихода, с
int N = (moveEnd - moveStart) / intLen + 1; // Число интервалов
readParams(60);
// Массив приходящих пассажиров
int[] arrPasCome = new int[N];
// Массив временных интервалов диаграммы
int[] arrTimeInt = new int[N];
int t = moveStart, pasCome;
for (int k = 0; k < N; k++)
{
if (checkBoxWeekEnd.Checked)
{
if (t >= morn && t <= morn2 || t >= ev && t <= ev2)
pasCome = rnd.Next(pasPeak, pasPeak2);
else if (t > morn2 && t < ev)
pasCome = (pasOth2 + pasPeak2) / 2;
else
pasCome = rnd.Next(pasOth, pasOth2);
}
else
{
// Время может быть в одном из трех интервалов: утреннем, вечернем и прочем
if (t >= morn && t <= morn2 || t >= ev && t <= ev2)
// Пассажиры, пришедшие в часы пик
pasCome = rnd.Next(pasPeak, pasPeak2);
else
// Пассажиры, пришедшие в прочие часы
pasCome = rnd.Next(pasOth, pasOth2);
}
arrPasCome[k] = pasCome;
arrTimeInt[k] = t;
t += intLen; // Время текущего интервала
}
for (int k = 0; k < N; k++) chartIn.Series[0].Points.AddXY(arrTimeInt[k], arrPasCome[k]);
// Корректировка после проверки
numericUpDownMorn2.Value = Convert.ToDecimal(morn2 / 60);
numericUpDownEv2.Value = Convert.ToDecimal(ev2 / 60);
numericUpDownPasPeak2.Value = Convert.ToDecimal(pasPeak2);
numericUpDownPasOth2.Value = Convert.ToDecimal(pasOth2);
}
private void buttonShow_Click(object sender, EventArgs e)
{
ShowDiag(); // Показываем диаграмму
}
private void radioButtonDiagType_CheckedChanged(object sender, EventArgs e)
{
ShowDiag(); // Показываем диаграмму
}
private void checkBoxLegend_CheckedChanged(object sender, EventArgs e)
{
chartIn.Series[0].IsVisibleInLegend = checkBoxLegend.Checked;
ShowDiag(); // Показываем диаграмму
}
private void numericUpDown_ValueChanged(object sender, EventArgs e)
{
nStops = (int)numericUpDownNPas.Value;
arrDiags = new int[nStops][]; // Массив диаграмм прихода пасссажиров на остановки
ShowDiag(); // Показываем диаграмму
}
private void buttonGen_Click(object sender, EventArgs e)
{
GenDiags(); // Генерируем диаграммы и сохраняем их в файлы
MessageBox.Show("Готово");
}
private void GenDiags()
{
int intLen = (int)numericUpDownInt.Value * 60; // Длина интервала диаграммы прихода, с
int N = (tEnd + tGoLast - tStart) / intLen + 1; // Число интервалов
int t, pasCome, nPas2 = 0; // Текущее время, число пассажиров, приходящих на остановку и общее число пассажиров
int[] arrDiag;
string fileSt;
nPas = (int)numericUpDownNPas.Value;
readParams(3600);
sW = new StreamWriter(fileParams);
sW.WriteLine(intLen); // Итервал диаграммы прихода
sW.WriteLine(N); // Число интервалов
// Начало и конец утреннего и вечернего интервалов часов пик, c
sW.WriteLine(morn);
sW.WriteLine(morn2);
sW.WriteLine(ev);
sW.WriteLine(ev2);
sW.Close();
for (int k = 0; k < nStops; k++)
{
arrDiag = new int[N];
t = tStart;
for (int k2 = 0; k2 < N; k2++)
{
if (checkBoxWeekEnd.Checked)
{
if (t >= morn && t <= morn2 || t >= ev && t <= ev2)
pasCome = rnd.Next(pasPeak, pasPeak2);
else if (t > morn2 && t < ev)
pasCome = (pasOth2 + pasPeak2) / 2;
else
pasCome = rnd.Next(pasOth, pasOth2);
}
else
{
if (t >= morn && t <= morn2 || t >= ev && t <= ev2)
// Пассажиры, пришедшие в часы пик
pasCome = rnd.Next(pasPeak, pasPeak2);
else
// Пассажиры, пришедшие в прочие часы
pasCome = rnd.Next(pasOth, pasOth2);
}
arrDiag[k2] = pasCome;
nPas2 += pasCome;
t += intLen; // Время текущего интервала
}
arrDiags[k] = arrDiag;
}
//MessageBox.Show("" + nPas2);
int d = (nPas2 < nPas ? 1 : -1);
while (nPas2 != nPas)
{
for (int k = 0; k < nStops; k++)
{
arrDiag = arrDiags[k];
for (int k2 = 0; k2 < N; k2++)
{
if (arrDiag[k2] > 3)
{
arrDiag[k2] += d;
nPas2 += d;
if (nPas2 == nPas)
{
arrDiags[k] = arrDiag;
break;
}
}
}
arrDiags[k] = arrDiag;
if (nPas2 == nPas) break;
}
}
// Пишем диаграммы в файлы
for (int k = 0; k < nStops; k++)
{
fileSt = fileStop + k + ".txt";
sW = new StreamWriter(fileSt);
arrDiag = arrDiags[k];
for (int k2 = 0; k2 < N; k2++)
{
sW.WriteLine(arrDiag[k2]);
}
Console.WriteLine("Сооздан файл " + fileSt);
sW.Close();
}
}
private void checkBoxWeekEnd_CheckedChanged(object sender, EventArgs e)
{
if(checkBoxWeekEnd.Checked)
{
numericUpDownPasPeak.Value = 30;
numericUpDownPasPeak2.Value = 31;
numericUpDownPasOth.Value = 10;
numericUpDownPasOth2.Value = 11;
numericUpDownMorn.Value = 8;
numericUpDownMorn2.Value = numericUpDownMorn2.Maximum;
numericUpDownEv.Value = 17;
numericUpDownEv2.Value = numericUpDownEv2.Maximum;
}
else
{
numericUpDownPasPeak.Value = 20;
numericUpDownPasPeak2.Value = 25;
numericUpDownPasOth.Value = 5;
numericUpDownPasOth2.Value = 15;
numericUpDownMorn2.Value = 9;
numericUpDownEv.Value = 17;
numericUpDownEv.Value = 19;
}
ShowDiag();
}
}
}