1
0

feat: Complete L3.K2

This commit is contained in:
Rokas Puzonas 2022-04-07 15:05:22 +03:00
parent 636d2b21e5
commit d603b57809
4 changed files with 398 additions and 1 deletions

5
L3/K2/Duomenys.txt Normal file
View File

@ -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

14
L3/K2/K2.csproj Normal file
View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<None Update="Duomenys.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

372
L3/K2/Program.cs Normal file
View File

@ -0,0 +1,372 @@
using System;
using System.IO;
namespace K2
{
public interface IBetween<T>
{
/// <summary>
/// Indicates whether the value of the certain property of the current instance is in
/// [<paramref name="from"/>, <paramref name="to"/>] range including range marginal values.
/// <paramref name="from"/> should always precede <paramref name="to"/> in default sort order.
/// </summary>
/// <param name="from">The starting value of the range</param>
/// <param name="to">The ending value of the range</param>
/// <returns>true if the value of the current object property is in range; otherwise,
/// false.</returns>
bool MutuallyInclusiveBetween(T from, T to);
/// <summary>
/// Indicates whether the value of the certain property of the current instance is in
/// [<paramref name="from"/>, <paramref name="to"/>] range excluding range marginal values.
/// <paramref name="from"/> should always precede <paramref name="to"/> in default sort order.
/// </summary>
/// <param name="from">The starting value of the range</param>
/// <param name="to">The ending value of the range</param>
/// <returns>true if the value of the current object property is in range; otherwise,
/// false.</returns>
bool MutuallyExclusiveBetween(T from, T to);
}
/// <summary>
/// Provides generic container where the data are stored in the linked list.
/// </summary>
/// <typeparam name="T">The type of the data to be stored in the list. Data
/// class should implement some interfaces.</typeparam>
public class LinkList<T>
where T: IComparable<T>
{
class Node
{
public T Data { get; set; }
public Node Next { get; set; }
public Node(T data, Node next)
{
Data = data;
Next = next;
}
}
/// <summary>
/// All the time should point to the first element of the list.
/// </summary>
private Node begin;
/// <summary>
/// All the time should point to the last element of the list.
/// </summary>
private Node end;
/// <summary>
/// Shouldn't be used in any other methods except Begin(), Next(), Exist() and Get().
/// </summary>
private Node current;
/// <summary>
/// Initializes a new instance of the LinkList class with empty list.
/// </summary>
public LinkList()
{
begin = current = end = null;
}
/// <summary>
/// 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.
/// </summary>
public void Begin()
{
current = begin;
}
/// <summary>
/// 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.
/// </summary>
public void Next()
{
current = current.Next;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>true, if the internal pointer points to some element of the list; otherwise,
/// false.</returns>
public bool Exist()
{
return current != null;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>the value of the element that is pointed by the internal pointer.</returns>
public T Get()
{
return current.Data;
}
/// <summary>
/// Method appends new node to the end of the list and saves in it <paramref name="data"/>
/// passed by the parameter.
/// </summary>
/// <param name="data">The data to be stored in the list.</param>
public void Add(T data)
{
var node = new Node(data, null);
if (begin == null)
{
begin = node;
end = node;
} else
{
end.Next = node;
end = node;
}
}
/// <summary>
/// Method sorts data in the list. The data object class should implement IComparable
/// interface though defining sort order.
/// </summary>
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;
}
}
}
}
}
/// <summary>
/// Provides properties and interface implementations for the storing and manipulating of cars data.
/// </summary>
public class Car : IComparable<Car>, IBetween<double>, IBetween<string>
{
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;
}
/// <summary>
/// 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.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>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.</returns>
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
{
/// <summary>
/// Creates the list containing data read from the text file.
/// </summary>
/// <param name="fileName">The name of the text file</param>
/// <returns>List with data from file</returns>
public static LinkList<Car> ReadFromFile(string fileName)
{
var cars = new LinkList<Car>();
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;
}
/// <summary>
/// Appends the table, built from data contained in the list and preceded by the header,
/// to the end of the text file.
/// </summary>
/// <param name="fileName">The name of the text file</param>
/// <param name="header">The header of the table</param>
/// <param name="list">The list from which the table to be formed</param>
public static void PrintToFile(string fileName, string header, LinkList<Car> 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
{
/// <summary>
/// The method finds the biggest price value in the given list.
/// </summary>
/// <param name="list">The data list to be searched.</param>
/// <returns>The biggest price value.</returns>
public static double MaxPrice(LinkList<Car> list)
{
double maxPrice = -1;
for (list.Begin(); list.Exist(); list.Next())
{
var car = list.Get();
maxPrice = Math.Max(maxPrice, car.Price);
}
return maxPrice;
}
/// <summary>
/// Filters data from the source list that meets filtering criteria and writes them
/// into the new list.
/// </summary>
/// <typeparam name="TData">The type of the data objects stored in the list</typeparam>
/// <typeparam name="TCriteria">The type of criteria</typeparam>
/// <param name="source">The source list from which the result would be created</param>
/// <param name="from">Lower bound of the interval</param>
/// <param name="to">Upper bound of the interval</param>
/// <returns>The list that contains filtered data</returns>
public static LinkList<TData> Filter<TData, TCriteria>(LinkList<TData> source, TCriteria from, TCriteria to)
where TData : IComparable<TData>, IBetween<TCriteria>
{
var filtered = new LinkList<TData>();
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.
}
}
}

View File

@ -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