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

Савельев Григорий #200

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
da15221
Initial commit
luvairo-m Jan 22, 2024
0780e96
Переработка класса, отвечающего за отрисовку изображения. TagsCloudVi…
luvairo-m Jan 22, 2024
73a2267
Добавление точки входа в программу. Замена Word => Tag
luvairo-m Jan 23, 2024
b22dab8
Добавление фильтров и источников информации.
luvairo-m Jan 23, 2024
350b9c1
Правки в фильтрах.
luvairo-m Jan 24, 2024
b3a8bfe
Первая рабочая версия.
luvairo-m Jan 24, 2024
6fe9c1d
Добавление переворотов слов.
luvairo-m Jan 24, 2024
553449d
Добавлен CLI
luvairo-m Jan 24, 2024
a216c4e
Исправление ошибки ввода частей речи.
luvairo-m Jan 24, 2024
554883b
Первые правки.
luvairo-m Jan 26, 2024
c9e8946
Reformat кода.
luvairo-m Jan 26, 2024
5579be7
Reformat TagCloudVisualization.
luvairo-m Jan 26, 2024
9965d1e
Новая структура.
luvairo-m Jan 27, 2024
5ecfab1
Переработка фильтров. Расширение ServiceCollectionExtensions.
luvairo-m Jan 28, 2024
4892a1e
Опции для процессоров теперь неизменяемые.
luvairo-m Jan 28, 2024
b2084cb
Устранение бага с переворотом слова и бага, связанного с регистром ис…
luvairo-m Jan 28, 2024
609ddca
Реализация csvfilereader + docxfilereader.
luvairo-m Jan 28, 2024
f3c6de3
Сведение регистрации зависимостей к одному методу и добавление атрибу…
luvairo-m Jan 30, 2024
2f385c6
Добавление тестов.
luvairo-m Jan 30, 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
28 changes: 28 additions & 0 deletions TagsCloud.Tests/DefaultPostFormatterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using FluentAssertions;
using NUnit.Framework;
using TagsCloud.Formatters;

namespace TagsCloud.Tests;

[TestFixture]
public class DefaultPostFormatterTests
{
private readonly DefaultPostFormatter defaultFormatter = new();

[TestCase("Mercedes-Benz", "Mercedes")]
[TestCase("Hello, world!", "Hello")]
[TestCase("123", "")]
[TestCase("Apple Orange Banana", "Apple")]
[TestCase("", "")]
[TestCase(" circle", "circle")]
[TestCase("circle ", "circle")]
[TestCase("$$$", "")]
[TestCase("A", "A")]
[TestCase(" ___ Juice", "")]
[TestCase(" ", "")]
public void Formatter_Should_CutLineToFirstNonLetterCharacter(string line, string expected)
Copy link

Choose a reason for hiding this comment

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

Попробуй ещё сделать вот так, но перезаливать нет нужды, просто попробуй.

В TestFixture можно добавить TestOf. К методу можно добавить такой же атрибут TestOf - тогда нет нужды в имя теста вписывать имя метода / сущности. Тестируемую систему часто называют sut

{
var actual = defaultFormatter.Format(line);
actual.ShouldBeEquivalentTo(expected);
}
}
63 changes: 63 additions & 0 deletions TagsCloud.Tests/FileReadersTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using FluentAssertions;
using NUnit.Framework;
using System.Reflection;
using System.Text.RegularExpressions;
using TagsCloud.Contracts;
using TagsCloud.Formatters;

namespace TagsCloud.Tests;

[TestFixture]
public partial class FileReadersTests
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
expectedLines = File.ReadAllLines($"{testDataPath}.txt")
.Select(line => line.Split(separators, StringSplitOptions.RemoveEmptyEntries))
.Select(array => array[0])
.Where(word => char.IsLetter(word[0]))
.ToArray();
}

private readonly string testDataPath = Path.Join("TestData", "test_data");
private readonly IPostFormatter defaultFormatter = new DefaultPostFormatter();
private readonly char[] separators = { ' ', ',', '.', ':', ';', '!', '?' };
private string[] expectedLines;

private readonly IFileReader[] fileReaders =
Assembly
.GetAssembly(typeof(IFileReader))!
.GetTypes()
.Where(type => type.GetInterfaces().Any(inter => inter == typeof(IFileReader)))
.Select(reader => (IFileReader)Activator.CreateInstance(reader)!)
.ToArray();

[Test]
public void Readers_Should_ReadFileContentCorrectly()
{
foreach (var reader in fileReaders)
{
var actualLines = reader
.ReadContent($"{testDataPath}.{reader.SupportedExtension}", defaultFormatter)
.Where(line => !string.IsNullOrEmpty(line));

actualLines.ShouldAllBeEquivalentTo(expectedLines);
}
}

[Test]
public void ReadersNames_Should_MatchSupportedExtensions()
{
foreach (var reader in fileReaders)
{
var match = ReaderNamePattern().Match(reader.GetType().Name);

match.Success.Should().Be(true);
match.Groups[1].Value.ToLower().ShouldBeEquivalentTo(reader.SupportedExtension);
Copy link

Choose a reason for hiding this comment

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

Сомнительный тест, т.к. по контракт по имени класса не самый сильный, но в целом пойдет, т.к. административные конвенции всё же встречаются.

}
}

[GeneratedRegex("([A-Z]\\w*)FileReader")]
private static partial Regex ReaderNamePattern();
}
116 changes: 116 additions & 0 deletions TagsCloud.Tests/GlobalTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using FluentAssertions;
using NUnit.Framework;
using SixLabors.ImageSharp;
using TagsCloud.Builders;
using TagsCloud.Entities;
using TagsCloudVisualization;

namespace TagsCloud.Tests;

[TestFixture]
public class GlobalTest
{
[OneTimeSetUp]
public void OneTimeSetUp()
{
var textParts = new HashSet<string> { "S" };
var colors = new HashSet<string> { "#de2114", "#07f727", "#7707f7" };
var (width, height) = (1920, 1080);

var inputOptions = new InputOptionsBuilder()
.SetWordsCase(CaseType.Upper)
.SetCastPolitics(true)
.SetExcludedWords(excludedWords)
.SetLanguageParts(textParts)
.SetLanguagePolitics(true)
.BuildOptions();

var cloudOptions = new CloudOptionsBuilder()
.SetColors(colors)
.SetLayout(
PointGeneratorType.Spiral,
new PointF((float)width / 2, (float)height / 2),
0.1f,
(float)Math.PI / 180)
.SetColoringStrategy(ColoringStrategy.AllRandom)
.SetMeasurerType(MeasurerType.Linear)
.SetFontFamily(string.Empty)
.SetSortingType(SortType.Ascending)
.SetFontSizeBounds(35, 100)
.BuildOptions();

var outputOptions = new OutputOptionsBuilder()
.SetImageFormat(ImageFormat.Jpeg)
.SetImageSize(new Size(width, height))
.SetImageBackgroundColor("#ffffff")
.BuildOptions();

var engine = new TagCloudEngine(inputOptions, cloudOptions, outputOptions);
wordGroups = engine.GenerateTagCloud(Path.Join("TestData", "data.txt"), outputPath);
}

private readonly HashSet<string> excludedWords = new(StringComparer.OrdinalIgnoreCase)
{
"Ноутбук",
"Камера"
};

private const string outputPath = "tagcloud_image.jpeg";

private readonly HashSet<string> verbs = new(StringComparer.OrdinalIgnoreCase)
{
"Программировать",
"Прыгать",
"Бегать",
"Играть"
};

private readonly HashSet<string> englishWords = new(StringComparer.OrdinalIgnoreCase)
{
"America",
"Russia",
"Germany",
"Apple",
"TV",
"Join",
"Split"
};

private HashSet<WordTagGroup> wordGroups;

[Test]
public void WordGroups_Should_ContainOnlyRussianWords()
{
wordGroups.Should().NotContain(group => englishWords.Contains(group.WordInfo.Text));
}

[Test]
public void WordGroups_ShouldNot_ContainVerbs()
{
wordGroups.Should().NotContain(group => verbs.Contains(group.WordInfo.Text));
}

[Test]
public void WordGroups_ShouldNot_ContainExcludedWords()
{
wordGroups.Should().NotContain(group => excludedWords.Contains(group.WordInfo.Text));
}

[Test]
public void WordGroupsWords_Should_BeUpperCase()
{
foreach (var group in wordGroups)
AreLettersUpperCase(group.WordInfo.Text).Should().Be(true);
}

[Test]
public void TagCloud_Should_CreateImageFile()
{
File.Exists(outputPath).Should().Be(true);
}

private static bool AreLettersUpperCase(string word)
{
return word.Where(char.IsLetter).All(letter => letter == char.ToUpper(letter));
}
}
16 changes: 16 additions & 0 deletions TagsCloud.Tests/TagsCloud.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@

<ItemGroup>
<ProjectReference Include="..\TagsCloudVisualization\TagsCloudVisualization.csproj"/>
<ProjectReference Include="..\TagsCloud\TagsCloud.csproj"/>
</ItemGroup>

<ItemGroup>
<None Update="TestData\test_data.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="TestData\test_data.docx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="TestData\test_data.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="TestData\data.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions TagsCloud.Tests/TestData/data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Программировать
Играет
Germany
Бегает
Прыгают
Apple
Join
Split
TV
Бегать
Бегать
Russia
Russia
Russia
Бегать
Камера
Камера
Играть
Играть
Прыжок
Ноутбук
Планшет
Яблоко
America
Ноутбук
14 changes: 14 additions & 0 deletions TagsCloud.Tests/TestData/test_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Lorem ,
consectetur 1 2 3 4 5,
Praesent,
Nunc --->,
Maecenas,
Fusce,
Nullam (5 + 5 = 10),
Nulla world!,
Vivamus Hello,
Aenean,
Mauris <<<-,
Nullam,
nec Microsoft Power point,
Aliquam nec,
Binary file added TagsCloud.Tests/TestData/test_data.docx
Binary file not shown.
18 changes: 18 additions & 0 deletions TagsCloud.Tests/TestData/test_data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Lorem! ipsum dolor sit amet,
consectetur :) adipiscing elit.
--->>>>>>>>>>>>>>>>>>>>>>
@@@@
Praesent blandit consequat tristique. Donec felis purus, consequat eget enim et, tempus porttitor felis. ->
Nunc @@@ semper nulla a ante vulputate mattis.
Maecenas pellentesque vestibulum nisl, ut elementum ante sagittis nec.
Fusce semper finibus nibh at vehicula.
Nullam, auctor euismod risus, ac interdum leo. Nulla pulvinar turpis eu interdum volutpat.
Nulla, dignissim vestibulum leo, vel mollis quam. Pellentesque sed erat dictum, commodo arcu ut, euismod urna.
######################
Vivamus, eu venenatis velit.
Aenean rhoncus et lectus et aliquam.
Mauris quis est odio. Vivamus id condimentum nunc.
Nullam sagittis dictum leo,
nec egestas ligula accumsan eget.
<><><><>
Aliquam enim dui, pharetra accumsan tincidunt id, imperdiet quis quam.
35 changes: 35 additions & 0 deletions TagsCloud.Tests/TextAnalyzerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using FluentAssertions;
using NUnit.Framework;
using TagsCloud.TextAnalysisTools;
using TagsCloudVisualization;

namespace TagsCloud.Tests;

[TestFixture]
public class TextAnalyzerTests
{
[Test]
public void TextAnalyzer_Should_DistinguishRussianAndOtherWords()
{
var testData = GetTestGroups().ToArray();
var groups = testData
.Select(data => data.Group)
.ToHashSet();

TextAnalyzer.FillWithAnalysis(groups);

foreach (var (group, isEnglish) in testData)
group.WordInfo.IsRussian.Should().Be(isEnglish);
}

private static IEnumerable<(WordTagGroup Group, bool isRussian)> GetTestGroups()
Copy link

Choose a reason for hiding this comment

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

Кажется, проще было реализовать массив, чем прописывать yield return, но ок

{
yield return (new WordTagGroup("Apple", 1), false);
yield return (new WordTagGroup("Игра", 1), true);
yield return (new WordTagGroup("BMW", 1), false);
yield return (new WordTagGroup("Богатырь", 1), true);
yield return (new WordTagGroup("Математика", 1), true);
yield return (new WordTagGroup("C#", 1), false);
yield return (new WordTagGroup("Fibonacci", 1), false);
}
}
1 change: 0 additions & 1 deletion TagsCloud/FileReaders/TxtFileReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public IEnumerable<string> ReadContent(string filename, IPostFormatter postForma
{
return File
.ReadLines(filename)
.Where(line => !string.IsNullOrEmpty(line))
.Select(line => postFormatter is null ? line : postFormatter.Format(line));
}
}
6 changes: 4 additions & 2 deletions TagsCloud/Formatters/DefaultPostFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ public class DefaultPostFormatter : IPostFormatter
{
public string Format(string input)
{
var idx = GetFirstNonLetterIndex(input);
return idx == -1 ? input : input[..idx];
var trimmedInput = input.TrimStart();
var endIdx = GetFirstNonLetterIndex(trimmedInput);

return endIdx == -1 ? trimmedInput : trimmedInput[..endIdx];
}

private static int GetFirstNonLetterIndex(string line)
Expand Down
4 changes: 4 additions & 0 deletions TagsCloud/Processors/InputProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ public HashSet<WordTagGroup> CollectWordGroupsFromFile(string filename)
var reader = FindFileReader(filename);
var wordGroups = reader
.ReadContent(filename, postFormatter)
.Where(line => !string.IsNullOrEmpty(line))
.GroupBy(line => line)
.Select(group => new WordTagGroup(group.Key, group.Count()))
.ToHashSet();

if (wordGroups.Count == 0)
throw new ArgumentException("No words found! Check file structure.");
Copy link

Choose a reason for hiding this comment

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

Можно информативнее 🙃, у тебя на руках есть имя файла


TextAnalyzer.FillWithAnalysis(wordGroups);
filterConveyor.ApplyFilters(wordGroups);

Expand Down
5 changes: 4 additions & 1 deletion TagsCloud/TagCloudEngine.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using TagsCloud.Contracts;
using TagsCloud.Extensions;
using TagsCloudVisualization;

namespace TagsCloud;

Expand All @@ -21,7 +22,7 @@ public TagCloudEngine(
.BuildServiceProvider();
}

public void GenerateTagCloud(string inputFile, string outputFile)
public HashSet<WordTagGroup> GenerateTagCloud(string inputFile, string outputFile)
{
var textProcessor = serviceProvider.GetRequiredService<IInputProcessor>();
var cloudProcessor = serviceProvider.GetRequiredService<ICloudProcessor>();
Expand All @@ -34,5 +35,7 @@ public void GenerateTagCloud(string inputFile, string outputFile)
cloudProcessor.SetColors(groups);

outputProcessor.SaveVisualization(groups, outputFile);

return groups;
}
}