-
Notifications
You must be signed in to change notification settings - Fork 31
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
base: master
Are you sure you want to change the base?
Бабинцев Г.В. #34
Changes from all commits
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,45 @@ | ||
using TagCloud.CloudDrawer; | ||
using TagCloud.Config; | ||
using TagCloud.ReadWriter; | ||
using TagCloud.TagCloudService; | ||
|
||
namespace TagCloud.API | ||
{ | ||
public class ConsoleAPI | ||
{ | ||
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); | ||
} | ||
} | ||
} |
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)); | ||
} | ||
} | ||
} |
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); | ||
} | ||
} | ||
} |
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 = "Неизвестный алгоритм расскраски слов:"; | ||
} | ||
} |
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); | ||
} | ||
} | ||
} |
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); | ||
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. Рисователь не должен заниматься сохранением, вместо этого от него хорошо бы получать массив байтов (картинку). Которую можно сохранять, отправлять по сети, кормить в другие алгоритмы и т. п. |
||
} | ||
} |
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) | ||
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. Каждый раз пытаешь класть прямоугольник в центр. - Действие после размещения первого прямоугольника бессмысленное. На большом количестве прямоугольников работать будет плохо. |
||
{ | ||
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; | ||
} | ||
} | ||
} | ||
} |
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); | ||
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. Смешение ответственности произошло. Лэйоутеру не нужны слова, он отдает прямоугольник, и работать должен с прямоугольниками |
||
} | ||
} |
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 | ||
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. Еще про эту штуку вспомнил. Такой класс с настройками плохо. Лучше было сделать отдельные классы конфигураций для каждого сервиса. + Настройки у тебя плохо инкапсулированы. 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]; | ||
} | ||
} | ||
} |
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.
Замечание про семантику. API - это интерфейс для программ. А это у тебя UI