В основном манипуляции производились с данными, хранимыми в Excell, таблицы которого сформированы по 3НФ, поэтому в некоторых местах кода вместо индексов используются данные из ячеек. Итак согласно алгоритму необходимо получить коэффициент клуба и климатическую характеристику города, в котором этот клуб принимает соперников = команда: {климат, рейтинг} — это и есть основная цель. Поехали.
1 этап:
Уполномоченный человек или Система случайным образом выбирают число N в рамках количества представителей команд участниц – от 1 до 16, упорядоченных согласно алфавиту. Выбранный участник приглашается для вычисления веса-рейтинга случайной команды.
TeamSequence = new List<int>(); for (int i = 0; i < teams.Length; i++) { int team_ambassor = generator.Next(1000, 1000000)%teams.Length; while (TeamSequence.Contains(team_ambassor)) team_ambassor = generator.Next(1000, 1000000)%teams.Length; TeamSequence.Add(team_ambassor); } foreach (int i in TeamSequence) textBox1.Text += "Приглашается прдставитель команды: " + teams[i] + "\r\n";
Для представителя уже сформированы данные по участникам соревнований, которые конечно же он не видит, также как и название команды, для которой производится расчет:
2 Этап
Т.к. у меня не было возможности пригласить кого-либо из экспертов, расстановку оценок по параметрам сделал случайной, а для того чтобы приблизить к реальности провел эту процедуру 8 раз ровно по количеству оцениваемых показателей.
double[,] rate = new double[16,8]; int team=new int(); DataTable table = new DataTable(); List<int> Marklist = new List<int>(); string strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text\"", "C:\\team.xlsx"); using (OleDbConnection dbConnection = new OleDbConnection(strConn)) { using (OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT * FROM [Лист3$]", dbConnection)) dbAdapter.Fill(table); for (int j = 0; j < 8; j++) { team = 0; foreach (DataRow dr in table.Rows) { for (int i = 9; i < 17; i++) { int mark = 1 + generator.Next(10000, 10000000)%8; while (Marklist.Contains(mark)) mark = 1 + generator.Next(10000, 10000000)%8; Marklist.Add(mark); rate[team, i - 9] += Convert.ToInt32(dr.ItemArray[i])*mark; } team++; Marklist.Clear(); } } dbConnection.Close(); }
Хранение данных в xlsx файлах достаточно удобное, т.к. некоторые тривиальные арифметические действия можно проводить сразу внутри таблиц с данными.
Выполнив случайную оценку показателей, были получены объективные характеристики участников соревнований.
Результаты получились вполне логичными.
Напомню, что оптимизация производится по минимальному критерию, т.е. меньше=лучше.
3 Этап
Остается к коэффициенту клуба, добавить климатическую характеристику города. Эти характеристики были получены для каждого месяца, в в рамках которых проводится турнир: июль-декабрь, март-май. Данные достаточно громоздкие и приводить их не вижу смысла.
Подсчитаем итоговые характеристики:
double[,] rate = new double[12,9]; int team=new int(); DataTable table = new DataTable(); List<int> Marklist = new List<int>(); string strConn = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;TypeGuessRows=0;ImportMixedTypes=Text\"", "C:\\team.xlsx"); using (OleDbConnection dbConnection = new OleDbConnection(strConn)) { //здесь данные о климате, 12 городов, 9 месяцев using (OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT * FROM [Лист5$]", dbConnection)) dbAdapter.Fill(table); team = 0; foreach (DataRow dr in table.Rows) { { rate[Convert.ToInt32(dr.ItemArray[0]) - 1, team%9] = Convert.ToDouble(dr.ItemArray[6]); team++; } } dbConnection.Close(); } table = new DataTable(); double[,] team_rate = new double[16,9]; team = 0; using (OleDbConnection dbConnection = new OleDbConnection(strConn)) { //здесь данные о командах = 16 шт. using (OleDbDataAdapter dbAdapter = new OleDbDataAdapter("SELECT * FROM [Лист6$]", dbConnection)) dbAdapter.Fill(table); foreach (DataRow dr in table.Rows) { for (int i = 0; i < 9; i++) { team_rate[team%16, i] = rate[Convert.ToInt32(dr.ItemArray[0]) - 1, i]* Convert.ToDouble(dr.ItemArray[1]); } team++; } dbConnection.Close(); } StreamWriter sw = new StreamWriter("teams_koeff.txt"); for (int i = 0; i <16; i++) { sw.WriteLine(Convert.ToString(teams[i])); for (int j = 0; j < 9; j++) { sw.Write(Convert.ToString(month[j]+"\t")); sw.Write(team_rate[i, j]+"\t"); } sw.WriteLine(); } sw.Close();
Готово. Немного преобразования и получится следующая таблица:
Как видно, у Кубани и Краснодара рейтинги разные, хотя они из одного города, аналогичная ситуация у московских клубов. На основе этой информации можно оптимизировать процедуру жеребьевки. Конечно же, разные форс-мажоры, игры в еврокубках, сборные, рекомендации полиции и т.п., необходимо будет учитывать вручную, но общий каркас сетки уже будет сформирован.
Для примера сравним опубликованный календарь и нашу таблицу:
Если не учитывать 2 московские пары, то примерно 50% «качетсва». Однако в некоторых парах, коэффициент отличается на порядок!!! Кто-то может сказать, что в принципе «все нормально», но определенно можно было бы сформировать календарь так, чтобы (по 1 таблице) Терек сыграл с Томью, а Краснодар с Рубином. Как ни крути в Сибири в ноябре прохладно и бегать и уж тем более смотреть на трибуне.
Спасибо! Как всегда рад Вашим комментариям.
ссылка на оригинал статьи http://habrahabr.ru/post/185130/
Добавить комментарий