-
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
Конина Анастасия #205
base: master
Are you sure you want to change the base?
Конина Анастасия #205
Changes from 1 commit
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,6 @@ | ||
namespace TagCloud; | ||
|
||
public interface IWordsForCloudGenerator | ||
{ | ||
List<WordForCloud> Generate(List<string> words); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace TagCloud; | ||
|
||
public interface IWordsNormalizer | ||
{ | ||
List<string> NormalizeWords(List<string> words); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System.Collections.Generic; | ||
using System.Drawing; | ||
using System.IO; | ||
using System.Linq; | ||
using TagsCloudVisualization; | ||
|
||
namespace TagCloud | ||
{ | ||
internal class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
var inputFile = "1.txt"; | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
var outputFile = "qwe.bmp"; | ||
|
||
var wordNormalizer = new WordsNormalizer(); | ||
var wordForCloudGenerator = new WordsForCloudGenerator("Arial", Color.Black, 60); | ||
var pictureSize = new Size(1000, 1000); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
var circularCloudLayouter = | ||
new CircularCloudLayouter(new SpiralPoints(new Point(pictureSize.Height / 2, pictureSize.Width / 2))); | ||
|
||
|
||
var words = GetWordsFromFile(inputFile); | ||
var normalizeWords = wordNormalizer.NormalizeWords(words); | ||
var wordsForCloud = wordForCloudGenerator.Generate(normalizeWords); | ||
|
||
|
||
DrawAndSaveCloud( | ||
wordsForCloud.Select(word => circularCloudLayouter.PutNextRectangle(word.WordSize)).ToList(), | ||
wordsForCloud, outputFile, pictureSize); | ||
} | ||
|
||
private static List<string> GetWordsFromFile(string path) | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
using (var fileStream = new StreamReader(path)) | ||
{ | ||
return fileStream.ReadToEnd().Split('\n').ToList(); | ||
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. Из базовых требований:
Сомневаюсь, что эта штука это учитывает |
||
} | ||
} | ||
|
||
private static void DrawAndSaveCloud(List<Rectangle> rectangles, List<WordForCloud> wordsForCloud, | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
string fileName, | ||
Size pictureSize) | ||
{ | ||
var bitmap = new Bitmap(pictureSize.Width, pictureSize.Height); | ||
var gr = Graphics.FromImage(bitmap); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
gr.FillRectangle(Brushes.White, 0, 0, pictureSize.Width, pictureSize.Height); | ||
for (var i = 0; i < rectangles.Count; i++) | ||
{ | ||
gr.DrawString($"{wordsForCloud[i].Word}", wordsForCloud[i].Font, | ||
new SolidBrush(wordsForCloud[i].WordColor), rectangles[i]); | ||
} | ||
|
||
bitmap.Save(fileName); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<GenerateProgramFile>false</GenerateProgramFile> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\TagsCloudVisualization\TagsCloudVisualization.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Drawing; | ||
|
||
namespace TagCloud; | ||
|
||
public class WordForCloud | ||
{ | ||
public Font Font { get; } | ||
public int FontSize { get; } | ||
public Size WordSize { get; } | ||
|
||
public string Word { get; } | ||
public Color WordColor { get; } | ||
|
||
public WordForCloud(string font, int fontSize, string word, Size wordSize, Color wordColor) | ||
{ | ||
Font = new Font(font, fontSize); | ||
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. Font - IDisposable Помимо этого название класса поменял бы, если у нас облако тэгов, можно назвать просто Tag 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. Проигноренный коммент |
||
FontSize = fontSize; | ||
WordSize = wordSize; | ||
WordColor = wordColor; | ||
Word = word; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System.Drawing; | ||
|
||
namespace TagCloud; | ||
|
||
public class WordsForCloudGenerator: IWordsForCloudGenerator | ||
{ | ||
private readonly string fontName; | ||
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. Такие параметры будто бы просятся унестись в какой-то класс настроечек для конкретной абстракции Это норм тема, когда двестиписят параметров инкапсулируют в класс и приносят одной моделькой 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. Проигнорированный коммент |
||
private readonly Color fontColor; | ||
private readonly int maxFontSize; | ||
|
||
|
||
public WordsForCloudGenerator(string fontName, Color color, int maxFontSize) | ||
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. Так уж TagGenerator, но это тоже неправда 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. Проигнорированный коммент |
||
{ | ||
this.fontName = fontName; | ||
this.maxFontSize = maxFontSize; | ||
fontColor = color; | ||
} | ||
|
||
public List<WordForCloud> Generate(List<string> words) | ||
{ | ||
var wordFrequency = GetWordsFrequency(words) | ||
.OrderBy(x => x.Value) | ||
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. Интересная логика, отсортировать по возрастанию и зареверсить, почему бы не делать это в один проход - отсортировать по убыванию? 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. Проигнорированный коммент |
||
.Reverse() | ||
.ToList(); | ||
|
||
var maxFrequency = wordFrequency.FirstOrDefault().Value; | ||
return wordFrequency | ||
.Select(x => | ||
GetWordForCloud(fontName, | ||
maxFontSize, | ||
fontColor, | ||
x.Key, | ||
x.Value, | ||
maxFrequency)) | ||
.ToList(); | ||
} | ||
|
||
private static Dictionary<string, int> GetWordsFrequency(List<string> words) | ||
{ | ||
var wordFrequency = new Dictionary<string, int>(); | ||
foreach (var word in words) | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
if (wordFrequency.ContainsKey(word)) | ||
wordFrequency[word] += 1; | ||
else | ||
wordFrequency[word] = 1; | ||
} | ||
|
||
return wordFrequency; | ||
} | ||
|
||
private static WordForCloud GetWordForCloud(string font, int maxWordSize, Color color, string word, | ||
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. Вообще Tag это абстракция рисовальщика, он ее рисует, сам определяет ей размеры и тд, учитывая общий размер холста и проч, не очень понимаю, почему за нее знает штука, которая веса слов вычисляет |
||
int wordFrequency, int maxFrequency) | ||
{ | ||
var wordFontSize = (int) (maxWordSize * ((double) wordFrequency / maxFrequency) + 0.6); | ||
var wordSize = new Size((int) (word.Length * (wordFontSize + 6) * 0.65), wordFontSize + 10); | ||
return new WordForCloud(font, wordFontSize, word, wordSize, color); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace TagCloud; | ||
|
||
public class WordsNormalizer : IWordsNormalizer | ||
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. Имхо, нормализатор не должен отсеивать, кмк, он как-то преобразует - приводит регистр, форму слова, это преобразование, преобразование - это абстракция, а ее реализация может быть разной - приведение к нижнему регистру, приведение формы А есть фильтрация - не пускать какие-то слова, по части речи или еще по чему-то, это отдельная абстракция, которая базируется на условиях - а что конкретно не пускаем 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. Коммент проигнорен |
||
{ | ||
private readonly HashSet<string> boringWords; | ||
|
||
public WordsNormalizer(HashSet<string> boringWords = null) | ||
{ | ||
this.boringWords = boringWords ?? new HashSet<string>(); | ||
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. Все скучные слова: предлоги, междометья и прочее вручную вводить? |
||
} | ||
|
||
public List<string> NormalizeWords(List<string> 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. Кажется, нормализация должна включать приведение в начальную форму |
||
words.Where(x => !boringWords.Contains(x)).Select(x => x.ToLower()).ToList(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
global using NUnit.Framework; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="FluentAssertions" Version="7.0.0-alpha.3" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/> | ||
<PackageReference Include="NUnit" Version="3.12.0"/> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/> | ||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0"/> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\TagsCloudVisualization\TagsCloudVisualization.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
namespace TagCloudVisualization.Tests; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Drawing; | ||
using FluentAssertions; | ||
using System.Linq; | ||
using NUnit.Framework; | ||
using TagsCloudVisualization; | ||
|
||
[TestFixture] | ||
public class CircularCloudLayouter_Should | ||
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
private CircularCloudLayouter cloud; | ||
private Point center; | ||
private List<Rectangle> rectangles; | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
center = new Point(250, 250); | ||
cloud = new CircularCloudLayouter(new SpiralPoints(center)); | ||
rectangles = new List<Rectangle>(); | ||
} | ||
|
||
[Test] | ||
public void PutNextRectangle_NoIntersects_AfterPutting() | ||
{ | ||
var rectangleSize = new Size(10, 50); | ||
|
||
rectangles = new List<Rectangle>(); | ||
for (var i = 0; i < 100; i++) | ||
{ | ||
rectangles.Add(cloud.PutNextRectangle(rectangleSize)); | ||
} | ||
|
||
foreach (var rectangle in rectangles) | ||
{ | ||
foreach (var secondRectangle in rectangles.Where(x => x != rectangle)) | ||
{ | ||
rectangle.IntersectsWith(secondRectangle).Should().BeFalse(); | ||
} | ||
} | ||
} | ||
|
||
[Test] | ||
public void PutNextRectangle_OnCenter_AfterFirstPut() | ||
{ | ||
var rectangleSize = new Size(100, 50); | ||
var expectedRectangle = new Rectangle(center, rectangleSize); | ||
var rectangle = cloud.PutNextRectangle(rectangleSize); | ||
rectangles.Add(rectangle); | ||
rectangle.Should().BeEquivalentTo(expectedRectangle); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System.Collections.Generic; | ||
using System.Drawing; | ||
using System.Linq; | ||
|
||
namespace TagsCloudVisualization | ||
{ | ||
public class CircularCloudLayouter : ITagCloudLayouter | ||
{ | ||
private readonly List<Rectangle> rectangles = new List<Rectangle>(); | ||
private readonly IPoints Points; | ||
|
||
public CircularCloudLayouter(IPoints points) => | ||
Points = points; | ||
|
||
public Rectangle PutNextRectangle(Size rectangleSize) | ||
{ | ||
var halfRectangleSize = new Size(rectangleSize.Width / 2, rectangleSize.Height / 2); | ||
foreach (var point in Points.GetPoints()) | ||
{ | ||
var rectangle = new Rectangle(point - halfRectangleSize, rectangleSize); | ||
if (rectangles.Any(x => x.IntersectsWith(rectangle))) | ||
continue; | ||
|
||
rectangles.Add(rectangle); | ||
return rectangle; | ||
} | ||
|
||
return new Rectangle(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public interface IPoints | ||
{ | ||
IEnumerable<Point> GetPoints(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public interface ITagCloudLayouter | ||
{ | ||
Rectangle PutNextRectangle(Size rectangleSize); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
namespace TagsCloudVisualization; | ||
|
||
public class Program | ||
{ | ||
public static void Main(string[] args){} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
100 квадратов со случайными размерами (максимальный размер - 70) | ||
![TagCloud](100(randomButLesser70)Rectangles.png ) | ||
|
||
40 квадратов со случайными размерами (максимальный размер - 50) | ||
![TagCloud](40(randomButLesser50)Rectangles.png ) | ||
|
||
100 квадратов со сторонами 10, 50 | ||
![TagCloud](100(10,50)Rectangles.png ) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization; | ||
|
||
public sealed class SpiralPoints : IPoints | ||
{ | ||
private readonly Point center; | ||
private readonly double radiusStep; | ||
|
||
public SpiralPoints(Point center, double radiusStep = 1) | ||
{ | ||
this.center = center; | ||
this.radiusStep = radiusStep; | ||
} | ||
|
||
///<exception cref="System.OverflowExeption"> | ||
/// Long point generation operation | ||
/// </exception> | ||
public IEnumerable<Point> GetPoints() | ||
{ | ||
double radius = 0; | ||
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 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 term = radiusStep / 360; | ||
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. Что такое term? Кажется, нужно более понятное название переменной 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. Проигнорированный коммент |
||
while (true) | ||
{ | ||
for (var pointNumber = 0; pointNumber < 360; pointNumber++) | ||
{ | ||
var pointAngle = 2 * Math.PI * pointNumber / 360; | ||
var currentPoint = new Point(center.X, center.Y); | ||
currentPoint.Offset((int)(Math.Cos(pointAngle) * radius), (int)(Math.Sin(pointAngle) * radius)); | ||
yield return currentPoint; | ||
radius += term; | ||
} | ||
} | ||
} | ||
} |
This comment was marked as resolved.
Sorry, something went wrong.