-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Бессараб Дмитрий #31
base: master
Are you sure you want to change the base?
Бессараб Дмитрий #31
Changes from 20 commits
59d38a8
45b91db
441cd69
143db64
baf26aa
8149754
1b85764
3f413ea
29ea260
e9254ec
5259a19
78bb80a
cf302b3
66b48b9
c329079
529f90c
821147e
2392c92
db6772b
29142c4
2cb1edd
8eeaab8
ab0392f
825fa46
2fa6816
946768e
7c1ca09
ef193e7
cb067a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\TagsCloudContainer\TagsCloudContainer.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="test.doc"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
<None Update="test.docx"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
<None Update="TestFile.txt"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using Autofac; | ||
using TagsCloudContainer; | ||
using TagsCloudContainer.ColorProviders; | ||
using TagsCloudContainer.Configuration; | ||
using TagsCloudContainer.PointGenerators; | ||
using TagsCloudContainer.StringParsers; | ||
using TagsCloudContainer.TagGenerator; | ||
using TagsCloudContainer.TextProcessor; | ||
using TagsCloudContainer.TextProviders; | ||
using TagsCloudContainer.WordFilters; | ||
|
||
namespace Client; | ||
|
||
public class DependencyInjection | ||
{ | ||
public static IContainer BuildContainer(Config config) | ||
{ | ||
var container = new ContainerBuilder(); | ||
container.RegisterInstance(config).AsSelf(); | ||
|
||
container.RegisterType(config.SupportedReadingFormats[Path.GetExtension(config.FilePath)]) | ||
.As<ITextProvider>() | ||
.WithParameter("filePath", config.FilePath) | ||
.SingleInstance(); | ||
container.RegisterType<TextProcessor>() | ||
.As<ITextProcessor>() | ||
.SingleInstance(); | ||
|
||
container.RegisterType(config.PointGenerator) | ||
.As<IPointGenerator>() | ||
.SingleInstance(); | ||
|
||
if (config.Color != null) | ||
container.RegisterType<ColorProvider>() | ||
.As<IColorProvider>() | ||
.WithParameter("color", config.Color) | ||
.SingleInstance(); | ||
else | ||
container.RegisterType<RandomColorProvider>() | ||
.As<IColorProvider>() | ||
.SingleInstance(); | ||
|
||
container.RegisterType<RegexParser>() | ||
.As<IStringParser>() | ||
.SingleInstance(); | ||
|
||
container.RegisterType<TagGenerator>() | ||
.As<ITagsGenerator>() | ||
.WithParameter("defaultFont", config.Font) | ||
.SingleInstance(); | ||
|
||
|
||
|
||
container.RegisterType<ToLowerFilter>().As<IWordFilter>() | ||
.SingleInstance(); | ||
container.RegisterType<ShortWordFilter>().As<IWordFilter>() | ||
.SingleInstance(); | ||
container.RegisterType<BoringWordFilter>().As<IWordFilter>() | ||
.SingleInstance(); | ||
|
||
container.RegisterType<PictureMaker>() | ||
.AsSelf() | ||
.WithParameter("fileName", config.PicturePath) | ||
.WithParameter("startPoint", config.StartPoint) | ||
.SingleInstance(); | ||
|
||
return container.Build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
using System.Drawing; | ||
using System.Reflection; | ||
using System.Threading.Channels; | ||
using TagsCloudContainer.Configuration; | ||
using TagsCloudContainer.PointGenerators; | ||
using TagsCloudContainer.StringParsers; | ||
using TagsCloudContainer.TextProviders; | ||
using TagsCloudContainer.WordFilters; | ||
using System.Linq; | ||
using System.Security.Cryptography.X509Certificates; | ||
using System.ComponentModel; | ||
using TagsCloudContainer; | ||
using TagsCloudContainer.TextProcessor; | ||
using Autofac; | ||
|
||
namespace Client | ||
{ | ||
internal class Program | ||
{ | ||
static void Main() | ||
{ | ||
var config = new Config(); | ||
|
||
ConfigureSupportedReadingFormats(config); | ||
ConfigureFileSource(config); | ||
ConfigureCloudView(config); | ||
ConfigureColor(config); | ||
ConfigurePathToSave(config); | ||
ConfigureStartPoint(config); | ||
ConfigureFont(config); | ||
|
||
var container = DependencyInjection.BuildContainer(config); | ||
using var scope = container.BeginLifetimeScope(); | ||
scope.Resolve<PictureMaker>().DrawPicture(); | ||
Comment on lines
+26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно использовать без усложнений со скоупами, так как жизненный цикл всех сущностей совпадает с временем жизни всего приложения. Просто у контейнера вызывать Resolve |
||
Console.WriteLine($"результат сохранен в {config.PicturePath}"); | ||
} | ||
|
||
private static void ConfigureSupportedReadingFormats(Config config) | ||
{ | ||
Console.WriteLine("Поддерживаются следующие форматы файлов для чтения:"); | ||
var textProviders = FindImplemetations<ITextProvider>(); | ||
foreach (var point in textProviders) | ||
Console.WriteLine("\t" + point.Key); | ||
config.SupportedReadingFormats = textProviders; | ||
} | ||
|
||
private static void ConfigureFont(Config config) | ||
{ | ||
config.Font = new Font("arial", 12); | ||
} | ||
|
||
private static void ConfigurePathToSave(Config config) | ||
{ | ||
Console.WriteLine("Введите полный путь и название файла для сохранения"); | ||
var inp = Console.ReadLine(); | ||
config.PicturePath = inp.Length == 0 ? "1.bmp" : inp; | ||
} | ||
|
||
private static void ConfigureStartPoint(Config config) | ||
{ | ||
Console.WriteLine("Введите координаты центра поля для рисования" + | ||
"\n При некорректном вводе координаты центра составят ( 1000, 1000)"); | ||
var xLine = Console.ReadLine(); | ||
var yLine = Console.ReadLine(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Без кода никогда не догадаться, в каком формате вводить координаты. Пользователю нужно давать как можно больше подсказок. Желательно все ReadLine заменить на что-нибудь такое
|
||
if (int.TryParse(xLine, out var xResult) && | ||
int.TryParse(yLine, out var yResult)) | ||
config.StartPoint = new Point(xResult, yResult); | ||
config.StartPoint = new Point(1000, 1000); | ||
} | ||
|
||
private static void ConfigureFileSource(Config config) | ||
{ | ||
Console.WriteLine("Введите имя файла источника тэгов"); | ||
var inp = Console.ReadLine(); | ||
config.FilePath = inp.Length == 0 ? @"TestFile.txt" : inp; | ||
} | ||
|
||
private static string GetLabel(RainbowColors color) | ||
{ | ||
var fieldInfo = color.GetType().GetField(color.ToString()); | ||
var attribute = (LabelAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(LabelAttribute)); | ||
|
||
return attribute.LabelText; | ||
} | ||
|
||
private static void ConfigureColor(Config config) | ||
{ | ||
Console.WriteLine("Выборите цвет из возможных:"); | ||
var colors = Enum.GetValues(typeof(RainbowColors)) | ||
.Cast<RainbowColors>() | ||
.ToDictionary(color => GetLabel(color).ToLower(), color => color); | ||
|
||
foreach (var color in colors) | ||
Console.WriteLine("\t" + color.Key); | ||
|
||
Console.WriteLine("В случае неправильного ввода - цвет будет выбираться случайным образом"); | ||
var inp = Console.ReadLine().ToLower(); | ||
if (colors.ContainsKey(inp)) | ||
{ | ||
config.Color = Color.FromName(colors[inp].ToString()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ContainsKey под капотом уже получает значение по ключу, а потом снова происходит поиск по этому же ключу. Здесь это чревато только повторением одного и того же действия. В многопоточном коде это может привести даже к ошибке поток 1: И такие ситуации очень неожиданные, ведь только что проверяли, что ключ есть. Поэтому если требуется в итоге работать со значением, то лучше использовать TryGetValue. Если же нужно лишь убедиться в наличии, то ContainsKey по семантике подходит лучше There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Color.FromName - почти наверняка сработает, так как поддерживает много цветов. Но безопаснее было бы сделать в библиотеке в качестве параметра конструктора у класса GolorProvider значение enum, а потом его уже в switch преобразовывать в цвет. Таким образом, если вместо color придётся использовать какой-нибудь UnixColor, для внешних пользователей ничего не поменяется в использовании |
||
Console.WriteLine($"Выбран {inp} цвет"); | ||
} | ||
else | ||
Console.WriteLine("Цвет будет выбираться случайно"); | ||
|
||
} | ||
|
||
private static void ConfigureCloudView(Config config) | ||
{ | ||
Console.WriteLine("Выберите внешний вид облака из возможных:"); | ||
var pointGenerators = FindImplemetations<IPointGenerator>(); | ||
foreach (var point in pointGenerators) | ||
Console.WriteLine("\t" + point.Key); | ||
Console.WriteLine("Введите, соблюдая орфографию"); | ||
var pointGenerator = Console.ReadLine().ToLower(); | ||
if (pointGenerators.ContainsKey(pointGenerator)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Аналогично цвету, лучше использовать TryGetValue, но не критично здесь |
||
config.PointGenerator = pointGenerators[pointGenerator]; | ||
else | ||
{ | ||
Console.WriteLine("Такой формы не предусмотрено"); | ||
ConfigureCloudView(config); | ||
} | ||
} | ||
|
||
private static Dictionary<string, Type> FindImplemetations<T>() | ||
{ | ||
var assembly = Assembly.LoadFrom("TagsCloudContainer.dll"); | ||
var type = typeof(T); | ||
return assembly.GetTypes() | ||
.Where(t => type.IsAssignableFrom(t) && !t.IsInterface) | ||
.ToDictionary(x => x.GetCustomAttribute<LabelAttribute>().LabelText.ToLower(), x => x); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
корзина корзина корзина корзина фрукты фрукты фрукты овощи овощи овощи яблоки груши бананы смородина персики картофель свекла | ||
морковь он я ты она за по |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using FluentAssertions; | ||
using System.Drawing; | ||
using TagsCloudContainer.PointGenerators; | ||
|
||
|
||
namespace TagsCloudContainer.Tests | ||
{ | ||
[TestFixture] | ||
public class CloudLayoutShould | ||
{ | ||
private CloudLayout layout; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно не выносить в общее поле, ведь нигде в других местах его не нужно переиспользовать. А лишний раз делать общие переменные плохо сказывается на параллельности выполнения |
||
[TestCase(1, 2, TestName = "Odd coordinate value results in an even size value")] | ||
[TestCase(2, 5, TestName = "Even coordinate value results in an odd size value")] | ||
public void MakeRightSizeLayout(int coordinateValue, int sizeValue) | ||
{ | ||
var center = new Point(coordinateValue, coordinateValue); | ||
var size = new Size(sizeValue, sizeValue); | ||
|
||
layout = new CloudLayout(center, new ArchemedianSpiral()); | ||
|
||
layout.Size.Should().BeEquivalentTo(size); | ||
} | ||
|
||
[TestCase(-1, 1, TestName = "Negative X")] | ||
[TestCase(1, -1, TestName = "Negative Y")] | ||
[TestCase(0, 1, TestName = "Zero X")] | ||
[TestCase(1, 0, TestName = "Zero Y")] | ||
public void GetOnlyPositiveCenterCoordinates(int x, int y) | ||
{ | ||
Action makeLayout = () => new CloudLayout(new Point(x, y), new ArchemedianSpiral()); | ||
|
||
makeLayout.Should().Throw<ArgumentException>() | ||
.WithMessage("Center coordinates values have to be greater than Zero"); | ||
} | ||
|
||
[Test] | ||
public void PutNextRectangle_ShouldKeepEnteredSize() | ||
{ | ||
layout = new CloudLayout(new Point(5, 5), new ArchemedianSpiral()); | ||
var enteredSize = new Size(3, 4); | ||
var returnedSize = layout.PutNextRectangle(enteredSize).Size; | ||
|
||
returnedSize.Should().BeEquivalentTo(enteredSize); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using FluentAssertions; | ||
using System.Drawing; | ||
using TagsCloudContainer.PointGenerators; | ||
|
||
namespace TagsCloudContainer.Tests | ||
{ | ||
[TestFixture] | ||
public class IPointGeneratorShould | ||
{ | ||
[TestCaseSource(nameof(TestCases))] | ||
public void GeneratePoints_MovingAwayFromTheStartFor(IPointGenerator pointGenerator) | ||
{ | ||
var start = new Point(0, 0); | ||
var points = pointGenerator.GeneratePoints(start); | ||
var nearPoint = points.ElementAt(100); | ||
var farPoint = points.ElementAt(1000); | ||
|
||
DistanceBetween(start, nearPoint).Should().BeLessThan(DistanceBetween(start, farPoint)); | ||
} | ||
|
||
[TestCaseSource(nameof(TestCases))] | ||
public void GeneratePoints_ReturnsStartAsFirstPointFor(IPointGenerator pointGenerator) | ||
{ | ||
var start = new Point(100, 100); | ||
var firstReturned = pointGenerator.GeneratePoints(start) | ||
.First(); | ||
|
||
firstReturned.Should().BeEquivalentTo(start); | ||
} | ||
|
||
private static IEnumerable<IPointGenerator> TestCases() | ||
{ | ||
yield return new ArchemedianSpiral(); | ||
yield return new HeartShaped(); | ||
yield return new DeltaShaped(); | ||
} | ||
|
||
private static int DistanceBetween(Point start, Point destination) | ||
{ | ||
return (int)Math.Sqrt((start.X - destination.X) * (start.X - destination.X) + | ||
(start.Y - destination.Y) * (start.Y - destination.Y)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using FluentAssertions; | ||
using System.Drawing; | ||
using TagsCloudContainer.ColorProviders; | ||
using TagsCloudContainer.StringParsers; | ||
using TagsCloudContainer.TextProviders; | ||
using TagsCloudContainer.WordFilters; | ||
|
||
namespace TagsCloudContainer.Tests | ||
{ | ||
public class RandomColorTagGeneratorShould | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это ведь тест на два независимых объекта: TagGenerator и RandomColorProvider. Сложно будет понять, из-за кого пошло не так, при последующей разработке |
||
{ | ||
[Test] | ||
public void SetRightFontSize() | ||
{ | ||
var bitmap = new Bitmap(1, 1); | ||
using var graphics = Graphics.FromImage(bitmap); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Графика нигде не используется |
||
|
||
var processor = new TextProcessor.TextProcessor( | ||
new TxtTextProvider(@"TextFile1.txt"), new RegexParser(), new BoringWordFilter()); | ||
var words = processor.WordFrequencies(); | ||
var generator = new TagGenerator.TagGenerator(new RandomColorProvider(), new Font("arial", 12)); | ||
var result = generator.GenerateTags(words).First(); | ||
|
||
result.Font.Name.Should().Be("Arial"); | ||
result.Font.Size.Should().Be(36); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
<PackageReference Include="FluentAssertions" Version="7.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="NUnit" Version="3.14.0" /> | ||
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\TagsCloudContainer\TagsCloudContainer.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="NUnit.Framework" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="TextFile1.txt"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
он ОНА ОНО корзина творог печенье Корзина ++ ,- = корЗина по ха за |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Очень много лишних using (