diff --git a/L3/K2/Duomenys.txt b/L3/K2/Duomenys.txt new file mode 100644 index 0000000..670d33c --- /dev/null +++ b/L3/K2/Duomenys.txt @@ -0,0 +1,5 @@ +Toshiba;123Bąčę;1200.01 +Foobar;AAA;1300.01 +Foobar;AAB;1300.01 +Foobar;BBB;1350.01 +Baz BAAAZ;The FOO - BAZ;1700.12345 \ No newline at end of file diff --git a/L3/K2/K2.csproj b/L3/K2/K2.csproj new file mode 100644 index 0000000..ab828a7 --- /dev/null +++ b/L3/K2/K2.csproj @@ -0,0 +1,14 @@ + + + + Exe + netcoreapp3.1 + + + + + Always + + + + diff --git a/L3/K2/Program.cs b/L3/K2/Program.cs new file mode 100644 index 0000000..4061616 --- /dev/null +++ b/L3/K2/Program.cs @@ -0,0 +1,372 @@ +using System; +using System.IO; + +namespace K2 +{ + public interface IBetween + { + /// + /// Indicates whether the value of the certain property of the current instance is in + /// [, ] range including range marginal values. + /// should always precede in default sort order. + /// + /// The starting value of the range + /// The ending value of the range + /// true if the value of the current object property is in range; otherwise, + /// false. + bool MutuallyInclusiveBetween(T from, T to); + + /// + /// Indicates whether the value of the certain property of the current instance is in + /// [, ] range excluding range marginal values. + /// should always precede in default sort order. + /// + /// The starting value of the range + /// The ending value of the range + /// true if the value of the current object property is in range; otherwise, + /// false. + bool MutuallyExclusiveBetween(T from, T to); + } + + /// + /// Provides generic container where the data are stored in the linked list. + /// + /// The type of the data to be stored in the list. Data + /// class should implement some interfaces. + public class LinkList + where T: IComparable + { + class Node + { + public T Data { get; set; } + public Node Next { get; set; } + public Node(T data, Node next) + { + Data = data; + Next = next; + } + } + + /// + /// All the time should point to the first element of the list. + /// + private Node begin; + + /// + /// All the time should point to the last element of the list. + /// + private Node end; + + /// + /// Shouldn't be used in any other methods except Begin(), Next(), Exist() and Get(). + /// + private Node current; + + /// + /// Initializes a new instance of the LinkList class with empty list. + /// + public LinkList() + { + begin = current = end = null; + } + + /// + /// One of four interface methods devoted to loop through a list and get value stored in it. + /// Method should be used to move internal pointer to the first element of the list. + /// + public void Begin() + { + current = begin; + } + + /// + /// One of four interface methods devoted to loop through a list and get value stored in it. + /// Method should be used to move internal pointer to the next element of the list. + /// + public void Next() + { + current = current.Next; + } + + /// + /// One of four interface methods devoted to loop through a list and get value stored in it. + /// Method should be used to check whether the internal pointer points to the element of the list. + /// + /// true, if the internal pointer points to some element of the list; otherwise, + /// false. + public bool Exist() + { + return current != null; + } + + /// + /// One of four interface methods devoted to loop through a list and get value stored in it. + /// Method should be used to get the value stored in the node pointed by the internal pointer. + /// + /// the value of the element that is pointed by the internal pointer. + public T Get() + { + return current.Data; + } + + /// + /// Method appends new node to the end of the list and saves in it + /// passed by the parameter. + /// + /// The data to be stored in the list. + public void Add(T data) + { + var node = new Node(data, null); + if (begin == null) + { + begin = node; + end = node; + } else + { + end.Next = node; + end = node; + } + } + + /// + /// Method sorts data in the list. The data object class should implement IComparable + /// interface though defining sort order. + /// + public void Sort() + { + for (Node nodeA = begin; nodeA != null; nodeA = nodeA.Next) + { + if (nodeA.Next == null) continue; + + for (Node nodeB = nodeA.Next; nodeB != null; nodeB = nodeB.Next) + { + if (nodeA.Data.CompareTo(nodeB.Data) < 0) + { + T tmp = nodeA.Data; + nodeA.Data = nodeB.Data; + nodeB.Data = tmp; + } + } + } + } + } + + /// + /// Provides properties and interface implementations for the storing and manipulating of cars data. + /// + public class Car : IComparable, IBetween, IBetween + { + public string Manufacturer { get; set; } + public string Model { get; set; } + public double Price { get; set; } + + public Car(string manufacturer, string model, double price) + { + Manufacturer = manufacturer; + Model = model; + Price = price; + } + + /// + /// Compares the current instance with another object of the same type and returns an integer + /// that indicates whether the current instance precedes, follows, or occurs in the same + /// position in the sort order as the other object. + /// + /// An object to compare with this instance. + /// A value that indicates the relative order of the objects being compared.The + /// return value has these meanings: -1 when this instance precedes other in the sort order; + /// 0 when this instance occurs in the same position in the sort order as other; + /// 1 when this instance follows other in the sort order. + public int CompareTo(Car other) + { + if (Price < other.Price) + { + return -1; + } else if (Price == other.Price) + { + return -Model.CompareTo(other.Model); + } else + { + return 1; + } + } + + public bool MutuallyInclusiveBetween(double from, double to) + { + return from <= Price && Price <= to; + } + + public bool MutuallyExclusiveBetween(double from, double to) + { + return from < Price && Price < to; + } + + public bool MutuallyInclusiveBetween(string from, string to) + { + return Manufacturer.CompareTo(from) <= 0 && Manufacturer.CompareTo(to) >= 0; + } + + public bool MutuallyExclusiveBetween(string from, string to) + { + return Manufacturer.CompareTo(from) < 0 && Manufacturer.CompareTo(to) > 0; + } + } + + public static class InOut + { + /// + /// Creates the list containing data read from the text file. + /// + /// The name of the text file + /// List with data from file + public static LinkList ReadFromFile(string fileName) + { + var cars = new LinkList(); + foreach (var line in File.ReadAllLines(fileName)) + { + string[] parts = line.Split(';'); + string manufacturer = parts[0].Trim(); + string model = parts[1].Trim(); + double price = double.Parse(parts[2].Trim()); + cars.Add(new Car(manufacturer, model, price)); + } + return cars; + } + + /// + /// Appends the table, built from data contained in the list and preceded by the header, + /// to the end of the text file. + /// + /// The name of the text file + /// The header of the table + /// The list from which the table to be formed + public static void PrintToFile(string fileName, string header, LinkList list) + { + using (var writer = new StreamWriter(fileName, true)) + { + writer.WriteLine(new string('-', 53)); + writer.WriteLine("| {0, -49} |", header); + writer.WriteLine(new string('-', 53)); + + // Klausimas: Ar GRIEŽTAI negalima kurtis savo pagalbinių funkcijų? + // Nes šitoje situacijoje žemiau labai praverstų tiesiog susikurti `IsEmpty` metodą. + // Kartu prie to pačio, man labai nepatinka `Begin`, `Exist` ir `Next`, tai koks `IEnumerable` + // manau yra žymiai geresnis sprendimas, kad kaip sukti ciklą per listą. + list.Begin(); + if (list.Exist()) + { + writer.WriteLine("| {0,-20} | {1,-15} | {2,8} |", "Gamintojas", "Modelis", "Kaina"); + writer.WriteLine(new string('-', 53)); + for (list.Begin(); list.Exist(); list.Next()) + { + var car = list.Get(); + writer.WriteLine("| {0,-20} | {1,-15} | {2,8:f2} |", car.Manufacturer, car.Model, car.Price); + } + } else + { + writer.WriteLine("| {0, -49} |", "Nėra"); + } + writer.WriteLine(new string('-', 53)); + writer.WriteLine(); + } + } + } + + public static class Task + { + /// + /// The method finds the biggest price value in the given list. + /// + /// The data list to be searched. + /// The biggest price value. + public static double MaxPrice(LinkList list) + { + double maxPrice = -1; + for (list.Begin(); list.Exist(); list.Next()) + { + var car = list.Get(); + maxPrice = Math.Max(maxPrice, car.Price); + } + return maxPrice; + } + + /// + /// Filters data from the source list that meets filtering criteria and writes them + /// into the new list. + /// + /// The type of the data objects stored in the list + /// The type of criteria + /// The source list from which the result would be created + /// Lower bound of the interval + /// Upper bound of the interval + /// The list that contains filtered data + public static LinkList Filter(LinkList source, TCriteria from, TCriteria to) + where TData : IComparable, IBetween + { + var filtered = new LinkList(); + for (source.Begin(); source.Exist(); source.Next()) + { + var item = source.Get(); + if (item.MutuallyInclusiveBetween(from, to)) + { + filtered.Add(item); + } + } + return filtered; + } + } + + class Program + { + // Klausimas: Ar reikia kurti testus `LinkList` klasei? + static void Main() + { + string inputFilename = "Duomenys.txt"; + string outputFilename = "Rezultatai.txt"; + File.Delete(outputFilename); + + Console.Write("Įveskite pirmą gamintoją: "); + string manufacturer1 = Console.ReadLine(); + Console.Write("Įveskite antrą gamintoją: "); + string manufacturer2 = Console.ReadLine(); + + var cars1 = InOut.ReadFromFile(inputFilename); + InOut.PrintToFile(outputFilename, "Pradinės mašinos", cars1); + + var cars2 = Task.Filter(cars1, manufacturer1, manufacturer1); + var cars3 = Task.Filter(cars1, manufacturer2, manufacturer2); + InOut.PrintToFile(outputFilename, string.Format("Mašinos pagal gamintoją '{0}'", manufacturer1), cars2); + InOut.PrintToFile(outputFilename, string.Format("Mašinos pagal gamintoją '{0}'", manufacturer2), cars3); + + var maxPrice = Task.MaxPrice(cars1); + var cars4 = Task.Filter(cars2, maxPrice * 0.75, maxPrice); + var cars5 = Task.Filter(cars3, maxPrice * 0.75, maxPrice); + cars4.Sort(); + cars5.Sort(); + InOut.PrintToFile(outputFilename, string.Format("Brangios mašinos pagal gamintoją '{0}'", manufacturer1), cars4); + InOut.PrintToFile(outputFilename, string.Format("Brangios mašinos pagal gamintoją '{0}'", manufacturer2), cars5); + + // Klausimas: Ar galima įdėti išdemą į failą maine? + // Taip, žinau per LD darbus negalima tai daryti. Bet K2 apraše + // parašyta, kad negalima pridėti naujų metodų ar keisti egzistuojančių + // kamienus. + // Bet reikalaujama išvesti surastą didžiausią kainą į failo galą + // su paaiškinamu tekstu. + // Paradoksas ¯\_(ツ)_/¯ + using (var writer = new StreamWriter(outputFilename, true)) + { + writer.WriteLine("Didžiausia mašinos kaina: {0:f2}", maxPrice); + } + + // Klausimas: KAS SUGALVOJO ŠITĄ UŽDUOTĮ?!?!?! + // Niekada nebuvau matęs, kad kas būtų naudojąs interface užklojimiui vieno + // lauko palyginimiui pagal tipą. IR DAR tą inteface reikia panaudoti 2 kartus ant `Car` + // klasės, kad būtų galima patikrinti skirtingus laukus?! + // Čia atrodo, kad kažkas bandė išsisukinėti, kad nereikėtų kurti 2 `Task.Filter` + // ir galų gale gavosi, kad reikia aplamai turėti daugiau kodo kad pasiekti tą patį + // rezultatą. Ir dar ant viršaus, jeigu to nepakako `MutuallyExclusiveBetween` metodai + // lieka nepanaudoti. + // Ką galiu pasakyti tai, kad man labai nepatiko šita užduotis. + } + } +} diff --git a/L3/L3.sln b/L3/L3.sln index 48a6674..8ac655c 100644 --- a/L3/L3.sln +++ b/L3/L3.sln @@ -5,7 +5,9 @@ VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LD_24", "LD_24\LD_24.csproj", "{AE159626-A105-440C-B997-F377C5F8F280}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LD_24Tests", "LD_24Tests\LD_24Tests.csproj", "{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LD_24Tests", "LD_24Tests\LD_24Tests.csproj", "{39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "K2", "K2\K2.csproj", "{2C869FE9-7C18-4EA6-BE85-B4B10A557F25}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -21,6 +23,10 @@ Global {39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Debug|Any CPU.Build.0 = Debug|Any CPU {39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Release|Any CPU.ActiveCfg = Release|Any CPU {39E0FA27-E323-45EE-BA1B-5DDFE00A7C03}.Release|Any CPU.Build.0 = Release|Any CPU + {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C869FE9-7C18-4EA6-BE85-B4B10A557F25}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE