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

Бабинцев Г.В. #34

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
45 changes: 45 additions & 0 deletions TagCloud/API/ConsoleAPI.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using TagCloud.CloudDrawer;
using TagCloud.Config;
using TagCloud.ReadWriter;
using TagCloud.TagCloudService;

namespace TagCloud.API
{
public class ConsoleAPI

Choose a reason for hiding this comment

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

Замечание про семантику. API - это интерфейс для программ. А это у тебя UI

{
private readonly IReadWriter readWriter;
private readonly ICloudDrawer drawer;
private readonly ITagCloudService tagCloudService;

private AppConfig appConfig;

public ConsoleAPI(IReadWriter reader, ICloudDrawer drawer, ITagCloudService tagCloudService, AppConfig appConfig)
{
this.readWriter = reader;
this.drawer = drawer;
this.tagCloudService = tagCloudService;

this.appConfig = appConfig;
}

public void Start()
{
var wordsPath = readWriter.ReadLine(Messages.BeforeWordsDataInput, Messages.FileNotFound, Handlers.GetPath);
var boringPath = readWriter.ReadLine(Messages.BeforeBoringWordsDataInput, Messages.FileNotFound, Handlers.GetPath);

var set = readWriter.ReadLine(Messages.UseDefaultConfig, Messages.BadFormat,
x => (HandlersConfig.SetAppConfig.TryGetValue(x, out var set), set));

set(appConfig, readWriter);

var wordsData = readWriter.ReadDataFromFile(wordsPath);
var boringWordsData = readWriter.ReadDataFromFile(boringPath);

var words = tagCloudService.GetWordTags(wordsData, boringWordsData);

drawer.DrawWordsAndSave(words);

readWriter.WriteLine(Messages.Success);
}
}
}
29 changes: 29 additions & 0 deletions TagCloud/API/Handlers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Drawing;

namespace TagCloud.API
{
public static class Handlers
{
public static (bool, int) ParseInt(string input) => (int.TryParse(input, out var converted), converted);

public static (bool, float) ParseFloat(string input) => (float.TryParse(input, out var converted), converted);

public static (bool, string) GetPath(string input) => (File.Exists(input), input);

public static (bool, Color) GetColorFromName(string input)
{
var color = Color.FromName(input);
return (color.IsKnownColor, color);
}

public static (bool, string) GetFontFamilyName(string input) => (FontFamily.Families.Any(x => x.Name == input), input);

public static (bool, TEnum) ParseEnum<TEnum>(string input)
{
if (Enum.TryParse(typeof(TEnum), input, true, out var enumValue))
return (true, (TEnum)enumValue);

return (false, default(TEnum));
}
}
}
81 changes: 81 additions & 0 deletions TagCloud/API/HandlersConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Drawing;
using TagCloud.Config;
using TagCloud.ReadWriter;
using TagCloud.Models;

namespace TagCloud.API
{
public static class HandlersConfig
{
public static Dictionary<string, Action<AppConfig, IReadWriter>> SetAppConfig
{
get
{
return new Dictionary<string, Action<AppConfig, IReadWriter>>()
{
{ "Да", SetDefaultConfig },
{ "Нет", SetCustomConfig },
};
}
}

private static void SetDefaultConfig(AppConfig config, IReadWriter _)
{
config.CloudLayouterConfig = DefaultConfigs.DefaultCloudLayouterConfig;
config.FontConfig = DefaultConfigs.DefaultFontConfig;
config.ImageConfig = DefaultConfigs.DefaultImageConfig;
}

private static void SetCustomConfig(AppConfig config, IReadWriter readWriter)
{
config.CloudLayouterConfig = GetCustomCloudLayouterConfig(readWriter);
config.FontConfig = GetCustomFontConfig(readWriter);
config.ImageConfig = GetCustomImageConfig(readWriter);
}

private static ImageConfig GetCustomImageConfig(IReadWriter readWriter)
{
var width = readWriter.ReadLine(Messages.BeforeWidthInput, Messages.BadFormat, Handlers.ParseInt);

var height = readWriter.ReadLine(Messages.BeforeHeightInput, Messages.BadFormat, Handlers.ParseInt);

var background = readWriter.ReadLine(Messages.BeforeBackgroundInput, Messages.UnknownColor, Handlers.GetColorFromName);

var countColors = readWriter.ReadLine(Messages.CountWordsColors, Messages.BadFormat, Handlers.ParseInt);

var wordsColors = new Color[countColors];
for (int i = 0; i< countColors; i++)
wordsColors[i] = readWriter.ReadLine(Messages.BeforeColorInput, Messages.UnknownColor, Handlers.GetColorFromName);

var colorScheme = readWriter.ReadLine(Messages.ColorSchemeInput, Messages.UnknownColorScheme, Handlers.ParseEnum<ColorScheme>);

return new ImageConfig(width, height, background, wordsColors, colorScheme);
}

private static FontConfig GetCustomFontConfig(IReadWriter readWriter)
{
var fontFamily = readWriter.ReadLine(Messages.FontFamilyName, Messages.UnknownFontFamilyName, Handlers.GetFontFamilyName);

var fontSize = readWriter.ReadLine(Messages.FontSize, Messages.BadFormat, Handlers.ParseFloat);

var fontStyle = readWriter.ReadLine(Messages.FontStyle, Messages.UnknownFontStyle, Handlers.ParseEnum<FontStyle>);

var increase = readWriter.ReadLine(Messages.FontIncrease, Messages.BadFormat, Handlers.ParseInt);

return new FontConfig(fontFamily, fontSize, fontStyle, increase);
}

private static CloudLayouterConfig GetCustomCloudLayouterConfig(IReadWriter readWriter)
{
var radius = readWriter.ReadLine(Messages.BeforeRadiusInput, Messages.BadFormat, Handlers.ParseInt);

var deltaRadius = readWriter.ReadLine(Messages.BeforeRadiusDeltaInput, Messages.BadFormat, Handlers.ParseInt);

var angle = readWriter.ReadLine(Messages.BeforeAngleInput, Messages.BadFormat, Handlers.ParseInt);

var deltaAngle = readWriter.ReadLine(Messages.BeforeAngleDeltaInput, Messages.BadFormat, Handlers.ParseInt);

return new CloudLayouterConfig(radius, deltaRadius, angle, deltaAngle);
}
}
}
55 changes: 55 additions & 0 deletions TagCloud/API/Messages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace TagCloud.API
{
public static class Messages
{
public const string FileNotFound = "Файл не найден.";

public const string BeforeWordsDataInput = "Введите путь до файла со словами облака:";

public const string BeforeBoringWordsDataInput = "Введите путь до файла со скучными словами:";

public const string BeforeWidthInput = "Введите ширину изображения:";

public const string BeforeHeightInput = "Введите высоту изображения:";

public const string UseDefaultConfig = "Использовать стандартные настройки? [Да/Нет]";

public const string BadFormat = "Неправильный формат ввода.";

public const string BeforeBackgroundInput = "Введите цвет заднего фона:";

public const string BeforeColorInput = "Введите цвет:";

public const string UnknownColor = "Неизвестный цвет";

public const string CountWordsColors = "Введите кол-во цветов для слов:";

public const string FontFamilyName = "Введите название семейства шрифтов:";

public const string UnknownFontFamilyName = "Неизвестный шрифт";

public const string FontStyle = "Введите стиль шрифта:";

public const string UnknownFontStyle = "Неизвестный стиль шрифта";

public const string FontIncrease = "Введите увеличение размера шрифта:";

public const string FontSize = "Введите размер шрифта:";

public const string Filename = "result.png";

public const string Success = $"Файл {Filename} успешно сохранен!";

public const string BeforeRadiusInput = "Введите радиус для облака тегов:";

public const string BeforeRadiusDeltaInput = "Введите изменение радиуса для облака тегов:";

public const string BeforeAngleInput = "Введите угол для облака тегов:";

public const string BeforeAngleDeltaInput = "Введите изменение угла для облака тегов:";

public const string ColorSchemeInput = "Введите алгоритм расскраски слов:";

public const string UnknownColorScheme = "Неизвестный алгоритм расскраски слов:";
}
}
39 changes: 39 additions & 0 deletions TagCloud/CloudDrawer/CloudDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Drawing;
using TagCloud.API;
using TagCloud.Config;
using TagCloud.Models;

namespace TagCloud.CloudDrawer
{
public class CloudDrawer : ICloudDrawer
{
private readonly AppConfig appConfig;

public CloudDrawer(AppConfig appConfig)
{
this.appConfig = appConfig;
}

public void DrawWordsAndSave(IEnumerable<WordTag> words)
{
var imageConfig = appConfig.ImageConfig;

var bitmap = new Bitmap(imageConfig.Width, imageConfig.Height);

var graphics = Graphics.FromImage(bitmap);

graphics.Clear(imageConfig.Background);

var index = 0;

foreach (var word in words)
{
var brush = new SolidBrush(imageConfig.WordColors[index % imageConfig.WordColors.Length]);
graphics.DrawString(word.Content, word.Font, brush, word.Rectangle);
index++;
}

bitmap.Save(Messages.Filename);
}
}
}
10 changes: 10 additions & 0 deletions TagCloud/CloudDrawer/ICloudDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Drawing;
using TagCloud.Models;

namespace TagCloud.CloudDrawer
{
public interface ICloudDrawer
{
void DrawWordsAndSave(IEnumerable<WordTag> words);

Choose a reason for hiding this comment

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

Рисователь не должен заниматься сохранением, вместо этого от него хорошо бы получать массив байтов (картинку). Которую можно сохранять, отправлять по сети, кормить в другие алгоритмы и т. п.

}
}
51 changes: 51 additions & 0 deletions TagCloud/CloudLayouter/CircularCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Drawing;
using TagCloud.Config;
using TagCloud.Models;

namespace TagCloud.CircularCloudLayouter
{
public class CircularCloudLayouter :ICloudLayouter
{
private AppConfig appConfig;

public CircularCloudLayouter(AppConfig appConfig)
{
this.appConfig = appConfig;
}

public RectangleF GetPossibleNextRectangle(IEnumerable<WordTag> cloudRectangles, SizeF rectangleSize)
{
if (rectangleSize.Width <= 0 || rectangleSize.Height <= 0)
throw new ArgumentException("the width and height of the rectangle must be positive numbers");

return FindPossibleNextRectangle(cloudRectangles, rectangleSize);
}

private RectangleF FindPossibleNextRectangle(IEnumerable<WordTag> cloudRectangles, SizeF rectangleSize)

Choose a reason for hiding this comment

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

Каждый раз пытаешь класть прямоугольник в центр. - Действие после размещения первого прямоугольника бессмысленное. На большом количестве прямоугольников работать будет плохо.

{
var cloudLayouterConfig = appConfig.CloudLayouterConfig;
var imageConfig = appConfig.ImageConfig;

var center = new Point(imageConfig.Width / 2, imageConfig.Height / 2);

var radius = cloudLayouterConfig.Radius;
var angle = cloudLayouterConfig.Angle;

while (true)
{
var point = new Point(
(int)(center.X + radius * Math.Cos(angle)),
(int)(center.Y + radius * Math.Sin(angle))
);

var possibleRectangle = new RectangleF(point, rectangleSize);

if (!cloudRectangles.Any(textRectangle => textRectangle.Rectangle.IntersectsWith(possibleRectangle)))
return possibleRectangle;

angle += cloudLayouterConfig.DeltaAngle;
radius += cloudLayouterConfig.DeltaRadius;
}
}
}
}
10 changes: 10 additions & 0 deletions TagCloud/CloudLayouter/ICloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Drawing;
using TagCloud.Models;

namespace TagCloud.CircularCloudLayouter
{
public interface ICloudLayouter
{
RectangleF GetPossibleNextRectangle(IEnumerable<WordTag> cloudRectangles, SizeF rectangleSize);

Choose a reason for hiding this comment

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

Смешение ответственности произошло. Лэйоутеру не нужны слова, он отдает прямоугольник, и работать должен с прямоугольниками

}
}
54 changes: 54 additions & 0 deletions TagCloud/Config/AppConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Drawing;
using TagCloud.Models;

namespace TagCloud.Config
{
public class AppConfig

Choose a reason for hiding this comment

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

Еще про эту штуку вспомнил. Такой класс с настройками плохо. Лучше было сделать отдельные классы конфигураций для каждого сервиса. + Настройки у тебя плохо инкапсулированы. Setter-ы надо делать приватными (или заменять на init)

{
public CloudLayouterConfig CloudLayouterConfig { get; set; }

public FontConfig FontConfig { get; set; }

public ImageConfig ImageConfig { get; set; }

private Dictionary<ColorScheme, Func<Color>> ColorSchemas;

private Random rnd;

private int index;

public AppConfig()
{
CloudLayouterConfig = DefaultConfigs.DefaultCloudLayouterConfig;

FontConfig = DefaultConfigs.DefaultFontConfig;

ImageConfig = DefaultConfigs.DefaultImageConfig;

rnd = new Random();
index = -1;

ColorSchemas = new Dictionary<ColorScheme, Func<Color>>
{
{ColorScheme.Random, ColorSchemeRandom},
{ColorScheme.RoundRobin, ColorSchemeRoundRobin},
};
}

public Color GetNextColor() => ColorSchemas[ImageConfig.ColorScheme]();

private Color ColorSchemeRandom()
{
var index = rnd.Next(0, ImageConfig.WordColors.Length);

return ImageConfig.WordColors[index];
}

private Color ColorSchemeRoundRobin()
{
index = (index + 1) % ImageConfig.WordColors.Length;

return ImageConfig.WordColors[index];
}
}
}
Loading