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

Конина Анастасия #205

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 0 additions & 1 deletion FractalPainter/fractalPainter.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<LangVersion>8</LangVersion>
Expand Down
6 changes: 6 additions & 0 deletions TagCloud/IWordsForCloudGenerator.cs
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);
}
6 changes: 6 additions & 0 deletions TagCloud/IWordsNormalizer.cs
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);
}
57 changes: 57 additions & 0 deletions TagCloud/Program.cs
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)

This comment was marked as resolved.

{
var inputFile = "1.txt";

This comment was marked as resolved.

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.

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.

{
using (var fileStream = new StreamReader(path))
{
return fileStream.ReadToEnd().Split('\n').ToList();
Copy link

Choose a reason for hiding this comment

The 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.

string fileName,
Size pictureSize)
{
var bitmap = new Bitmap(pictureSize.Width, pictureSize.Height);
var gr = Graphics.FromImage(bitmap);

This comment was marked as resolved.

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);
}
}
}
14 changes: 14 additions & 0 deletions TagCloud/TagCloud.csproj
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>
22 changes: 22 additions & 0 deletions TagCloud/WordForCloud.cs
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);
Copy link

@gisinka gisinka Jan 29, 2024

Choose a reason for hiding this comment

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

Font - IDisposable
Кажется, это слишком расточительно на каждое слово создавать экземпляр шрифта
А еще зачем два размера, кажется слово можно описать одним размером

Помимо этого название класса поменял бы, если у нас облако тэгов, можно назвать просто Tag

Copy link

Choose a reason for hiding this comment

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

Проигноренный коммент

FontSize = fontSize;
WordSize = wordSize;
WordColor = wordColor;
Word = word;
}
}
59 changes: 59 additions & 0 deletions TagCloud/WordsForCloudGenerator.cs
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;
Copy link

Choose a reason for hiding this comment

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

Такие параметры будто бы просятся унестись в какой-то класс настроечек для конкретной абстракции
Типа TagGeneratorSettings и тп

Это норм тема, когда двестиписят параметров инкапсулируют в класс и приносят одной моделькой

Copy link

Choose a reason for hiding this comment

The 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)
Copy link

Choose a reason for hiding this comment

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

Так уж TagGenerator, но это тоже неправда
В этом классе совмещены несколько ответственностей - сбор весов слов и генерация тэгов с их параметрами
SRP, все дела

Copy link

Choose a reason for hiding this comment

The 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)
Copy link

Choose a reason for hiding this comment

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

Интересная логика, отсортировать по возрастанию и зареверсить, почему бы не делать это в один проход - отсортировать по убыванию?

Copy link

Choose a reason for hiding this comment

The 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.

{
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,
Copy link

Choose a reason for hiding this comment

The 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);
}
}
14 changes: 14 additions & 0 deletions TagCloud/WordsNormalizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace TagCloud;

public class WordsNormalizer : IWordsNormalizer
Copy link

Choose a reason for hiding this comment

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

Имхо, нормализатор не должен отсеивать, кмк, он как-то преобразует - приводит регистр, форму слова, это преобразование, преобразование - это абстракция, а ее реализация может быть разной - приведение к нижнему регистру, приведение формы
На мой взгляд, нормализатор должен применять список преобразований к каждому слову

А есть фильтрация - не пускать какие-то слова, по части речи или еще по чему-то, это отдельная абстракция, которая базируется на условиях - а что конкретно не пускаем

Copy link

Choose a reason for hiding this comment

The 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>();
Copy link

Choose a reason for hiding this comment

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

Все скучные слова: предлоги, междометья и прочее вручную вводить?

}

public List<string> NormalizeWords(List<string> words) =>
Copy link

Choose a reason for hiding this comment

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

Кажется, нормализация должна включать приведение в начальную форму

words.Where(x => !boringWords.Contains(x)).Select(x => x.ToLower()).ToList();
}
1 change: 1 addition & 0 deletions TagCloudVisualization.Tests/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using NUnit.Framework;
24 changes: 24 additions & 0 deletions TagCloudVisualization.Tests/TagCloudVisualization.Tests.csproj
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>
54 changes: 54 additions & 0 deletions TagCloudVisualization.Tests/UnitTest1.cs
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.

This comment was marked as resolved.

{
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);
}
}
Binary file added TagsCloudVisualization/100(10,50)Rectangles.png
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions TagsCloudVisualization/CircularCloudLayouter.cs
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();
}
}
}
8 changes: 8 additions & 0 deletions TagsCloudVisualization/IPoints.cs
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();
}
8 changes: 8 additions & 0 deletions TagsCloudVisualization/ITagCloudLayouter.cs
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);
}
6 changes: 6 additions & 0 deletions TagsCloudVisualization/Program.cs
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){}
}
8 changes: 8 additions & 0 deletions TagsCloudVisualization/README.md
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 )
35 changes: 35 additions & 0 deletions TagsCloudVisualization/SpiralPoints.cs
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;
Copy link

Choose a reason for hiding this comment

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

var

Copy link

Choose a reason for hiding this comment

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

Проигнорированный коммент

var term = radiusStep / 360;
Copy link

Choose a reason for hiding this comment

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

Что такое term? Кажется, нужно более понятное название переменной

Copy link

Choose a reason for hiding this comment

The 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;
}
}
}
}
Loading