Skip to content
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

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
59d38a8
start
d2em0n Dec 25, 2024
45b91db
add simple filter
d2em0n Dec 25, 2024
441cd69
add textprocessor
d2em0n Dec 25, 2024
143db64
add some tests for processor, filter, provider
d2em0n Dec 26, 2024
baf26aa
add layout with some tests
d2em0n Dec 26, 2024
8149754
add interface for TextProcessor
d2em0n Dec 26, 2024
1b85764
add Tag and interface for Tag generator
d2em0n Dec 26, 2024
3f413ea
remove and sort usings, text processor refactoring
d2em0n Dec 27, 2024
29ea260
Word became record
d2em0n Dec 27, 2024
e9254ec
add interface for string parsers
d2em0n Dec 27, 2024
5259a19
add rnd color tag generator
d2em0n Dec 27, 2024
78bb80a
add shortwordfilter
d2em0n Jan 3, 2025
cf302b3
hypothesis
d2em0n Jan 3, 2025
66b48b9
add chosing color
d2em0n Jan 3, 2025
c329079
add IColorProvider and refactor TagGenerator
d2em0n Jan 4, 2025
529f90c
pattern filter for filters
d2em0n Jan 4, 2025
821147e
container refuse to wark (
d2em0n Jan 5, 2025
2392c92
mvp
d2em0n Jan 6, 2025
db6772b
add DocTextProvider
d2em0n Jan 7, 2025
29142c4
DocXTextProvider
d2em0n Jan 7, 2025
2cb1edd
minus unused usings
d2em0n Jan 11, 2025
8eeaab8
fix color and pointgenerator checking
d2em0n Jan 12, 2025
ab0392f
fix color data integrity
d2em0n Jan 12, 2025
825fa46
fix random for multithreading in randomcolorprovider
d2em0n Jan 12, 2025
2fa6816
no public mod to interface methods
d2em0n Jan 12, 2025
946768e
fix TxtText provider
d2em0n Jan 12, 2025
7c1ca09
dispose idisposable
d2em0n Jan 12, 2025
ef193e7
fix regexparser
d2em0n Jan 12, 2025
cb067a4
fix packages
d2em0n Jan 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions TagsCloudContainer.Tests/CloudLayoutShould.cs
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;

Choose a reason for hiding this comment

The 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);
}
}
}
44 changes: 44 additions & 0 deletions TagsCloudContainer.Tests/IPointGeneratorShould.cs
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));
}
}
}
27 changes: 27 additions & 0 deletions TagsCloudContainer.Tests/RandomColorTagGeneratorShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using FluentAssertions;
using System.Drawing;
using TagsCloudContainer.StringParsers;
using TagsCloudContainer.TagGenerator;
using TagsCloudContainer.TextProviders;
using TagsCloudContainer.WordFilters;

namespace TagsCloudContainer.Tests
{
public class RandomColorTagGeneratorShould

Choose a reason for hiding this comment

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Графика нигде не используется


var processor = new TextProcessor.TextProcessor(@"TextFile1.txt",
new TxtTextProvider(), new RegexParser(), new BoringWordFilter());
var generator = new RandomColorTagGenerator(processor, graphics, new Font("arial", 12));
var result = generator.GenerateTags().First();

result.Font.Name.Should().Be("Arial");
result.Font.Size.Should().Be(36);
}
}
}
35 changes: 35 additions & 0 deletions TagsCloudContainer.Tests/TagsCloudContainer.Tests.csproj
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>
1 change: 1 addition & 0 deletions TagsCloudContainer.Tests/TextFile1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
он ОНА ОНО корзина творог печенье Корзина ++ ,- = корЗина по ха за
21 changes: 21 additions & 0 deletions TagsCloudContainer.Tests/TextProcessorShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using FluentAssertions;
using TagsCloudContainer.StringParsers;
using TagsCloudContainer.TextProviders;
using TagsCloudContainer.WordFilters;

namespace TagsCloudContainer.Tests
{
public class TextProcessorShould
{
[Test]
public void Process()
{
var result = new TextProcessor.TextProcessor(@"TextFile1.txt",
new TxtTextProvider(), new RegexParser(), new BoringWordFilter(), new ShortWordFilter()).Words();

result.Count.Should().Be(3);

result.MaxBy(word => word.Value).Value.Should().Be(3);
}
}
}
32 changes: 32 additions & 0 deletions TagsCloudContainer.Tests/TxtTextProviderShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using FluentAssertions;
using TagsCloudContainer.TextProviders;

namespace TagsCloudContainer.Tests
{
public class TxtTextProviderShould
{
private TxtTextProvider _provider;
[SetUp]
public void Setup()
{
_provider = new TxtTextProvider();
}

[Test]
public void ThrowExceptionIfFileNotFounded()
{
Action act = () => _provider.ReadFile("NotExisted.txt");

act.Should().Throw<FileNotFoundException>();
}

[Test]
public void ReturnLowerCase()
{
var result = _provider.ReadFile("TextFile1.txt");

foreach (var c in result.Where(c => char.IsLetter(c)))
char.IsLower(c).Should().BeTrue();
}
}
}
65 changes: 65 additions & 0 deletions TagsCloudContainer/CloudLayout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Drawing;
using TagsCloudContainer.PointGenerators;

namespace TagsCloudContainer
{
public class CloudLayout
{
public readonly Point Center;
public readonly Size Size;
private readonly IEnumerable<Point> _points;
public List<Rectangle> Rectangles { get; set; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Точно должен быть public?



public CloudLayout(Point center, IPointGenerator pointGenerator)
{
if (center.X <= 0 || center.Y <= 0)
throw new ArgumentException("Center coordinates values have to be greater than Zero");
Center = center;
Size = CountSize(center);
Rectangles = [];
_points = pointGenerator.GeneratePoints(Center);
}

public CloudLayout(Size size, IPointGenerator pointGenerator)
{
Size = size;
Center = FindCenter(size);
Rectangles = [];
_points = pointGenerator.GeneratePoints(Center);
}


private Size CountSize(Point center)
{
var width = (center.X % 2 == 0) ? center.X * 2 + 1 : Center.X * 2;
var height = (center.Y % 2 == 0) ? center.Y * 2 + 1 : center.Y * 2;
return new Size(width, height);
}

private static Point FindCenter(Size size)
{
return new Point(size.Width / 2, size.Height / 2);
}

public Rectangle PutNextRectangle(Size rectangleSize)
{
foreach (var point in _points)
{
var supposed = new Rectangle(new Point(point.X - rectangleSize.Width / 2, point.Y - rectangleSize.Height / 2),
rectangleSize);
if (IntersectsWithAnyOther(supposed, Rectangles))
continue;
Rectangles.Add(supposed);
return supposed;
}
throw new ArgumentException("Not Enough Points Generated");
}

public static bool IntersectsWithAnyOther(Rectangle supposed, List<Rectangle> others)
{
return others.Any(x => x.IntersectsWith(supposed));
}
}
}

18 changes: 18 additions & 0 deletions TagsCloudContainer/Configuration/Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TagsCloudContainer.PointGenerators;

namespace TagsCloudContainer.Configuration;

public class Config

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Раньше файл конфигурации использовался в классах и был необходим в библиотеке. Теперь же все его значения используются только в клиенте, поэтому нет причин его оставлять здесь. Клиенту нужно как-то собрать приложение, для этого он использует свою специфичную сущность Config.

{
public Type PointGenerator { get; set; }

public bool RandomColor;
public Color Color { get; set; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Названия у этих свойств не очень отражают суть. Получится придать им смысла? И ещё не очень понятно, как быть в ситуации, когда RandomColor=true и цвет тоже указан. Можно посмотреть в сторону nullable типов


}
35 changes: 35 additions & 0 deletions TagsCloudContainer/Configuration/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autofac;
using TagsCloudContainer.TagGenerator;

namespace TagsCloudContainer.Configuration;

public class DependencyInjection
{
public IContainer BuildContainer(Config config)
{
var container = new ContainerBuilder();

container.RegisterType(config.PointGenerator)
.AsImplementedInterfaces()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Писать один раз удобно, но в поддержке тяжело. Поиском не найти, где этот интерфейс применяется и с кем связан. А ещё возможны потенциальные конфликты, так как иногда один класс реализует несколько интерфейсов, и не ясно, к какому его использовать. А ещё вложенное наследование

.SingleInstance();

if (config.RandomColor)
container.RegisterType<RandomColorTagGenerator>()
.AsImplementedInterfaces()
.SingleInstance();
else
{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Фигурные скобки сильно путают. Если у if их нет, то скорее всего в else тоже они не нужны

container.RegisterType<SingleColorTagGenerator>()
.AsImplementedInterfaces()
.SingleInstance();
}


return container.Build();
}
}
13 changes: 13 additions & 0 deletions TagsCloudContainer/LabelAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TagsCloudContainer
{
public class LabelAttribute(string labelText) : Attribute
{
public string LabelText { get; set; } = labelText;
}
}
23 changes: 23 additions & 0 deletions TagsCloudContainer/PointGenerators/ArchemedianSpiral.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Drawing;

namespace TagsCloudContainer.PointGenerators
{
[Label("Спираль")]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это интересная техника, хорошо что прочитал. Но здесь на мой взгляд это перебор. Если что-то подобное делать, то нужно использовать локализации, а это уже совсем другая история. Предлагаю остановиться просто на названиях классов или даже цифрах при выборе. Это уже будет определяться реализацией клиента (ui или console)

public class ArchemedianSpiral : IPointGenerator
{
public IEnumerable<Point> GeneratePoints(Point start)
{
var zoom = 1;
var spiralStep = 0.0;
yield return start;
while (true)
{
spiralStep += Math.PI / 180;
var x = start.X + (int)(zoom * spiralStep * Math.Cos(spiralStep));
var y = start.Y + (int)(zoom * spiralStep * Math.Sin(spiralStep));
var next = new Point(x, y);
yield return next;
}
}
}
}
Loading