-
Notifications
You must be signed in to change notification settings - Fork 303
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
Холстинин Егор #190
Open
Yrwlcm
wants to merge
16
commits into
kontur-courses:master
Choose a base branch
from
Yrwlcm:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Холстинин Егор #190
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
9edd430
Added initial TagCloudLayoter
Yrwlcm b44c2b2
Word parser
Yrwlcm 2d7478c
Now draws text instead of rectangles
Yrwlcm 98269c6
Console app with DI container
Yrwlcm b4aac5f
Refactored responsibilities and DI
Yrwlcm f0e45c9
Word parser with word formation processing
Yrwlcm 7522b53
Pallete now supports color ordering
Yrwlcm d3d0d51
Refactoring and description for options
Yrwlcm 491567f
Another algorithm
Yrwlcm d7d051b
Readme and examples
Yrwlcm 3485b50
Cleared .cjproj
Yrwlcm 8d308b8
Fixed typo
Yrwlcm 7505905
Refactored DI
Yrwlcm 4c45b2c
Refactored with TagLayoutSettings
Yrwlcm 5c8dff7
More refactoring using TagLayoutSettings
Yrwlcm b3fbaa8
Updated tests
Yrwlcm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Drawing; | ||
using System.Drawing.Imaging; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public static class BitmapExtensions | ||
{ | ||
public static void SaveImage(this Bitmap bitmap, string outputFilePath, ImageFormat imageFormat) | ||
{ | ||
outputFilePath = Path.GetFullPath(outputFilePath); | ||
var outputFileName = Path.GetFileName(outputFilePath); | ||
var outputFileDirectory = Path.GetDirectoryName(outputFilePath); | ||
|
||
Directory.CreateDirectory(outputFileDirectory); | ||
|
||
var savePath = Path.Combine(outputFileDirectory, $"{outputFileName}.{imageFormat.ToString().ToLower()}"); | ||
|
||
bitmap.Save(savePath, imageFormat); | ||
|
||
Console.WriteLine($"Image is saved to {savePath}"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace TagsCloudVisualization; | ||
|
||
public interface IDullWordChecker | ||
{ | ||
public bool Check(WordAnalysis word); | ||
} |
34 changes: 34 additions & 0 deletions
34
TagsCloudVisualization/DullCheckers/MystemDullWordChecker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Text; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class MystemDullWordChecker : IDullWordChecker | ||
{ | ||
private HashSet<string> removedPartOfSpeech; | ||
private HashSet<string> excludedWords = new(); | ||
|
||
public MystemDullWordChecker(TagLayoutSettings tagLayoutSettings) | ||
{ | ||
removedPartOfSpeech = tagLayoutSettings.RemovedPartOfSpeech; | ||
var excludedWordsFile = tagLayoutSettings.ExcludedWordsFile; | ||
if (excludedWordsFile is null) | ||
return; | ||
|
||
try | ||
{ | ||
excludedWords = | ||
new HashSet<string>(File.ReadAllText(excludedWordsFile, Encoding.UTF8).Split(Environment.NewLine)); | ||
} | ||
catch (FileNotFoundException e) | ||
{ | ||
Console.WriteLine($"Could not find specified excluded words file {excludedWordsFile}. " + | ||
$"No words will be excluded."); | ||
} | ||
} | ||
|
||
public bool Check(WordAnalysis wordAnalysis) | ||
{ | ||
return removedPartOfSpeech.Any(dullPart => wordAnalysis.GrammarAnalysis.StartsWith(dullPart)) | ||
|| excludedWords.Contains(wordAnalysis.Lexema.ToLower()); | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public interface IRectangleLayouter | ||
{ | ||
public Rectangle PutNextRectangle(Size rectangleSize); | ||
public Rectangle PutNextRectangle(SizeF rectangleSize); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System.Drawing.Imaging; | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class LayoutDrawer | ||
{ | ||
private IInterestingWordsParser interestingWordsParser; | ||
private IRectangleLayouter rectangleLayouter; | ||
private IPalette palette; | ||
private Font font; | ||
|
||
public LayoutDrawer(IInterestingWordsParser interestingWordsParser, | ||
IRectangleLayouter rectangleLayouter, | ||
IPalette palette, | ||
Font font) | ||
{ | ||
this.interestingWordsParser = interestingWordsParser; | ||
this.rectangleLayouter = rectangleLayouter; | ||
this.palette = palette; | ||
this.font = font; | ||
} | ||
|
||
public Bitmap CreateLayoutImageFromFile(string inputFilePath, | ||
Size imageSize, | ||
int minimumFontSize) | ||
{ | ||
var bitmap = new Bitmap(imageSize.Width, imageSize.Height); | ||
using var graphics = Graphics.FromImage(bitmap); | ||
|
||
inputFilePath = Path.GetFullPath(inputFilePath); | ||
|
||
var sortedWordsCount = interestingWordsParser.GetInterestingWords(inputFilePath) | ||
.GroupBy(s => s) | ||
.Select(group => new { Word = group.Key, Count = group.Count() }) | ||
.OrderByDescending(wordCount => wordCount.Count); | ||
var mostWordOccurrencies = sortedWordsCount.Max(arg => arg.Count); | ||
|
||
graphics.Clear(palette.GetBackgroundColor()); | ||
|
||
foreach (var wordCount in sortedWordsCount) | ||
{ | ||
var rectangleFont = new Font(font.FontFamily, | ||
Math.Max(font.Size * wordCount.Count / mostWordOccurrencies, minimumFontSize)); | ||
var rectangleSize = graphics.MeasureString(wordCount.Word, rectangleFont); | ||
|
||
var textRectangle = rectangleLayouter.PutNextRectangle(rectangleSize); | ||
var x = textRectangle.X + imageSize.Width / 2; | ||
var y = textRectangle.Y + imageSize.Height / 2; | ||
|
||
using var brush = new SolidBrush(palette.GetNextWordColor()); | ||
graphics.DrawString(wordCount.Word, rectangleFont, brush, x, y); | ||
} | ||
|
||
return bitmap; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public interface IPalette | ||
{ | ||
public Color GetNextWordColor(); | ||
|
||
public Color GetBackgroundColor(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class Palette : IPalette | ||
{ | ||
public Palette(Color[] textColor, Color backgroundColor) | ||
{ | ||
TextColor = textColor; | ||
BackgroundColor = backgroundColor; | ||
} | ||
|
||
private Color[] TextColor { get; set; } | ||
private int currentColorId = 0; | ||
private Color BackgroundColor { get; set; } | ||
|
||
public Color GetNextWordColor() | ||
{ | ||
if (currentColorId >= TextColor.Length) currentColorId = 0; | ||
return TextColor[currentColorId++]; | ||
} | ||
|
||
public Color GetBackgroundColor() | ||
{ | ||
return BackgroundColor; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace TagsCloudVisualization; | ||
|
||
public enum Algorithm | ||
{ | ||
Spiral, | ||
Square | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public interface IPointGenerator | ||
{ | ||
public Algorithm Name { get; } | ||
Point GetNextPoint(); | ||
} |
31 changes: 31 additions & 0 deletions
31
TagsCloudVisualization/PointGenerators/LissajousCurvePointGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class LissajousCurvePointGenerator : IPointGenerator | ||
{ | ||
private int xAmplitude = 100; | ||
private int yAmplitude = 100; | ||
private int xConstant = 19; | ||
private int yConstant = 20; | ||
private double delta = Math.PI / 2; | ||
private double parameter = 0; | ||
|
||
public Algorithm Name { get; } = Algorithm.Square; | ||
|
||
public Point GetNextPoint() | ||
{ | ||
parameter += 0.01; | ||
var x = Math.Round(xAmplitude * Math.Sin(xConstant * parameter + delta)); | ||
var y = Math.Round(yAmplitude * Math.Sin(yConstant * parameter)); | ||
|
||
if (parameter > 20) | ||
{ | ||
parameter = 0; | ||
xAmplitude += 20; | ||
yAmplitude += 20; | ||
} | ||
|
||
return new Point((int)x, (int)y); | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
TagsCloudVisualization/PointGenerators/SpiralPointGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class SpiralPointGenerator : IPointGenerator | ||
{ | ||
public Point Center { get; } = new(0, 0); | ||
public int Radius { get; private set; } | ||
public double Angle { get; private set; } | ||
public int RadiusDelta { get; private set; } = 1; | ||
public double AngleDelta { get; private set; } = Math.PI / 60; | ||
|
||
public Algorithm Name { get; } = Algorithm.Spiral; | ||
|
||
public Point GetNextPoint() | ||
{ | ||
var x = (int)Math.Round(Center.X + Radius * Math.Cos(Angle)); | ||
var y = (int)Math.Round(Center.Y + Radius * Math.Sin(Angle)); | ||
|
||
var nextAngle = Angle + AngleDelta; | ||
var angleMoreThan2Pi = Math.Abs(nextAngle) >= Math.PI * 2; | ||
|
||
Radius = angleMoreThan2Pi ? Radius + RadiusDelta : Radius; | ||
Angle = angleMoreThan2Pi ? 0 : nextAngle; | ||
|
||
return new Point(x, y); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
using System.ComponentModel.DataAnnotations; | ||
using System.Drawing; | ||
using System.Drawing.Imaging; | ||
using McMaster.Extensions.CommandLineUtils; | ||
using Microsoft.Extensions.DependencyInjection; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public class Program | ||
{ | ||
public static int Main(string[] args) => CommandLineApplication.Execute<Program>(args); | ||
|
||
[Argument(0, Description = "Path to txt file with words")] | ||
[Required(ErrorMessage = "Expected to get path to file with words as first positional argument." + | ||
"\nExample: C:\\PathTo\\File.txt\nOr relative to exe: PathTo\\File.txt")] | ||
public string InputFilePath { get; set; } | ||
|
||
[Argument(1, Description = "Path to output file")] | ||
[Required(ErrorMessage = "Expected to get output file path as second positional argument." + | ||
"\nExample: C:\\PathTo\\File\nOr relative to exe: PathTo\\File")] | ||
public string OutputFilePath { get; set; } | ||
|
||
[Option("-w", Description = "Image width in pixels")] | ||
private int ImageWidth { get; set; } = 1000; | ||
|
||
[Option("-h", Description = "Image height in pixels")] | ||
private int ImageHeight { get; set; } = 1000; | ||
|
||
[Option("-bc", Description = "Image background color from KnownColor enum")] | ||
private Color BackgroundColor { get; set; } = Color.Wheat; | ||
|
||
[Option("-tc", Description = "Image words colors sequence array from KnownColor enum. " + | ||
"Can be set multiple times for sequence. Example: -tc black -tc white")] | ||
private Color[] TextColor { get; set; } = { Color.Black }; | ||
|
||
[Option("-ff", Description = "Font used for words")] | ||
private string FontFamily { get; set; } = "Arial"; | ||
|
||
[Option("-fs", Description = "Max font size in em")] | ||
private int FontSize { get; set; } = 50; | ||
|
||
[Option("-mfs", Description = "Min font size in em")] | ||
private int MinimalFontSize { get; set; } = 0; | ||
|
||
[Option("-img", Description = "Output image format. Choosen from ImageFormat")] | ||
private ImageFormat SaveImageFormat { get; set; } = ImageFormat.Png; | ||
|
||
[Option("-ef", Description = "Txt file with words to exclude. 1 word in line. Words must be lexems.")] | ||
private string ExcludedWordsFile { get; set; } | ||
|
||
[Option("-rp", Description = "Parts of speech abbreviations that are excluded from parsed words. " + | ||
"More info here https://yandex.ru/dev/mystem/doc/ru/grammemes-values")] | ||
private HashSet<string> RemovedPartsOfSpeech { get; set; } = new() | ||
{ "ADVPRO", "APRO", "INTJ", "CONJ", "PART", "PR", "SPRO" }; | ||
|
||
[Option("-alg", Description = "Choose algorithm to generate tag cloud. Available: Spiral, Square")] | ||
private Algorithm Algorithm { get; set; } = Algorithm.Spiral; | ||
|
||
|
||
private void OnExecute() | ||
{ | ||
var services = new ServiceCollection(); | ||
services.AddSingleton(new TagLayoutSettings(Algorithm, RemovedPartsOfSpeech, ExcludedWordsFile)); | ||
services.AddScoped<Font>(x => new Font(FontFamily, FontSize)); | ||
services.AddScoped<IPalette>(x => new Palette(TextColor, BackgroundColor)); | ||
services.AddScoped<IPointGenerator, LissajousCurvePointGenerator>(); | ||
services.AddScoped<IPointGenerator, SpiralPointGenerator>(); | ||
services.AddScoped<IDullWordChecker, MystemDullWordChecker>(); | ||
services.AddScoped<IInterestingWordsParser, MystemWordsParser>(); | ||
services.AddScoped<IRectangleLayouter, RectangleLayouter>(); | ||
services.AddScoped<LayoutDrawer>(); | ||
|
||
using var provider = services.BuildServiceProvider(); | ||
|
||
var layoutDrawer = provider.GetRequiredService<LayoutDrawer>(); | ||
try | ||
{ | ||
layoutDrawer | ||
.CreateLayoutImageFromFile(InputFilePath, new Size(ImageWidth, ImageHeight), MinimalFontSize) | ||
.SaveImage(OutputFilePath, SaveImageFormat); | ||
} | ||
Comment on lines
+77
to
+81
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. Не уверен насколько сейчас рационально выносить эти поля в TagLayoutSettings, так как сейчас мы не прячем ничего внутрь метода |
||
catch (Exception ex) | ||
{ | ||
if (ex is FileNotFoundException or DirectoryNotFoundException) | ||
{ | ||
Console.WriteLine(ex.Message); | ||
if (!Path.IsPathRooted(InputFilePath)) | ||
Console.WriteLine("Relative paths are searched realative to .exe file. " + | ||
"Try giving an absolute path."); | ||
} | ||
else | ||
{ | ||
throw; | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Сейчас почти все сервисы добавлены синглтоном. Вопрос - почему?)
По умолчанию, нужно начинать с самого маленького скоупа, понимать, подходит ли он, если нет, подумать над большим скоупом, пока не станет ясно, какой подходит. А здесь ситуация обратная - решили сразу поставить максимальный скоуп, хотя каких-то предпосылок я здесь не вижу. Это как по умолчанию все переменные делать глобальными.