Pull to refresh

Футбол на плюсе, ч.2: практическая

Reading time 4 min
Views 6.9K
Несмотря на некоторый скепсис, по поводу первой части материала, как и обещал, публикую результаты, и то как они были получены.
В основном манипуляции производились с данными, хранимыми в 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";

Для представителя уже сформированы данные по участникам соревнований, которые конечно же он не видит, также как и название команды, для которой производится расчет:
image

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 файлах достаточно удобное, т.к. некоторые тривиальные арифметические действия можно проводить сразу внутри таблиц с данными.
Выполнив случайную оценку показателей, были получены объективные характеристики участников соревнований.
image
Результаты получились вполне логичными.
Напомню, что оптимизация производится по минимальному критерию, т.е. меньше=лучше.

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();

Готово. Немного преобразования и получится следующая таблица:
image
Как видно, у Кубани и Краснодара рейтинги разные, хотя они из одного города, аналогичная ситуация у московских клубов. На основе этой информации можно оптимизировать процедуру жеребьевки. Конечно же, разные форс-мажоры, игры в еврокубках, сборные, рекомендации полиции и т.п., необходимо будет учитывать вручную, но общий каркас сетки уже будет сформирован.
Для примера сравним опубликованный календарь и нашу таблицу:
image image
Если не учитывать 2 московские пары, то примерно 50% «качества». Однако в некоторых парах, коэффициент отличается на порядок!!! Кто-то может сказать, что в принципе «все нормально», но определенно можно было бы сформировать календарь так, чтобы (по 1 таблице) Терек сыграл с Томью, а Краснодар с Рубином. Как ни крути, в Сибири в ноябре прохладно и бегать, а уж тем более смотреть на трибуне.
Спасибо! Как всегда рад Вашим комментариям.
Tags:
Hubs:
+3
Comments 1
Comments Comments 1

Articles