Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
93 changes: 93 additions & 0 deletions TagCloudConsoleClient/ConsoleClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using CommandLine;
using System.Drawing;
using System.Drawing.Imaging;
using TagCloudGenerator.Core.Interfaces;
using TagCloudGenerator.Core.Models;
using TagCloudGenerator.Infrastructure;
using TagCloudGenerator.Infrastructure.Readers;
using static System.Runtime.InteropServices.JavaScript.JSType;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Лишние using. В других местах тоже проверь

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Проверил, постарался убрать все лишние


namespace TagCloudConsoleClient
{
public class ConsoleClient : IClient
{
private readonly ITagCloudGenerator _generator;
private readonly IEnumerable<IFilter> _filters;
private readonly IReaderRepository _readersRepository;
private readonly INormalizer _normalizer;

public ConsoleClient(ITagCloudGenerator generator, IEnumerable<IFilter> filters, IReaderRepository readers, INormalizer normalizer)
{
_generator = generator;
_filters = filters;
_readersRepository = readers;
_normalizer = normalizer;
}

public void Run(string[] args)
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed(RunWithOptions)
.WithNotParsed(errors => { });
}

private void RunWithOptions(Options opts)
{
if (!File.Exists(opts.InputFile))
{
Console.WriteLine($"Error: input file '{opts.InputFile}' does not exist.");
return;
}

var canvasSettings = new CanvasSettings()
.SetSize(opts.Width, opts.Height)
.SetBackgroundColor(TryParseColor(opts.BackgroundColor))
.WithShowRectangles()
.SetPadding(opts.Padding);

var textSettings = new TextSettings()
.SetFontFamily(opts.FontFamily)
.SetFontSizeRange(opts.MinFontSize, opts.MaxFontSize)
.SetTextColor(TryParseColor(opts.TextColor));

string inputFile = opts.InputFile;
string outputFile = opts.OutputFile;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

string => var

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Исправил


Console.WriteLine("Starting tag cloud generation...");
Console.WriteLine($"Input file: {inputFile}");
Console.WriteLine($"Output file: {outputFile}");


_readersRepository.TryGetReader(inputFile)
.Then(reader => reader.TryRead(inputFile))
.Then(words => _normalizer.Normalize(words))
.Then(words => _generator.Generate(words, canvasSettings, textSettings, _filters))
.Then(image => Result.OfAction(() => image.Save(outputFile, ImageFormat.Png), "Failed to save output image"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Аргументы для метода OfAction стоит разбить по строкам (лямбда и сообщение в случае ошибки). Так будет легче читать.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Поменял

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

image нужно задиспоузить после сохранения

.OnFail(error =>
{
Console.WriteLine("Error during generation:");
Console.WriteLine(error);
});
}

private static Color? TryParseColor(string colorStr)
{
if (string.IsNullOrWhiteSpace(colorStr))
return null;

try
{
var known = Color.FromName(colorStr);
if (known.IsKnownColor)
return known;

return ColorTranslator.FromHtml(colorStr);
}
catch
{
Console.WriteLine($"Color '{colorStr}' could not be parsed. Default color will be used.");
return null;
}
}
}
}
41 changes: 41 additions & 0 deletions TagCloudConsoleClient/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using CommandLine;

namespace TagCloudConsoleClient
{
public class Options
{
[Value(0, MetaName = "input",
HelpText = "Path to the input file containing text.",
Required = true)]
public string InputFile { get; set; }

[Value(1, MetaName = "output",
HelpText = "Path for the output image (e.g., out.png).",
Required = true)]
public string OutputFile { get; set; }

[Option("width", HelpText = "Canvas width (default is 1000).")]
public int? Width { get; set; }

[Option("height", HelpText = "Canvas height (default is 1000).")]
public int? Height { get; set; }

[Option("padding", HelpText = "Canvas padding (default if 50).")]
public int? Padding { get; set; }

[Option("bgcolor", HelpText = "Background color (name or #RRGGBB).")]
public string BackgroundColor { get; set; }

[Option("textcolor", HelpText = "Text color (name or #RRGGBB).")]
public string TextColor { get; set; }

[Option("font", HelpText = "Font family name (e.g., Arial).")]
public string FontFamily { get; set; }

[Option("minsize", HelpText = "Minimum font size.")]
public float? MinFontSize { get; set; }

[Option("maxsize", HelpText = "Maximum font size.")]
public float? MaxFontSize { get; set; }
}
}
25 changes: 25 additions & 0 deletions TagCloudConsoleClient/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Autofac;
using TagCloudGenerator.Core.Interfaces;
using TagCloudGenerator.DI;
using TagCloudGenerator.Infrastructure.Filters;

namespace TagCloudConsoleClient
{
public class Program
{
public static void Main(string[] args)
{
var builder = new ContainerBuilder();

builder.RegisterModule<TagCloudModule>();
builder.RegisterType<BoringWordsFilter>().As<IFilter>();
builder.RegisterType<ConsoleClient>().As<IClient>();

var container = builder.Build();

using var scope = container.BeginLifetimeScope();
var client = scope.Resolve<IClient>();
client.Run(args);
}
}
}
14 changes: 14 additions & 0 deletions TagCloudConsoleClient/TagCloudConsoleClient.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\TagCloudGenerator\TagCloudGenerator.csproj" />
</ItemGroup>

</Project>
100 changes: 100 additions & 0 deletions TagCloudGenerator/Algorithms/BasicTagCloudAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System.Drawing;
using TagCloudGenerator.Core.Interfaces;

namespace TagCloudGenerator.Algorithms
{
public class BasicTagCloudAlgorithm : ITagCloudAlgorithm
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Здесь тоже переход на Result нужен

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Обновил

{
private Point center;

private readonly Random random = new Random();

private readonly List<Rectangle> rectangles = new List<Rectangle>();

private double currentAngle = 0;
private double currentRadius = 0;

private int countToGenerate = 10;

private (int min, int max) width = new(20, 21);
private (int min, int max) height = new(20, 21);

private double angleStep = 0.1;
private double radiusStep = 0.5;

public BasicTagCloudAlgorithm(Point center)
{
if (center.X <= 0 || center.Y <= 0) throw new ArgumentException("Center coordinates must be positives");
this.center = center;
}

public BasicTagCloudAlgorithm()
{
this.center = new Point(0, 0);
}

public Rectangle PutNextRectangle(Size rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0) throw new ArgumentException("Rectangle sizes must be positives");

if (rectangles.Count == 0)
{
return PutFirstRectangle(rectangleSize);
}

return PlaceNextRectange(rectangleSize);
}

private Rectangle PlaceNextRectange(Size rectangleSize)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Опечатка

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Исправил

{
while (true)
{
double x = center.X + currentRadius * Math.Cos(currentAngle);
double y = center.Y + currentRadius * Math.Sin(currentAngle);

var potentialCenter = new Point((int)(x - rectangleSize.Width / 2), (int)(y - rectangleSize.Height / 2));
var potentialRectangle = new Rectangle(potentialCenter, rectangleSize);

if (!IntersectWithAny(potentialRectangle))
{
rectangles.Add(potentialRectangle);
return potentialRectangle;
}

currentAngle += angleStep;
if (currentAngle >= 2 * Math.PI)
{
currentAngle = 0;
currentRadius += radiusStep;
}
}
}

private bool IntersectWithAny(Rectangle potentialRectangle)
{
return rectangles.Any(rect => rect.IntersectsWith(potentialRectangle));
}

private Rectangle PutFirstRectangle(Size rectangleSize)
{
var firstCenter = new Point((int)(center.X - rectangleSize.Width / 2), (int)(center.Y - rectangleSize.Width / 2));
var first = new Rectangle(firstCenter, rectangleSize);
currentRadius = rectangleSize.Height / 2;
rectangles.Add(first);
return first;
}

public BasicTagCloudAlgorithm WithCenterAt(Point point)
{
if (point.X <= 0 || point.Y <= 0) throw new ArgumentException("Center coordinates must be positives");
center = point;
return this;
}

public ITagCloudAlgorithm Reset()
{
rectangles.Clear();
return this;
}
}
}
9 changes: 9 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using TagCloudGenerator.Core.Models;

namespace TagCloudGenerator.Core.Interfaces
{
public interface IAnalyzer
{
Dictionary<string, int> Analyze(List<string> words);
}
}
7 changes: 7 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TagCloudGenerator.Core.Interfaces
{
public interface IClient
{
void Run(string[] args);
}
}
8 changes: 8 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

namespace TagCloudGenerator.Core.Interfaces
{
public interface IFilter
{
List<string> Filter(List<string> words);
}
}
8 changes: 8 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IFontSizeCalculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

namespace TagCloudGenerator.Core.Interfaces
{
public interface IFontSizeCalculator
{
float Calculate(int wordFrequency, int minFrequency, int maxFrequency, float minFontSize, float maxFontSize);
}
}
10 changes: 10 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IFormatReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using TagCloudGenerator.Infrastructure;

namespace TagCloudGenerator.Core.Interfaces
{
public interface IFormatReader
{
bool CanRead(string filePath);
Result<List<string>> TryRead(string filePath);
}
}
7 changes: 7 additions & 0 deletions TagCloudGenerator/Core/Interfaces/INormalizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TagCloudGenerator.Core.Interfaces
{
public interface INormalizer
{
public List<string> Normalize(List<string> words);
}
}
9 changes: 9 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IReaderRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using TagCloudGenerator.Infrastructure;

namespace TagCloudGenerator.Core.Interfaces
{
public interface IReaderRepository
{
public Result<IFormatReader> TryGetReader(string filePath);
}
}
11 changes: 11 additions & 0 deletions TagCloudGenerator/Core/Interfaces/IRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Drawing;
using TagCloudGenerator.Core.Models;
using TagCloudGenerator.Infrastructure;

namespace TagCloudGenerator.Core.Interfaces
{
public interface IRenderer
{
public Result<Bitmap> Render(IEnumerable<CloudItem> items, CanvasSettings canvasSettings, TextSettings textSettings);
}
}
8 changes: 8 additions & 0 deletions TagCloudGenerator/Core/Interfaces/ISorterer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

namespace TagCloudGenerator.Core.Interfaces
{
public interface ISorterer
{
public List<(string Word, int Frequency)> Sort(Dictionary<string, int> wordsWithFreqs);
}
}
12 changes: 12 additions & 0 deletions TagCloudGenerator/Core/Interfaces/ITagCloudAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Drawing;
using TagCloudGenerator.Algorithms;

namespace TagCloudGenerator.Core.Interfaces
{
public interface ITagCloudAlgorithm
{
Rectangle PutNextRectangle(Size rectangleSize);

public ITagCloudAlgorithm Reset();
}
}
11 changes: 11 additions & 0 deletions TagCloudGenerator/Core/Interfaces/ITagCloudGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Drawing;
using TagCloudGenerator.Core.Models;
using TagCloudGenerator.Infrastructure;

namespace TagCloudGenerator.Core.Interfaces
{
public interface ITagCloudGenerator
{
public Result<Bitmap> Generate(List<string> words, CanvasSettings canvasSettings, TextSettings textSettings, IEnumerable<IFilter> filters);
}
}
Loading