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

Шмаков Данил #192

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ x64/
x86/
bld/
[Bb]in/
![Bbin]/**/mystem.exe
[Oo]bj/

# Visual Studio 2015 cache/options directory
Expand Down
38 changes: 38 additions & 0 deletions TagCloud/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Drawing;

namespace TagCloud;

public class CircularCloudLayouter
{
private List<Rectangle> rectangles;
private Point center;
Reltig marked this conversation as resolved.
Show resolved Hide resolved
private ICloudShaper shaper;

public IEnumerable<Rectangle> Rectangles => rectangles;
Reltig marked this conversation as resolved.
Show resolved Hide resolved

public CircularCloudLayouter(Point center, ICloudShaper shaper)
{
this.center = center;
rectangles = new List<Rectangle>();
this.shaper = shaper;
}

public Rectangle PutNextRectangle(Size size)
{
if (size.Width <= 0)
throw new ArgumentException("Size width must be positive number");
if (size.Height <= 0)
throw new ArgumentException("Size height must be positive number");

Rectangle rectangle = Rectangle.Empty;
foreach (var point in shaper.GetPossiblePoints())
{
rectangle = new Rectangle(point, size);
if (!Rectangles.Any(rect => rect.IntersectsWith(rectangle)))
break;
}

rectangles.Add(rectangle);
return rectangle;
}
}
11 changes: 11 additions & 0 deletions TagCloud/CloudDrawers/CloudDrawer.cs
Reltig marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Drawing;
using TagCloud;

namespace TagCloudTests;

public interface ICloudDrawer
{
int FontSize { get; }
void Draw(IEnumerable<TextRectangle> rectangle);
Size GetTextRectangleSize(string text, int size);
}
72 changes: 72 additions & 0 deletions TagCloud/CloudDrawers/TagCloudDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Drawing;
using TagCloudTests;

namespace TagCloud;

public class TagCloudDrawer : ICloudDrawer
{
private readonly string path;
private readonly IColorSelector selector;
private readonly string name;
private readonly int fontSize;

private TagCloudDrawer(string path, string name, IColorSelector selector, int fontSize)
{
this.path = path;
this.selector = selector;
this.fontSize = fontSize;
this.name = name;
}

public int FontSize => fontSize;

public void Draw(IEnumerable<TextRectangle> rectangles)
Reltig marked this conversation as resolved.
Show resolved Hide resolved
{
if (rectangles.Count() == 0)
Reltig marked this conversation as resolved.
Show resolved Hide resolved
throw new ArgumentException("Empty rectangles list");

var minX = rectangles.Min(rect => rect.X);
var maxX = rectangles.Max(rect => rect.Right);
var minY = rectangles.Min(rect => rect.Top);
var maxY = rectangles.Max(rect => rect.Bottom);
Reltig marked this conversation as resolved.
Show resolved Hide resolved

using var bitmap = new Bitmap(maxX - minX + 2, maxY - minY + 2);
using var graphics = Graphics.FromImage(bitmap);
graphics.DrawRectangles(
selector,
Reltig marked this conversation as resolved.
Show resolved Hide resolved
rectangles
.Select(rect => rect with { X = -minX + rect.X, Y = -minY + rect.Y })
.Select(rect => new Rectangle(rect.X, rect.Y, rect.Width, rect.Height))
.ToArray()
);
graphics.DrawStrings(
selector,
rectangles
.Select(rect => rect with { X = -minX + rect.X, Y = -minY + rect.Y })
.ToArray()
);
Reltig marked this conversation as resolved.
Show resolved Hide resolved

SaveToFile(bitmap);
}

public Size GetTextRectangleSize(string text, int size)
Reltig marked this conversation as resolved.
Show resolved Hide resolved
{
var graphics = Graphics.FromImage(new Bitmap(1,1));
Reltig marked this conversation as resolved.
Show resolved Hide resolved
var sizeF = graphics.MeasureString(text, new Font(FontFamily.GenericSerif, size));
return new Size((int)sizeF.Width, (int)sizeF.Height);
}

private void SaveToFile(Bitmap bitmap)
{
var pathToFile = @$"{path}\{name}.jpg";
bitmap.Save(pathToFile);
Console.WriteLine($"Tag cloud visualization saved to file {path}");
}

public static TagCloudDrawer Create(string path, string name, int size, IColorSelector selector)

Choose a reason for hiding this comment

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

Комментарий, аналогичный тому, который я писал для SpiralCloudShaper

{
if (!Directory.Exists(path))
throw new ArgumentException("Directory does not exist");
return new TagCloudDrawer(path, name, selector, size);
}
}
15 changes: 15 additions & 0 deletions TagCloud/ColorSelectors/ConstantColorSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Drawing;
using TagCloudTests;

namespace TagCloud;

public class ConstantColorSelector : IColorSelector
{
private Color color;
public ConstantColorSelector(Color color)
{
this.color = color;
}

public Color PickColor() => color;
}
8 changes: 8 additions & 0 deletions TagCloud/ColorSelectors/IColorSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagCloudTests;

public interface IColorSelector
{
Color PickColor();
}
22 changes: 22 additions & 0 deletions TagCloud/ColorSelectors/RandomColorSelector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Drawing;

namespace TagCloudTests;

public class RandomColorSelector : IColorSelector
{
private readonly Random random;

public RandomColorSelector()
{
random = new Random(DateTime.Now.Microsecond);
}

public Color PickColor()
{
return Color.FromArgb(255,
random.Next(0, 255),
random.Next(0, 255),
random.Next(0, 255)
);
}
}
27 changes: 27 additions & 0 deletions TagCloud/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Drawing;
using TagCloudTests;

namespace TagCloud;

public static class Extensions
Reltig marked this conversation as resolved.
Show resolved Hide resolved
{
public static void DrawRectangles(this Graphics graphics, IColorSelector selector, Rectangle[] rectangles, int lineWidth = 1)
{
var pen = new Pen(selector.PickColor(), lineWidth);
Reltig marked this conversation as resolved.
Show resolved Hide resolved
foreach (var rectangle in rectangles)
{
graphics.DrawRectangle(pen, rectangle);
pen.Color = selector.PickColor();
Reltig marked this conversation as resolved.
Show resolved Hide resolved
}
}

public static void DrawStrings(this Graphics graphics, IColorSelector selector, TextRectangle[] rectangles)
{
var brush = new SolidBrush(selector.PickColor());
Reltig marked this conversation as resolved.
Show resolved Hide resolved
foreach (var rectangle in rectangles)
{
graphics.DrawString(rectangle.Text, rectangle.Font, brush, rectangle.X, rectangle.Y);
brush.Color = selector.PickColor();
}
}
}
8 changes: 8 additions & 0 deletions TagCloud/ICloudShaper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagCloud;

public interface ICloudShaper
{
IEnumerable<Point> GetPossiblePoints();
}
49 changes: 49 additions & 0 deletions TagCloud/Option.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using CommandLine;

namespace TagCloudApplication;

public class Options
{
[Option('d', "destination", HelpText = "Set destination path.", Default = @"..\..\..\Results")]
public string DestinationPath { get; set; }

[Option('s', "source", HelpText = "Set source path.", Default = @"..\..\..\Results\text.txt")]
public string SourcePath { get; set; }

[Option('n', "name", HelpText = "Set name.", Default = "default")]
public string Name { get; set; }

[Option('c', "color", HelpText = "Set color.", Default = "random")]
public string ColorScheme { get; set; }

[Option('f', "font", HelpText = "Set font.", Default = "Comic Sans")]
public string Font { get; set; }

[Option("size", HelpText = "Set font size.", Default = 20)]
public int FontSize { get; set; }

[Option("width", HelpText = "Set width.", Default = 100)]
public int Width { get; set; }

[Option("height", HelpText = "Set height.", Default = 100)]
public int Height { get; set; }

public static Options Default
Reltig marked this conversation as resolved.
Show resolved Hide resolved
{
get
{
var options = new Options();
foreach (var property in typeof(Options).GetProperties())
{
var option = property
.GetCustomAttributes(typeof(OptionAttribute), false)
.Cast<OptionAttribute>()
.FirstOrDefault();
if (option != null && option.Default != null)
property.SetValue(options, option.Default);
}

return options;
}
}
}
53 changes: 53 additions & 0 deletions TagCloud/SpiralCloudShaper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Drawing;

namespace TagCloud;

public class SpiralCloudShaper : ICloudShaper
{
private Point center;
private double coefficient;
private double deltaAngle;

private SpiralCloudShaper(Point center, double coefficient, double deltaAngle)
{
this.center = center;
this.deltaAngle = deltaAngle;
this.coefficient = coefficient;
}

public IEnumerable<Point> GetPossiblePoints()
{
var currentAngle = 0D;
var position = center;
var previousPoint = position;
while(true)
{
while (position == previousPoint)
{
currentAngle += deltaAngle;
previousPoint = position;
position = CalculatePointByCurrentAngle(currentAngle);
}
yield return position;
previousPoint = position;
position = CalculatePointByCurrentAngle(currentAngle);
}
}

private Point CalculatePointByCurrentAngle(double angle)
{
return new Point(
center.X + (int)(coefficient * angle * Math.Cos(angle)),
center.Y + (int)(coefficient * angle * Math.Sin(angle))
);
}

public static SpiralCloudShaper Create(Point center, double coefficient = 0.1, double deltaAngle = 0.1)

Choose a reason for hiding this comment

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

Немного контекста о том, когда и как обычно создаются такие методы:

  1. Модели - простые контейнеры для свойств. В твоем случае класс Options, где ты как раз и применил этот подход со статическим созданием. Из общих примеров можно взять FluentResults - там результат можно создавать как Result.Fail() и Result.Ok() (за точность методов не ручаюсь, просто показываю подход)
  2. Билдеры сложных моделей - Builder.Build() - обычный паттерн строитель, когда тебе нужно собрать сложную модель
  3. Фабрики моделей и зависимостей - паттерн фабрики (в разных вариациях) - обычно используется как раз для создания зависимостей для отдачи в контейнере

На основе всего, что написал выше - нам подходит последний пункт, так как SpiralCloudShaper - это не модель, а полноценная зависимость (модуль), и он не должен уметь хранить внутри себя ещё и логику собственного создания, для этого нужно отдельное место

{
if (coefficient <= 0)
throw new ArgumentException("Spiral coefficient must be positive number");
if (deltaAngle <= 0)
throw new ArgumentException("Spiral delta angle must be positive number");
return new SpiralCloudShaper(center, coefficient, deltaAngle);
}
}
16 changes: 16 additions & 0 deletions TagCloud/TagCloud.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="MyStemWrapper" Version="1.0.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
</ItemGroup>

</Project>
Loading