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

Козлов Двнил #196

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
12149fb
added file reader
SenyaPevko Jan 23, 2024
83d1aa6
added text parser
SenyaPevko Jan 23, 2024
ec0dca0
added tag builder
SenyaPevko Jan 23, 2024
29f1d22
added form pointer
SenyaPevko Jan 23, 2024
b15fdc1
added cloud layouter
SenyaPevko Jan 23, 2024
ee64719
added cloud drawer
SenyaPevko Jan 23, 2024
b0950ba
added tests
SenyaPevko Jan 23, 2024
ceb1207
added application
SenyaPevko Jan 23, 2024
45c5d7f
refactored code
SenyaPevko Jan 23, 2024
b385a92
TagsCloudSettings now can't have nullable fields
SenyaPevko Jan 26, 2024
afa5144
added laziness instead of initialization
SenyaPevko Jan 26, 2024
2c1e9fe
now every constructor throws null exception if null reference was passed
SenyaPevko Jan 26, 2024
b0c310a
now every constructor throws null exception if null reference was pas
SenyaPevko Jan 26, 2024
7193c85
refactored
SenyaPevko Jan 26, 2024
1d5b6eb
settings now loaded from settings file
SenyaPevko Jan 26, 2024
b74c843
refactored
SenyaPevko Jan 26, 2024
dad1000
settings added to config
SenyaPevko Jan 27, 2024
b743802
refactored
SenyaPevko Jan 27, 2024
af17557
added di tests
SenyaPevko Jan 27, 2024
6dd0cd7
refactored
SenyaPevko Jan 27, 2024
3a801dd
app settings now passed through container
SenyaPevko Jan 27, 2024
49959c5
refactored exceptions throwing
SenyaPevko Jan 28, 2024
74c891e
added app settings into di tests
SenyaPevko Jan 28, 2024
47ec8ee
now actions can be empty
SenyaPevko Jan 28, 2024
1b9fe40
refactored after feedback
SenyaPevko Jan 31, 2024
eae835c
files now copied to solution directory
SenyaPevko Feb 1, 2024
5a12d34
images are now saved with format
SenyaPevko Feb 1, 2024
52e1d87
cloud now stores list of tuples and layouter now doesn't have laziness
SenyaPevko Feb 1, 2024
6c8155c
cloud settings now use app settings
SenyaPevko Feb 1, 2024
f41c88d
changed file readers logic
SenyaPevko Feb 1, 2024
43d00cd
added interfaces for settings
SenyaPevko Feb 1, 2024
4f024d3
added interface for cloud drawer
SenyaPevko Feb 1, 2024
e463cc4
cleaned up
SenyaPevko Feb 1, 2024
944d472
added gif and bmp formats for image saving
SenyaPevko Feb 1, 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
57 changes: 57 additions & 0 deletions TagsCloudPainter/CloudDrawer/CloudDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Drawing;
using System.Drawing.Drawing2D;
using TagsCloudPainter.Settings.Cloud;
using TagsCloudPainter.Settings.Tag;

namespace TagsCloudPainter.Drawer;

public class CloudDrawer : ICloudDrawer
{
private readonly ICloudSettings cloudSettings;
private readonly ITagSettings tagSettings;

public CloudDrawer(ITagSettings tagSettings, ICloudSettings cloudSettings)
{
this.tagSettings = tagSettings ?? throw new ArgumentNullException(nameof(tagSettings));
this.cloudSettings = cloudSettings ?? throw new ArgumentNullException(nameof(cloudSettings));
}

public Bitmap DrawCloud(TagsCloud cloud, int imageWidth, int imageHeight)
{
if (cloud.Tags.Count == 0)
throw new ArgumentException("rectangles are empty");
if (imageWidth <= 0 || imageHeight <= 0)
throw new ArgumentException("either width or height of rectangle size is not positive");

var drawingScale = CalculateObjectDrawingScale(cloud.GetWidth(), cloud.GetHeight(), imageWidth, imageHeight);
var bitmap = new Bitmap(imageWidth, imageHeight);
using var graphics = Graphics.FromImage(bitmap);
using var pen = new Pen(tagSettings.TagColor);
{
graphics.TranslateTransform(-cloud.Center.X, -cloud.Center.Y);
graphics.ScaleTransform(drawingScale, drawingScale, MatrixOrder.Append);
graphics.TranslateTransform(cloud.Center.X, cloud.Center.Y, MatrixOrder.Append);
graphics.Clear(cloudSettings.BackgroundColor);
foreach (var tag in cloud.Tags)
{
var font = new Font(tagSettings.TagFontName, tag.Item1.FontSize);
graphics.DrawString(tag.Item1.Value, font, pen.Brush, tag.Item2.Location);
}
}
;
return bitmap;
}

public static float CalculateObjectDrawingScale(float width, float height, float imageWidth, float imageHeight)
{
var scale = 1f;
var scaleAccuracy = 0.05f;
var widthScale = scale;
var heightScale = scale;
if (width * scale > imageWidth)
widthScale = imageWidth / width - scaleAccuracy;
if (height * scale > imageHeight)
heightScale = imageHeight / height - scaleAccuracy;
return Math.Min(widthScale, heightScale);
}
}
8 changes: 8 additions & 0 deletions TagsCloudPainter/CloudDrawer/ICloudDrawer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagsCloudPainter.Drawer;

public interface ICloudDrawer
{
public Bitmap DrawCloud(TagsCloud cloud, int imageWidth, int imageHeight);
}
11 changes: 11 additions & 0 deletions TagsCloudPainter/CloudLayouter/ICloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Drawing;
using TagsCloudPainter.Tags;

namespace TagsCloudPainter.CloudLayouter;

public interface ICloudLayouter : IResetable
{
Rectangle PutNextTag(Tag tag);
TagsCloud GetCloud();
void PutTags(List<Tag> tags);
}
65 changes: 65 additions & 0 deletions TagsCloudPainter/CloudLayouter/TagsCloudLayouter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Drawing;
using TagsCloudPainter.Extensions;
using TagsCloudPainter.FormPointer;
using TagsCloudPainter.Settings.Cloud;
using TagsCloudPainter.Settings.Tag;
using TagsCloudPainter.Sizer;
using TagsCloudPainter.Tags;

namespace TagsCloudPainter.CloudLayouter;

public class TagsCloudLayouter : ICloudLayouter
{
private readonly ICloudSettings cloudSettings;
private readonly IFormPointer formPointer;
private readonly IStringSizer stringSizer;
private readonly ITagSettings tagSettings;
private TagsCloud cloud;

public TagsCloudLayouter(
ICloudSettings cloudSettings,
IFormPointer formPointer,
ITagSettings tagSettings,
IStringSizer stringSizer)
{
this.cloudSettings = cloudSettings ?? throw new ArgumentNullException(nameof(cloudSettings));
this.formPointer = formPointer ?? throw new ArgumentNullException(nameof(formPointer));
this.tagSettings = tagSettings ?? throw new ArgumentNullException(nameof(tagSettings));
this.stringSizer = stringSizer ?? throw new ArgumentNullException();
cloud = new TagsCloud(cloudSettings.CloudCenter, []);
}

public Rectangle PutNextTag(Tag tag)
{
var tagSize = stringSizer.GetStringSize(tag.Value, tagSettings.TagFontName, tag.FontSize);
if (tagSize.Height <= 0 || tagSize.Width <= 0)
throw new ArgumentException("either width or height of rectangle size is not possitive");

var nextRectangle = formPointer.GetNextPoint().GetRectangle(tagSize);
while (cloud.Tags.Any(pair => pair.Item2.IntersectsWith(nextRectangle)))
nextRectangle = formPointer.GetNextPoint().GetRectangle(tagSize);

cloud.AddTag(tag, nextRectangle);

return nextRectangle;
}

public void PutTags(List<Tag> tags)
{
if (tags.Count == 0)
throw new ArgumentException("пустые размеры");
foreach (var tag in tags)
PutNextTag(tag);
}

public TagsCloud GetCloud()
{
return new TagsCloud(cloud.Center, cloud.Tags);
}

public void Reset()
{
formPointer.Reset();
cloud = new TagsCloud(cloudSettings.CloudCenter, []);
}
}
14 changes: 14 additions & 0 deletions TagsCloudPainter/Extensions/PointExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Drawing;

namespace TagsCloudPainter.Extensions;

public static class PointExtension
{
public static Rectangle GetRectangle(this Point center, Size size)
{
var x = center.X - size.Width / 2;
var y = center.Y - size.Height / 2;

return new Rectangle(new Point(x, y), size);
}
}
13 changes: 13 additions & 0 deletions TagsCloudPainter/Extensions/RectangleExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Drawing;

namespace TagsCloudPainter.Extensions;

public static class RectangleExtensions
{
public static Point GetCenter(this Rectangle rectangle)
{
var x = rectangle.X;
var y = rectangle.Y;
return new Point(x + rectangle.Width / 2, y + rectangle.Height / 2);
}
}
17 changes: 17 additions & 0 deletions TagsCloudPainter/FileReader/DocFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Spire.Doc;

namespace TagsCloudPainter.FileReader;

public class DocFileReader : IFileReader
{
public HashSet<string> SupportedExtensions => new() { ".doc", ".docx" };

public string ReadFile(string path)
{
var doc = new Document();
doc.LoadFromFile(path);
var text = doc.GetText();
var lastIndexOfSpirePart = text.IndexOf(Environment.NewLine);
return text.Substring(lastIndexOfSpirePart + 2).Trim();
}
}
7 changes: 7 additions & 0 deletions TagsCloudPainter/FileReader/IFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TagsCloudPainter.FileReader;

public interface IFileReader
{
public HashSet<string> SupportedExtensions { get; }
public string ReadFile(string path);
}
6 changes: 6 additions & 0 deletions TagsCloudPainter/FileReader/IFormatFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudPainter.FileReader;

public interface IFormatFileReader<TFormat>
{
public TFormat ReadFile(string path);
}
26 changes: 26 additions & 0 deletions TagsCloudPainter/FileReader/TextFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace TagsCloudPainter.FileReader;

public class TextFileReader : IFormatFileReader<string>
{
private readonly IEnumerable<IFileReader> fileReaders;

public TextFileReader(IEnumerable<IFileReader> fileReaders)
{
this.fileReaders = fileReaders;
}

public string ReadFile(string path)
{
if (!File.Exists(path))
throw new FileNotFoundException();

var fileExtension = Path.GetExtension(path);
var fileReader =
fileReaders.FirstOrDefault(fileReader => fileReader.SupportedExtensions.Contains(fileExtension));

return fileReader is not null
? fileReader.ReadFile(path)
: throw new ArgumentException($"Incorrect file extension {fileExtension}. " +
$"Supported file extensions: txt, doc, docx");
}
}
11 changes: 11 additions & 0 deletions TagsCloudPainter/FileReader/TxtFileReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace TagsCloudPainter.FileReader;

public class TxtFileReader : IFileReader
{
public HashSet<string> SupportedExtensions => new() { ".txt" };

public string ReadFile(string path)
{
return File.ReadAllText(path).Trim();
}
}
41 changes: 41 additions & 0 deletions TagsCloudPainter/FormPointer/ArchimedeanSpiralPointer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Drawing;
using TagsCloudPainter.Settings.Cloud;
using TagsCloudPainter.Settings.FormPointer;

namespace TagsCloudPainter.FormPointer;

public class ArchimedeanSpiralPointer : IFormPointer
{
private readonly ICloudSettings cloudSettings;
private readonly ISpiralPointerSettings spiralPointerSettings;
private double сurrentDifference;

public ArchimedeanSpiralPointer(ICloudSettings cloudSettings, ISpiralPointerSettings spiralPointerSettings)
{
if (spiralPointerSettings.Step <= 0
|| spiralPointerSettings.RadiusConst <= 0
|| spiralPointerSettings.AngleConst <= 0)
throw new ArgumentException("either step or radius or angle is not possitive");
this.cloudSettings = cloudSettings ?? throw new ArgumentNullException(nameof(cloudSettings));
this.spiralPointerSettings =
spiralPointerSettings ?? throw new ArgumentNullException(nameof(spiralPointerSettings));
сurrentDifference = 0;
}

private double Angle => сurrentDifference * spiralPointerSettings.AngleConst;
private double Radius => сurrentDifference * spiralPointerSettings.RadiusConst;

public Point GetNextPoint()
{
сurrentDifference += spiralPointerSettings.Step;
var x = cloudSettings.CloudCenter.X + (int)(Radius * Math.Cos(Angle));
var y = cloudSettings.CloudCenter.Y + (int)(Radius * Math.Sin(Angle));

return new Point(x, y);
}

public void Reset()
{
сurrentDifference = 0;
}
}
8 changes: 8 additions & 0 deletions TagsCloudPainter/FormPointer/IFormPointer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Drawing;

namespace TagsCloudPainter.FormPointer;

public interface IFormPointer : IResetable
{
Point GetNextPoint();
}
6 changes: 6 additions & 0 deletions TagsCloudPainter/IResetable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudPainter;

public interface IResetable
{
void Reset();
}
32 changes: 32 additions & 0 deletions TagsCloudPainter/Parser/BoringTextParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using TagsCloudPainter.Settings;

namespace TagsCloudPainter.Parser;

public class BoringTextParser : ITextParser
{
private static readonly string[] _separators = [" ", ". ", ", ", "; ", "-", "—", Environment.NewLine];
private readonly ITextSettings textSettings;

public BoringTextParser(ITextSettings textSettings)
{
this.textSettings = textSettings ?? throw new ArgumentNullException(nameof(textSettings));
}

public List<string> ParseText(string text)
{
var boringWords = GetBoringWords(textSettings.BoringText);
var words = text.Split(_separators, StringSplitOptions.RemoveEmptyEntries);
return words.Select(word => word.ToLower()).Where(word => !boringWords.Contains(word)).ToList();
}

public HashSet<string> GetBoringWords(string text)
{
var words = text.Split(Environment.NewLine);
var boringWords = new HashSet<string>();

foreach (var word in words)
boringWords.Add(word.ToLower());

return boringWords;
}
}
6 changes: 6 additions & 0 deletions TagsCloudPainter/Parser/ITextParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace TagsCloudPainter.Parser;

public interface ITextParser
{
List<string> ParseText(string text);
}
9 changes: 9 additions & 0 deletions TagsCloudPainter/Settings/Cloud/CloudSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;

namespace TagsCloudPainter.Settings.Cloud;

public class CloudSettings : ICloudSettings
{
public Point CloudCenter { get; set; }
public Color BackgroundColor { get; set; }
}
9 changes: 9 additions & 0 deletions TagsCloudPainter/Settings/Cloud/ICloudSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;

namespace TagsCloudPainter.Settings.Cloud;

public interface ICloudSettings
{
public Point CloudCenter { get; set; }
public Color BackgroundColor { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace TagsCloudPainter.Settings.FormPointer;

public interface ISpiralPointerSettings
{
public double Step { get; set; }
public double RadiusConst { get; set; }
public double AngleConst { get; set; }
}
Loading