-
Notifications
You must be signed in to change notification settings - Fork 32
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 14 commits
59d38a8
45b91db
441cd69
143db64
baf26aa
8149754
1b85764
3f413ea
29ea260
e9254ec
5259a19
78bb80a
cf302b3
66b48b9
c329079
529f90c
821147e
2392c92
db6772b
29142c4
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,46 @@ | ||
using FluentAssertions; | ||
using System.Drawing; | ||
using TagsCloudContainer.PointGenerators; | ||
|
||
|
||
namespace TagsCloudContainer.Tests | ||
{ | ||
[TestFixture] | ||
public class CloudLayoutShould | ||
{ | ||
private CloudLayout layout; | ||
[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,27 @@ | ||
using FluentAssertions; | ||
using System.Drawing; | ||
using TagsCloudContainer.StringParsers; | ||
using TagsCloudContainer.TagGenerator; | ||
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(@"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); | ||
} | ||
} | ||
} |
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 @@ | ||
он ОНА ОНО корзина творог печенье Корзина ++ ,- = корЗина по ха за |
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); | ||
} | ||
} | ||
} |
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(); | ||
} | ||
} | ||
} |
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; } | ||
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. Точно должен быть 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)); | ||
} | ||
} | ||
} | ||
|
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 | ||
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. Раньше файл конфигурации использовался в классах и был необходим в библиотеке. Теперь же все его значения используются только в клиенте, поэтому нет причин его оставлять здесь. Клиенту нужно как-то собрать приложение, для этого он использует свою специфичную сущность |
||
{ | ||
public Type PointGenerator { get; set; } | ||
|
||
public bool RandomColor; | ||
public Color Color { get; set; } | ||
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. Названия у этих свойств не очень отражают суть. Получится придать им смысла? И ещё не очень понятно, как быть в ситуации, когда |
||
|
||
} |
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() | ||
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. Писать один раз удобно, но в поддержке тяжело. Поиском не найти, где этот интерфейс применяется и с кем связан. А ещё возможны потенциальные конфликты, так как иногда один класс реализует несколько интерфейсов, и не ясно, к какому его использовать. А ещё вложенное наследование |
||
.SingleInstance(); | ||
|
||
if (config.RandomColor) | ||
container.RegisterType<RandomColorTagGenerator>() | ||
.AsImplementedInterfaces() | ||
.SingleInstance(); | ||
else | ||
{ | ||
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. Фигурные скобки сильно путают. Если у |
||
container.RegisterType<SingleColorTagGenerator>() | ||
.AsImplementedInterfaces() | ||
.SingleInstance(); | ||
} | ||
|
||
|
||
return container.Build(); | ||
} | ||
} |
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; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudContainer.PointGenerators | ||
{ | ||
[Label("Спираль")] | ||
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. Это интересная техника, хорошо что прочитал. Но здесь на мой взгляд это перебор. Если что-то подобное делать, то нужно использовать локализации, а это уже совсем другая история. Предлагаю остановиться просто на названиях классов или даже цифрах при выборе. Это уже будет определяться реализацией клиента (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; | ||
} | ||
} | ||
} | ||
} |
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.
Можно не выносить в общее поле, ведь нигде в других местах его не нужно переиспользовать. А лишний раз делать общие переменные плохо сказывается на параллельности выполнения