Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
31 changes: 31 additions & 0 deletions TagCloud/TagCloud.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34728.123
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagCloud", "TagCloud\TagCloud.csproj", "{2AF38A2D-EE49-4C1D-A38F-7B524AF31ACA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagCloudTests", "TagCloudTests\TagCloudTests.csproj", "{68CB9437-2F08-4A23-A165-ECB72F1C0E07}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2AF38A2D-EE49-4C1D-A38F-7B524AF31ACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AF38A2D-EE49-4C1D-A38F-7B524AF31ACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AF38A2D-EE49-4C1D-A38F-7B524AF31ACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AF38A2D-EE49-4C1D-A38F-7B524AF31ACA}.Release|Any CPU.Build.0 = Release|Any CPU
{68CB9437-2F08-4A23-A165-ECB72F1C0E07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68CB9437-2F08-4A23-A165-ECB72F1C0E07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68CB9437-2F08-4A23-A165-ECB72F1C0E07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68CB9437-2F08-4A23-A165-ECB72F1C0E07}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {697D441B-1F34-4177-90F6-6EB0176AF803}
EndGlobalSection
EndGlobal
27 changes: 27 additions & 0 deletions TagCloud/TagCloud/BitmapGenerators/BitmapGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Drawing;
using TagCloud.CloudLayouter;

namespace TagCloud.BitmapGenerators;

public class BitmapGenerator(ICloudLayouter layouter, BitmapGeneratorSettings settings) : IBitmapGenerator
{
public Bitmap GenerateBitmapFromWords(IEnumerable<CloudWord> words)
{
var bitmap = new Bitmap(settings.ImageSize.Width, settings.ImageSize.Height);
using var graphics = Graphics.FromImage(bitmap);

graphics.Clear(settings.Background);
var brush = new SolidBrush(settings.WordsColor);

foreach (var word in words)
{
var font = new Font(settings.FontFamily, word.FontSize);
var size = graphics.MeasureString(word.Word, font);
var position = layouter.PutNextRectangle(size.ToSize());

Choose a reason for hiding this comment

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

Кажется bitmapGenerator должен только рисовать картинку, а не генерировать размеры и позиции для прямоугольников. Предлагаю эту информацию вынести в CloudWord или в какой-нибудь DrowingCloudWord


graphics.DrawString(word.Word, font, brush, position);
}

return bitmap;
}
}
9 changes: 9 additions & 0 deletions TagCloud/TagCloud/BitmapGenerators/BitmapGeneratorSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;

namespace TagCloud.BitmapGenerators;

public record class BitmapGeneratorSettings(
Size ImageSize,
Color Background,
Color WordsColor,
FontFamily FontFamily);
3 changes: 3 additions & 0 deletions TagCloud/TagCloud/BitmapGenerators/CloudWord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace TagCloud.BitmapGenerators;

public record class CloudWord(string Word, int FontSize);
8 changes: 8 additions & 0 deletions TagCloud/TagCloud/BitmapGenerators/IBitmapGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagCloud.BitmapGenerators;

public interface IBitmapGenerator
{
public Bitmap GenerateBitmapFromWords(IEnumerable<CloudWord> words);
}
28 changes: 28 additions & 0 deletions TagCloud/TagCloud/Clients/ConsoleClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using CommandLine;

namespace TagCloud;

public class ConsoleClient : IClient
{
private readonly string[] args;

public ConsoleClient(string[] args)
{
this.args = args;
}

public SettingsManager GetSettings()
{
Parser.Default.ParseArguments<Options>(args)
.WithParsed(settings =>
{

});
return new SettingsManager(null, null, null, null);
}

public void WritePath(string path)
{
throw new NotImplementedException();
}
}
7 changes: 7 additions & 0 deletions TagCloud/TagCloud/Clients/IClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TagCloud;

public interface IClient
{
public SettingsManager GetSettings();
public void WritePath(string path);
}
9 changes: 9 additions & 0 deletions TagCloud/TagCloud/Clients/Options.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using CommandLine;

namespace TagCloud;

public class Options
{
[Value(0, Required = true, HelpText = "Path of file with words")]
public string InputPath { get; set; }
}
13 changes: 13 additions & 0 deletions TagCloud/TagCloud/CloudImageSavers/CloudImageSaver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Drawing;

namespace TagCloud.CloudImageSavers;

public class CloudImageSaver(SaveSettings settings) : ICloudImageSaver
{
public string Save(Bitmap image)
{
var filename = $"{settings.Filename}.{settings.Format.ToString().ToLower()}";
image.Save(filename);
return Path.Combine(Directory.GetCurrentDirectory(), filename);
}
}
8 changes: 8 additions & 0 deletions TagCloud/TagCloud/CloudImageSavers/ICloudImageSaver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagCloud.CloudImageSavers;

public interface ICloudImageSaver
{
public string Save(Bitmap image);

Choose a reason for hiding this comment

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

А куда сохранять? На мой взгляд это уже не столько настройки конкретной реализации, сколько правила поведения в целом

}
10 changes: 10 additions & 0 deletions TagCloud/TagCloud/CloudImageSavers/SaveSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace TagCloud.CloudImageSavers;

public record class SaveSettings(string Filename, ImageFormat Format);

public enum ImageFormat
{
PNG,
JPEG,
JPG
}
45 changes: 45 additions & 0 deletions TagCloud/TagCloud/CloudLayouter/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Drawing;
using TagCloud.CloudLayouter.PositionGenerator;

namespace TagCloud.CloudLayouter;
public class CircularCloudLayouter : ICloudLayouter
{
private List<Rectangle> rectangles;
private readonly IEnumerator<Point> pointEnumerator;

public CircularCloudLayouter(IPositionGenerator generator)
{
rectangles = new();
pointEnumerator = generator.GetPositions().GetEnumerator();
}

public List<Rectangle> GetRectangles() => rectangles;

public Rectangle PutNextRectangle(Size rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
throw new ArgumentException(
$"{nameof(rectangleSize)} должен иметь высоту и ширину больше нуля, передано ({rectangleSize.Width} {rectangleSize.Height})"
);

Rectangle rectangle;

do
rectangle = PutRectangleInNextPosition(rectangleSize);
while (rectangles.Any(r => r.IntersectsWith(rectangle)));

rectangles.Add(rectangle);
return rectangle;
}

private Rectangle PutRectangleInNextPosition(Size rectagleSize)
{
pointEnumerator.MoveNext();
var centerOfRectangle = pointEnumerator.Current;
var rectanglePosition = GetPositionFromCenter(centerOfRectangle, rectagleSize);
return new(rectanglePosition, rectagleSize);
}

private Point GetPositionFromCenter(Point center, Size size) =>
new(center.X - size.Width / 2, center.Y - size.Height / 2);
}
22 changes: 22 additions & 0 deletions TagCloud/TagCloud/CloudLayouter/CloudGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Drawing;

namespace TagCloud.CloudLayouter;

public static class CloudGenerator
{
public static ICloudLayouter GenerateRandomCloudWithCenter(Point center, int rectangleCount)
{
var random = new Random();
var layouter = new CircularCloudLayouter(
new SpiralPositionGenerator(new(0.5, 0.1, center)));

for (var i = 0; i < rectangleCount; i++)
{
var width = random.NextInt64(10, 70);
var height = random.NextInt64(10, 70);
layouter.PutNextRectangle(new((int)width, (int)height));
}

return layouter;
}
}
9 changes: 9 additions & 0 deletions TagCloud/TagCloud/CloudLayouter/ICloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;

namespace TagCloud.CloudLayouter;

public interface ICloudLayouter
{
public List<Rectangle> GetRectangles();
public Rectangle PutNextRectangle(Size rectangleSize);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagCloud.CloudLayouter;

public interface IPositionGenerator
{
public IEnumerable<Point> GetPositions();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Drawing;

namespace TagCloud.CloudLayouter.PositionGenerator;

public class SpiralGeneratorSettings
{
public double AngleOffset { get; private set; }
public double SpiralStep { get; private set; }
public Point Center { get; private set; }

public SpiralGeneratorSettings(double angleOffset, double spiralStep, Point center)
{
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(angleOffset);
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(spiralStep);

AngleOffset = angleOffset;
SpiralStep = spiralStep;
Center = center;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Drawing;
using TagCloud.CloudLayouter.PositionGenerator;

namespace TagCloud.CloudLayouter;

public class SpiralPositionGenerator : IPositionGenerator
{
private readonly SpiralGeneratorSettings settings;

public SpiralPositionGenerator(SpiralGeneratorSettings settings)
{
this.settings = settings;
}

public IEnumerable<Point> GetPositions()
{
int x, y;
double radius, angle = 0;

while (true)
{
radius = settings.SpiralStep * angle;
x = (int)(settings.Center.X + radius * Math.Cos(angle));
y = (int)(settings.Center.Y + radius * Math.Sin(angle));

yield return new(x, y);

angle += settings.AngleOffset;
}
}
}
47 changes: 47 additions & 0 deletions TagCloud/TagCloud/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using CommandLine;
using Microsoft.Extensions.DependencyInjection;
using TagCloud.BitmapGenerators;
using TagCloud.CloudImageSavers;
using TagCloud.CloudLayouter;
using TagCloud.TextFilters;
using TagCloud.TextReader;

namespace TagCloud;

public static class Program
{
public static void Main(string[] args)
{
var client = new ConsoleClient(args);
var settings = client.GetSettings();

var services = new ServiceCollection();
RegisterServices(services);
RegisterSettings(services, settings);

var provider = services.BuildServiceProvider();
var generator = provider.GetService<TagCloudImageGenerator>();
generator.GenerateCloud();
client.WritePath(generator.TagCloudPath);
}

private static void RegisterServices(IServiceCollection services)
{
services.AddSingleton<IBitmapGenerator, BitmapGenerator>();
services.AddSingleton<ICloudImageSaver, CloudImageSaver>();
services.AddSingleton<ICloudLayouter, CircularCloudLayouter>();
services.AddSingleton<IPositionGenerator, SpiralPositionGenerator>();
services.AddSingleton<ITextFilter, BoringTextFilter>();
services.AddSingleton<ITextFilter, LowercaseTextFilter>();
services.AddSingleton<ITextReader, TxtTextReader>();
services.AddSingleton<TagCloudImageGenerator>();
}

private static void RegisterSettings(IServiceCollection services, SettingsManager settings)
{
services.AddSingleton(settings.BitmapGeneratorSettings);
services.AddSingleton(settings.SaveSettings);
services.AddSingleton(settings.SpiralGeneratorSettings);
services.AddSingleton(settings.TextReaderSettings);
}
}
12 changes: 12 additions & 0 deletions TagCloud/TagCloud/SettingsManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using TagCloud.BitmapGenerators;
using TagCloud.CloudImageSavers;
using TagCloud.CloudLayouter.PositionGenerator;
using TagCloud.TextReader;

namespace TagCloud;

public record class SettingsManager(
BitmapGeneratorSettings BitmapGeneratorSettings,
SaveSettings SaveSettings,
SpiralGeneratorSettings SpiralGeneratorSettings,
TextReaderSettings TextReaderSettings);
16 changes: 16 additions & 0 deletions TagCloud/TagCloud/TagCloud.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

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

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

</Project>
Loading