-
Notifications
You must be signed in to change notification settings - Fork 240
Савицких Антон #210
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
base: master
Are you sure you want to change the base?
Савицких Антон #210
Changes from 3 commits
eed1d8a
bda3418
0a21c47
52f7aed
57591ca
a1fdfe0
0ba2794
db85b57
a28b2b6
ca24a76
264f1a5
8a4bf9b
239700a
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,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; | ||
|
|
||
| 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; | ||
|
||
|
|
||
| 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")) | ||
|
||
| .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; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| 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; } | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } | ||
| } |
| 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> |
| 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 | ||
|
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. Здесь тоже переход на Result нужен
Author
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. Обновил |
||
| { | ||
| 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) | ||
|
||
| { | ||
| 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; | ||
| } | ||
| } | ||
| } | ||
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
| 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(); | ||
| } | ||
| } |
| 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); | ||
| } | ||
| } |
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.
Лишние using. В других местах тоже проверь
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.
Проверил, постарался убрать все лишние