Код C # для метода голосования Дондт, Парламент Великобритании

Пожалуйста, можете ли вы проверить, достаточно ли хорошо написанный мной код соответствует 4 правилам ООП, если есть что-то, что можно улучшить или что-то просто неправильное, я рад изменить (очень новичок в C #, извините, если это ужасно).

В коде реализован «метод Дхонд’та», который представляет собой систему опроса. https://www.bbc.co.uk/news/uk-politics-27187434

ГЛАВНЫЙ

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Voting_System
{
    class Program
    {  
        static void Main(string[] args)
        {
            // Establish the file path 
            string filepath = @"C:UsersmatheOneDriveDocumentsAll AssignmentsVoting Systeminputdata.txt";

            // Store values in a list of string
            List<string> file = File.ReadAllLines(filepath).ToList();

            // Puts each party into a list of Party and display Name + Votes
            List<Party> partys = new List<Party>();
            foreach (string line in file)
            {
                string[] items = line.Split(',');
                Party p = new Party(items[0], Convert.ToInt32(items[1]));
                partys.Add(p);
            }

            // Ask user for thresh hold and also calculate total votes
            Console.WriteLine("What is the threshold for partys (%) (round number) ?");
            int thresHold = Convert.ToInt32(Console.ReadLine());

            // Ask user how many seats they want to allocate
            Console.WriteLine("nHow many seats do you want to allocate in total? (round number)");
            int seatsCount = Convert.ToInt32(Console.ReadLine());

            // Calcutions for Dhon't method
            int totalVotes = SumOfVotes(partys);
            DisplayPercentageVotes(partys, thresHold, totalVotes);
            CalculateDhondt(partys, seatsCount);
            DisplayWinningParties(partys);

            Console.ReadKey();
        }

        // Print out all partys and there properties to user
        private static void DisplayWinningParties(List<Party> partys)
        {
            foreach (Party p in partys)
            {   
                if (p.Seats > 0)
                {
                    Console.WriteLine(p);
                }
            }
        }

        // Find total votes
        private static int SumOfVotes(List<Party> partys)
        {
            int totalVotes = 0;
            foreach (Party p in partys)
            {
                totalVotes += p.Votes;
            }
            Console.WriteLine($"nTOTAL No OF COMBINED VOTES FOR ALL PARTIES 2020 : {totalVotes}n");
            return totalVotes;
        }

        // Displays percent of votes for each party 
        private static void DisplayPercentageVotes(List<Party> partys, int threshold, int totalvotes)
        {
            // Displays percent of votes for each party 
            Console.WriteLine($"PARTIES THAT MEET THE {threshold}% INPUTTED THRESHOLD:");
            foreach (Party p in partys)
            {
                if (p.PercentOfVotes(totalvotes) > threshold)
                {
                    Console.WriteLine($"{p.Name} has {Math.Round(p.PercentOfVotes(totalvotes),2)} % of total votes.");
                }
            }
        }

        // Method to do the main caclutions of the Dhon't method
        private static void CalculateDhondt(List<Party> partys, int seatsCount)
        {
            // Find intial party with highest votes
            Party biggestVote = partys.Aggregate((v1, v2) => v1.Votes > v2.Votes ? v1 : v2);
            biggestVote.Seats += 1;
            biggestVote.DivideParty();

            // Keep looping through partys and applying dhond't method until all seats are taken
            int totalSeatsCount = 0;
            while (totalSeatsCount != seatsCount)
            {
                Party biggestVotes = partys.Aggregate((v1, v2) => v1.NewVotes > v2.NewVotes ? v1 : v2);
                biggestVotes.Seats += 1;
                biggestVotes.DivideParty();

                foreach (Party p in partys)
                {
                    totalSeatsCount += p.Seats;
                }
                // If we havent reached desired seats count reset the total seats variable
                if (totalSeatsCount != seatsCount)
                {
                    totalSeatsCount = 0;
                }
            }
            Console.WriteLine($"nWE HAVE {seatsCount} SEATS ALLOCATED:");
        }
    }
}

ВЕЧЕРИНКА

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Voting_System
{
    class Party
    {
        // properties for each party
        public string Name { get; private set; }
        public int Votes { get; private set; }
        public int NewVotes { get; set; }
        public int Seats { get; set; }

        // Constructor for party class 
        public Party(string name, int votes)
        {
            Name = name;
            Votes = votes;
            NewVotes = votes;
        }

        // Returns percentage of votes for your party
        public double PercentOfVotes(double totalVotes) => (Votes / totalVotes) * 100;

        // When ever you print the object of this class return this
        public override string ToString()
        {
            return $"Name: {Name} Votes: {Votes} Seats: {Seats}";
        }

        // Applies Dhond't method of division 
        public void DivideParty()
        {
            NewVotes = Votes / (1 + Seats);
        }
    }
}

ФАЙЛ ВВОДА ДАННЫХ

Brexit Party,452321,BP1,BP2,BP3,BP4,BP5;
Liberal Democrats,203989,LD1,LD2,LD3,LD4,LD5;
Labour,164682,LAB1,LAB2,LAB3,LAB4,LAB5;
Conservative,126138,CON1,CON2,CON3,CON4,CON5;
Green,124630,GR1,GR2,GR3,GR4,GR5;
UKIP,58198,UKP1,UKP2,UKP3,UKP4,UKP5;
Change UK,41117,CUK1,CUK2,CUK3,CUK4,CUK5;
Independent Network,7641,INET1,INET2,INET3,INET4,INET5;
Independent,4511,IND1;

1 ответ
1

В этом обзоре я остановлюсь только на Абстракция и Инкапсуляция потому что два других не применимы в этом сценарии.


Когда мы говорим об ООП, мы обычно имеем в виду четко определенные объекты (с известными обязанностями), которые взаимодействуют друг с другом для решения более серьезной проблемы.

Абстракция

Мы разбиваем исходную задачу на множество более мелких частей. Их можно решить как самостоятельно, так и в сотрудничестве. Если вы реализуете определенный алгоритм, обычно есть координатор / оркестратор, который осуществляет связь между объектами.

Эта роль координатора (логика) может находиться внутри вашего Main метод:

static void Main(string[] args)
{
    var parameters = DhondtMethodAlgorithmParameters.GatherFromConsole();
    var inputData = DhondtMethodAlgorithmInput.LoadFromFile(inputFilePath);
    
    var algorithm = new DhondtMethodAlgorithm(parameters, inputData);
    var results = algorithm.PerformCalculation();
    
    DisplayResults(results);
}
  • Здесь у нас есть 3 разных этапа:
    • Сбор данных и преобразование их в желаемую форму
    • Настройка алгоритма и его вызов
    • Отображение результата расчета

Мы разделили исходную проблему на более мелкие части, каждый из которых имеет четко определенные рамки и ответственность. Мы должны продолжать это разделение, пока не достигнем точки, от которой мы не сможем разделиться дальше.

Это упражнение поможет нам определить объекты и их поведение.

Инкапсуляция

Чтобы правильно использовать инкапсуляцию, мы должны скрыть детали нашей реализации за абстракцией. Другими словами, абстракция должна гарантировать постоянную согласованность данных с точки зрения потребителя.

Например, мы не создаем DhondtMethodAlgorithmParameters экземпляр, если данные, предоставленные пользователем, искажены. Мы можем досрочно завершить работу с исключением или повторить попытку собрать параметры от пользователя. Когда бы мы ни прошли GatherFromConsole factory, то мы можем быть уверены, что возвращенный DhondtMethodAlgorithmParameters содержит только достоверные данные.

То же самое касается LoadFromFile. Может быть много разных проблем (например, файл не существует, данные повреждены и т. Д.), Которые код может или не может решить. Но с точки зрения абстракции и инкапсуляции всякий раз, когда функция возвращается с проанализированными и проверенными входными данными (DhondtMethodAlgorithmInput instance), то мы можем быть уверены, что он находится в согласованном состоянии.

С точки зрения алгоритма инкапсуляция может означать, что его входные данные и параметры неизменны после создания. Он не предоставляет никаких методов или членов, с помощью которых потребитель экземпляра алгоритма может изменять базовые данные.


Итак, вкратце:

  1. Определить объекты и их обязанности << Абстракции
  2. Выставляйте только те члены, которые необходимы для совместной работы << Инкапсуляция

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *