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

Алешев Руслан #188

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
17a5d9f
init: начальная структура программы
Jan 22, 2024
22e56ab
feat: impliment basic text cloud layouting
Jan 23, 2024
271ef7f
feat: Добавлены тесты
Jan 24, 2024
77fb65f
feat: добавлена фильтрация слов
Jan 24, 2024
3d91d03
feat: добавлен интерфейс командной строки
Jan 25, 2024
af7d57d
fix: исправлен CloudBuilderTests
Jan 25, 2024
03e1d52
refactor: Изменен обработчик аргументов командной строки
Jan 27, 2024
9b16fc0
init: добавлен пустой проект для GUI
Jan 28, 2024
7a8a6b9
refactor: исправлен FrequencyAnalyzer
Jan 28, 2024
6601ff9
refactor: TextPreprocessing fixing
Jan 28, 2024
0f53408
fix: добавлены DI для классов
Jan 28, 2024
b1d2d86
feat: создание изображения вынесено из TagsCloudLayouter в класс Visu…
Jan 29, 2024
8655a10
feat: добавлен маппер цветов
Jan 29, 2024
74c589a
refactor: удалил пустые конструкторы
Jan 29, 2024
aab825f
feat: Добавлен NormalPointsProvider реализующий интерфейс IPointsProv…
Jan 30, 2024
7e628a2
fix: исправлена ошибка в TagsCloudLayouter
Jan 30, 2024
28f5212
init: добавлен проект приложения WinForms
Jan 30, 2024
c8cda5f
feat: настроен GUI
Jan 30, 2024
fccf8bf
feat: автоматическое сохранение и загрузка настроек в GUI
Jan 30, 2024
dda89b9
test: добавлены тесты
Jan 30, 2024
6373fa9
feat: добавлена настройка цвета фона в консольном приложении
Jan 31, 2024
7b562a2
feat: добавлена настройка цвета фона в GUI
Feb 1, 2024
6d2c3c2
init: создана заготовка класса Result и тестов
Feb 4, 2024
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
1 change: 1 addition & 0 deletions ResutlTests/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using NUnit.Framework;
20 changes: 20 additions & 0 deletions ResutlTests/ResutlTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions ResutlTests/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace ResutlTests
{
public class Tests
{
[SetUp]
public void Setup()
{
}

[Test]
public void Test1()
{
Assert.Pass();
}
}
}
147 changes: 147 additions & 0 deletions TagsCloudContainer/CLI/CommandLineOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
using CommandLine;
using System.Drawing;
using TagsCloudContainer.SettingsClasses;
using TagsCloudContainer.TagCloudBuilder;
using TagsCloudVisualization;

namespace TagsCloudContainer.CLI
{
class CommandLineOptions
{
[Option('f', "filename", Required = true, HelpText = "Input file name.")]
public string Filename { get; set; }

[Option('o', "output", Required = true, HelpText = "Output file name.")]
public string Output { get; set; }

[Option("font", Required = false, HelpText = "Set the font family name.")]
public string FontFamily { get; set; }

[Option("fontsize", Required = false, HelpText = "Set the font size. Must be a positive integer.")]
public int FontSize { get; set; }

[Option("colors", Required = false, HelpText = "List of color names. Separated by commas.")]
public string Colors { get; set; }

[Option("size", Required = false, HelpText = "Set the image size. Must be two positive integer.")]
public Size Size { get; set; }

[Option("exclude", Required = false, HelpText = "File with words to exclude.")]
public string Filter { get; set; }

[Option("layout", Required = false, HelpText = "Set cloud layouter - Spiral, Random or Normal.")]
public string Layout { get; set; }

[Option("background", Required = false, HelpText = "Set background color.")]
public string BgColor { get; set; }

public static AppSettings ParseArgs(CommandLineOptions options)
{
var appSettings = new AppSettings();
appSettings.DrawingSettings = new();

appSettings.TextFile = options.Filename;
appSettings.OutImagePath = options.Output;
appSettings.FilterFile = options.Filter;

appSettings.DrawingSettings.FontFamily = GetFontFamily(options.FontFamily);
appSettings.DrawingSettings.FontSize = GetFontSize(options.FontSize);
appSettings.DrawingSettings.Size = GetSize(options.Size);
appSettings.DrawingSettings.Colors = GetColors(options.Colors);
appSettings.DrawingSettings.PointsProvider = GetPointsProvider(
options.Layout,
appSettings.DrawingSettings.Size);
appSettings.DrawingSettings.BgColor = GetBGColor(options.BgColor);

return appSettings;
}

private static int GetFontSize(int fontSize)
{
if (fontSize > 0)
{
return fontSize;
}
return 12;
}

private static Size GetSize(Size size)
{
if (size.IsEmpty)
{
return new Size(800, 600);
}
return size;
}

private static IPointsProvider GetPointsProvider(string layout, Size size)
{
var center = new Point(size.Width / 2, size.Height / 2);
IPointsProvider pointProvider = new SpiralPointsProvider();

if (string.IsNullOrEmpty(layout))
{
pointProvider.Initialize(center);
return pointProvider;
}

switch (layout.ToLowerInvariant())
{
case "random":
pointProvider = new RandomPointsProvider();
break;

case "normal":
pointProvider = new NormalPointsProvider();
break;

case "spiral":
pointProvider = new NormalPointsProvider();
break;

default:
pointProvider = new SpiralPointsProvider();
break;
}

pointProvider.Initialize(center);
return pointProvider;
}

private static FontFamily GetFontFamily(string fontName)
{
try
{
var fontFamily = new FontFamily(fontName);
return fontFamily;
}
catch (ArgumentException)
{
Console.WriteLine("Font {0} not found. Using default font.", fontName);
return new FontFamily("Arial");
}
}

private static IList<Color> GetColors(string colors)
{
if (string.IsNullOrEmpty(colors))
{
return new List<Color>() { Color.White };
}

var c = colors.Split(',').Select(x => Color.FromName(x)).ToList();

if (c.Count > 0)
{
return c.ToList();
}

return new List<Color>() { Color.White };
}

private static Color GetBGColor(string colorName)
{
return Color.FromName(colorName);
}
}
}
36 changes: 36 additions & 0 deletions TagsCloudContainer/ColorMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Drawing;

namespace TagsCloudContainer
{
public class ColorMapper
{
public static Dictionary<int, Color> MapColors(IEnumerable<int> numbers, IList<Color> colors)
{
var distinctNumbers = numbers.Distinct().OrderByDescending(x => x);
var colorMapping = new Dictionary<int, Color>();

if (!distinctNumbers.Any() || !colors.Any())
{
return colorMapping;
}

int partitionSize = distinctNumbers.Count() / colors.Count;

int i = 0;
int j = 0;

foreach (var number in distinctNumbers)
{
colorMapping[number] = colors[j];
if (i >= partitionSize)
{
i = 0;
j = Math.Min(colors.Count - 1, j + 1);
}
i++;
}

return colorMapping;
}
}
}
25 changes: 25 additions & 0 deletions TagsCloudContainer/DependencyInjectionConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.Extensions.DependencyInjection;
using TagsCloudContainer.FrequencyAnalyzers;
using TagsCloudContainer.SettingsClasses;
using TagsCloudContainer.TagCloudBuilder;
using TagsCloudContainer.TextTools;
using TagsCloudVisualization;

namespace TagsCloudContainer
{
public class DependencyInjectionConfig
{
public static IServiceCollection AddCustomServices(IServiceCollection services)
{
services.AddSingleton<ITextReader, TextFileReader>();
services.AddSingleton<IAnalyzer, FrequencyAnalyzer>();
services.AddTransient<IPointsProvider, SpiralPointsProvider>();
services.AddTransient<IPointsProvider, RandomPointsProvider>();
services.AddTransient<IPointsProvider, NormalPointsProvider>();
services.AddTransient<TagsCloudLayouter>();
services.AddTransient<CloudDrawingSettings>();

return services;
}
}
}
34 changes: 34 additions & 0 deletions TagsCloudContainer/FrequencyAnalyzers/FrequencyAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace TagsCloudContainer.FrequencyAnalyzers
{
public class FrequencyAnalyzer : IAnalyzer
{
private readonly Dictionary<string, int> wordFrequency;

public FrequencyAnalyzer()
{
wordFrequency = new Dictionary<string, int>();
}

public void Analyze(string text, string exclude = "")
{
var preprocessor = new TextPreprocessing(exclude);

foreach (var word in preprocessor.Preprocess(text))
{
if (wordFrequency.ContainsKey(word.ToLower()))
{
wordFrequency[word]++;
}
else
{
wordFrequency.Add(word, 1);
}
}
}

public IEnumerable<(string, int)> GetAnalyzedText()
{
return wordFrequency.Select(p => (p.Key, p.Value));
}
}
}
8 changes: 8 additions & 0 deletions TagsCloudContainer/FrequencyAnalyzers/IAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TagsCloudContainer.FrequencyAnalyzers
{
public interface IAnalyzer
{
public void Analyze(string text, string exclude = "");
public IEnumerable<(string, int)> GetAnalyzedText();
}
}
30 changes: 30 additions & 0 deletions TagsCloudContainer/FrequencyAnalyzers/TextPreprocessing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace TagsCloudContainer.FrequencyAnalyzers
{
public class TextPreprocessing
{
private readonly HashSet<string> excludedWords = new();

public TextPreprocessing(string excludedWordsPath)
{
if (!File.Exists(excludedWordsPath))
{
return;
}

var reader = new StreamReader(excludedWordsPath);
excludedWords = reader.ReadToEnd()
.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToHashSet();
}

public IEnumerable<string> Preprocess(string text)
{
var words = text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.ToLower());
foreach (var word in words)
{
if (!excludedWords.Contains(word))
yield return word;
}
}
}
}
41 changes: 41 additions & 0 deletions TagsCloudContainer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using CommandLine;
using Microsoft.Extensions.DependencyInjection;
using TagsCloudContainer.CLI;
using TagsCloudContainer.Drawer;
using TagsCloudContainer.FrequencyAnalyzers;
using TagsCloudContainer.SettingsClasses;
using TagsCloudContainer.TextTools;
using TagsCloudVisualization;

namespace TagsCloudContainer
{
public static class Program
{
public static void Main(string[] args)
{
var services = DependencyInjectionConfig.AddCustomServices(new ServiceCollection());
var serviceProvider = services.BuildServiceProvider();

var reader = serviceProvider.GetService<ITextReader>();
var analyzer = serviceProvider.GetService<IAnalyzer>();

var appSettings = new AppSettings();

Parser.Default.ParseArguments<CommandLineOptions>(args)
.WithParsed(o => appSettings = CommandLineOptions.ParseArgs(o));

var text = reader.ReadText(appSettings.TextFile);
var layouter = serviceProvider.GetService<TagsCloudLayouter>();

analyzer.Analyze(text, appSettings.FilterFile);

layouter.Initialize(appSettings.DrawingSettings, analyzer.GetAnalyzedText());

Visualizer.Draw(appSettings.DrawingSettings.Size,
layouter.GetTextImages(),
appSettings.DrawingSettings.BgColor)
.Save(appSettings.OutImagePath);
Console.WriteLine("Resulting image saved to " + appSettings.OutImagePath);
}
}
}
8 changes: 8 additions & 0 deletions TagsCloudContainer/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"profiles": {
"TagsCloudContainer": {
"commandName": "Project",
"commandLineArgs": "-f sample.txt -o testout.png --exclude excludedWords.txt --font Calibri --colors Gold,Pink,LightGoldenrodYellow --layout SpiralPointsProvider --fontsize 12 --size 500,500 --background Blue"
}
}
}
Loading