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

Ослина Анастасия #15

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 35 additions & 0 deletions TagsCloudVisualization/App/ConsoleApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using TagsCloudVisualization.ConsoleCommands;
using TagsCloudVisualization.FileReaders;
using TagsCloudVisualization.Layouters;
using TagsCloudVisualization.Renderers;
using TagsCloudVisualization.WordPreprocessors;

namespace TagsCloudVisualization.App;

public class ConsoleApp : IApp
{
private readonly IWordPreprocessor wordPreprocessor;
private readonly IFileReader fileReader;
private readonly ICloudLayouter cloudLayouter;
private readonly ICloudRenderer cloudRenderer;
private readonly string inputFilePath;

public ConsoleApp(IWordPreprocessor wordPreprocessor,
IFileReader fileReader,
ICloudLayouter cloudLayouter,
ICloudRenderer cloudRenderer,
Options options)
{
this.wordPreprocessor = wordPreprocessor;
this.fileReader = fileReader;
this.cloudLayouter = cloudLayouter;
this.cloudRenderer = cloudRenderer;
inputFilePath = options.InputFilePath;
}

public void Run()
{
var words = wordPreprocessor.ProcessWords(fileReader.Read(inputFilePath));
cloudRenderer.Render(cloudLayouter.CreateTagsCloud(words));
}
}
6 changes: 6 additions & 0 deletions TagsCloudVisualization/App/IApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudVisualization.App;

public interface IApp
{
public void Run();
}
25 changes: 25 additions & 0 deletions TagsCloudVisualization/ConsoleCommands/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using CommandLine;

namespace TagsCloudVisualization.ConsoleCommands;

public class Options
{
[Option('i', "inputFilePath", Required = true, HelpText = "Set input file path.")]
public string InputFilePath { get; set; }
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
malinaboky marked this conversation as resolved.
Show resolved Hide resolved

[Option('o', "outputFilePath", Required = true, HelpText = "Set output file path.")]
public string OutputFilePath { get; set; }
malinaboky marked this conversation as resolved.
Show resolved Hide resolved

[Option('f', "font", Default = "Arial", HelpText = "Set font for tags cloud words.")]
public string TagsFont { get; set; }

[Option('h', "imageHeight", Default = 1080, HelpText = "Set output image height.")]
public int ImageHeight { get; set; }

[Option('w', "imageWidth", Default = 1920, HelpText = "Set output image width.")]
public int ImageWidth { get; set; }

[Option('b', "backgroundColor", Default = "Empty",
HelpText = "Set background color for tags cloud.")]
public string BackgroundColor { get; set; }
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
}
41 changes: 41 additions & 0 deletions TagsCloudVisualization/ContainerConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Autofac;
using MyStemWrapper;
using TagsCloudVisualization.App;
using TagsCloudVisualization.ConsoleCommands;
using TagsCloudVisualization.Distributors;
using TagsCloudVisualization.FileReaders;
using TagsCloudVisualization.Layouters;
using TagsCloudVisualization.Renderers;
using TagsCloudVisualization.Renderers.ColorGenerators;
using TagsCloudVisualization.WordPreprocessors;
using TagsCloudVisualization.WordPreprocessors.FontCreators;
using TagsCloudVisualization.WordPreprocessors.WordValidators;

namespace TagsCloudVisualization;

public static class ContainerConfig
{
public static IContainer Configure(Options options)
{
var builder = new ContainerBuilder();
builder.RegisterInstance(options).AsSelf().SingleInstance();
Copy link

@Folleach Folleach Dec 20, 2024

Choose a reason for hiding this comment

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

Меня несколько смущает, что объект Options это синглтон, который позволяет себя модифицировать.
Какой-то из компонентов может воспользоваться этим и поменять некоторые значения, ожидая, что у него личный экземпляр настроек, словно локальная переменная.

Choose a reason for hiding this comment

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

Несмотря на то, что по умолчанию Autofac регистрирует как per dependency, тут зарегистрирован конкретный объект options. Autofac не будет его копировать, поэтому шанс случайной модификации остаётся возможен
image

builder.RegisterType<DefaultColorGenerator>().As<IColorGenerator>().SingleInstance();
builder.RegisterType<SpiralDistribution>().As<ICloudDistribution>();
builder.RegisterType<DefaultRenderer>().As<ICloudRenderer>();
builder.RegisterType<DelegateFileReader>().As<IFileReader>();
builder.RegisterType<DefaultFontCreator>().As<IFontCreator>();
builder.RegisterType<DefaultWordValidator>().As<IWordValidator>();
builder.RegisterType<DefaultWordPreprocessor>().As<IWordPreprocessor>();
builder.RegisterType<CircularCloudLayouter>().As<ICloudLayouter>();
builder.RegisterType<ConsoleApp>().As<IApp>();

var myStem = new MyStem
{
PathToMyStem = Path.GetFullPath("Utilities\\mystem.exe"),
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
Parameters = "-ni"
};
builder.RegisterInstance(myStem).AsSelf().SingleInstance();

return builder.Build();
}
}
8 changes: 8 additions & 0 deletions TagsCloudVisualization/Distributors/ICloudDistribution.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagsCloudVisualization.Distributors;

public interface ICloudDistribution
{
public Point GetNextPoint();
}
35 changes: 35 additions & 0 deletions TagsCloudVisualization/Distributors/SpiralDistribution.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Drawing;
using TagsCloudVisualization.ConsoleCommands;

namespace TagsCloudVisualization.Distributors;

public class SpiralDistribution : ICloudDistribution
{
private const double AngleStep = 0.02;
private const double RadiusStep = 0.01;
private double angle;
private double radius;
private readonly Point cloudCenter;

public SpiralDistribution(Options options)
{
cloudCenter = new Point(options.ImageWidth / 2, options.ImageHeight / 2);
}
malinaboky marked this conversation as resolved.
Show resolved Hide resolved

public Point GetNextPoint()
{
var nextPoint = ConvertPolarToCartesian();
angle += AngleStep;
radius += RadiusStep;
return nextPoint;
}

public Point GetCenter() => cloudCenter;

private Point ConvertPolarToCartesian()
{
var cartesian = new Point((int)(radius * Math.Cos(angle)), (int)(radius * Math.Sin(angle)));
cartesian.Offset(cloudCenter);
return cartesian;
}
}
17 changes: 17 additions & 0 deletions TagsCloudVisualization/Domain/Tag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Drawing;

namespace TagsCloudVisualization.Domain;

public class Tag
{
public readonly Rectangle Rectangle;
public readonly Font Font;
public readonly string Content;

public Tag(Rectangle rectangle, Font font, string content)
{
Rectangle = rectangle;
Font = font;
Content = content;
}
}
33 changes: 33 additions & 0 deletions TagsCloudVisualization/FileReaders/DelegateFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace TagsCloudVisualization.FileReaders;

//Хочу попробовать переписать на visitor, чтобы избежать свича
public class DelegateFileReader : IFileReader
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
{
public IEnumerable<string> Read(string filePath)
{
try
{
var reader = CreateReader(filePath);
return reader.Read(filePath);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
}

private static IFileReader CreateReader(string filePath)
{
if (!File.Exists(filePath))
throw new FileNotFoundException("File not found", filePath);

var extension = Path.GetExtension(filePath).Trim('.');
Enum.TryParse(extension, true, out FileType fileType);

return fileType switch
{
FileType.Txt => new TextFileReader(),
_ => throw new NotSupportedException($"File type {fileType} is not supported.")
};
}
}
6 changes: 6 additions & 0 deletions TagsCloudVisualization/FileReaders/FileType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudVisualization.FileReaders;

public enum FileType
{
Txt
}
6 changes: 6 additions & 0 deletions TagsCloudVisualization/FileReaders/IFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudVisualization.FileReaders;

public interface IFileReader
{
public IEnumerable<string> Read(string filePath);
}
9 changes: 9 additions & 0 deletions TagsCloudVisualization/FileReaders/TextFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TagsCloudVisualization.FileReaders;

public class TextFileReader : IFileReader
{
public IEnumerable<string> Read(string filePath)
{
return File.ReadAllLines(filePath);
}
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
}
53 changes: 53 additions & 0 deletions TagsCloudVisualization/Layouters/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Drawing;
using TagsCloudVisualization.Distributors;
using TagsCloudVisualization.Domain;
using TagsCloudVisualization.WordPreprocessors.FontCreators;

namespace TagsCloudVisualization.Layouters;

public class CircularCloudLayouter : ICloudLayouter
{
private readonly ICloudDistribution distribution;
private readonly IFontCreator fontCreator;

public CircularCloudLayouter(ICloudDistribution distribution, IFontCreator fontCreator)
{
this.distribution = distribution;
this.fontCreator = fontCreator;
}

public IEnumerable<Tag> CreateTagsCloud(Dictionary<string, int> wordsCollection)
{
List<Tag> tags = [];
using var graphic = Graphics.FromImage(new Bitmap(1, 1));
foreach (var word in wordsCollection)
{
var tagFont = fontCreator.CreateFont(word.Value);
var rectangleSize = ConvertWordToRectangleSize(graphic, word.Key, tagFont);
var rectangle = GetNextRectangle(tags, rectangleSize);

tags.Add(new Tag(rectangle, tagFont, word.Key));
malinaboky marked this conversation as resolved.
Show resolved Hide resolved
}

return tags;
}

private Rectangle GetNextRectangle(List<Tag> tags, Size rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
throw new ArgumentException("The rectangle size must be greater than zero.");

var newRectangle = new Rectangle(distribution.GetNextPoint(), rectangleSize);

while (tags.Any(r => r.Rectangle.IntersectsWith(newRectangle)))
newRectangle.Location = distribution.GetNextPoint();

return newRectangle;
}

private static Size ConvertWordToRectangleSize(Graphics graphic, string word, Font font)
{
var sizeF = graphic.MeasureString(word, font);
return new Size((int)Math.Ceiling(sizeF.Width), (int)Math.Ceiling(sizeF.Height));
}
}
8 changes: 8 additions & 0 deletions TagsCloudVisualization/Layouters/ICloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using TagsCloudVisualization.Domain;

namespace TagsCloudVisualization.Layouters;

public interface ICloudLayouter
{
public IEnumerable<Tag> CreateTagsCloud(Dictionary<string, int> wordsCollection);
}
18 changes: 18 additions & 0 deletions TagsCloudVisualization/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Autofac;
using CommandLine;
using TagsCloudVisualization.App;
using TagsCloudVisualization.ConsoleCommands;

namespace TagsCloudVisualization;

public class Program
{
static void Main(string[] args)

Choose a reason for hiding this comment

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

Странно, что при неправильном вызове приложения выводится Exception в конце подсказки
image

Copy link

@Folleach Folleach Dec 27, 2024

Choose a reason for hiding this comment

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

resolved

upd: нет, не совсем.

Мне не понятно, почему команда сообщает о двух ошибках одновременно:

Required option 'i, inputFilePath' is missing.
Required option 'o, outputDirectory' is missing.
Value cannot be null. (Parameter 'instance')

image

Кажется, в данном случае правильно показать только требуемые параметры, а не null reference exception.
В то же время важно сохранить настоящие исключения, чтобы в случае ошибок было понятно, как исправлять

{
var options = Parser.Default.ParseArguments<Options>(args).Value;
var container = ContainerConfig.Configure(options);

using var scope = container.BeginLifetimeScope();
scope.Resolve<IApp>().Run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Drawing;

namespace TagsCloudVisualization.Renderers.ColorGenerators;

public class DefaultColorGenerator : IColorGenerator
{
private static Random random = new();
malinaboky marked this conversation as resolved.
Show resolved Hide resolved

public Color GetColor()
{
return Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagsCloudVisualization.Renderers.ColorGenerators;

public interface IColorGenerator
{
public Color GetColor();
}
Loading