-
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
Алешев Руслан #188
base: master
Are you sure you want to change the base?
Алешев Руслан #188
Changes from 6 commits
17a5d9f
22e56ab
271ef7f
77fb65f
3d91d03
af7d57d
03e1d52
9b16fc0
7a8a6b9
6601ff9
0f53408
b1d2d86
8655a10
74c589a
aab825f
7e628a2
28f5212
c8cda5f
fccf8bf
dda89b9
6373fa9
7b562a2
6d2c3c2
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,139 @@ | ||
using System.Drawing; | ||
using TagsCloudContainer.SettingsClasses; | ||
|
||
namespace TagsCloudContainer.CLI | ||
{ | ||
public static class CommandLineArgs | ||
{ | ||
public static void PrintUsage() | ||
{ | ||
Console.WriteLine(@"Usage: TagCloudContainer.exe <fileName> [-font <fontName>] [-fontsize <fontSize>] [-color <colorName>] [-size <Width> <Height>] | ||
|
||
Options: | ||
-font <FontName>: Set the font family name. Default is Arial. | ||
-fontsize <FontSize>: Set the font size. Must be a positive integer. | ||
-color <ColorName>: Add a color to the list of allowed colors. | ||
-size <Width> <Height> : Set the image width. Must be two positive integer separated by whitespace. | ||
-layout <Layout> : Set cloud layouter - Spiral or Random. Default is Spiral. | ||
-out <outputImage> : Set path for output image. | ||
"); | ||
} | ||
|
||
public static (CloudDrawingSettings, AppSettings) CreateSettingsObject(IReadOnlyCollection<string> args) | ||
{ | ||
if (args.Count < 1) throw new ArgumentException("At least one argument must be provided.", "args"); | ||
|
||
var settings = new CloudDrawingSettings(); | ||
|
||
var appSettings = new AppSettings(); | ||
|
||
return (settings, appSettings); | ||
} | ||
|
||
public static void ParseCommandLineArguments(CloudDrawingSettings settings, AppSettings appSettings, string[] args) | ||
{ | ||
HandleTextFileOption(args, ref appSettings); | ||
|
||
for (int i = 1; i < args.Length; i += 2) | ||
{ | ||
HandleFontOption(args, ref settings, i); | ||
HandleFontSizeOption(args, ref settings, i); | ||
HandleColorOption(args, ref settings, i); | ||
HandleSizeOption(args, ref settings, i); | ||
HandleOutputFileOption(args, ref appSettings, i); | ||
} | ||
} | ||
|
||
private static void HandleOutputFileOption(string[] args, ref AppSettings appSettings, int index) | ||
{ | ||
const string OptionName = "-out"; | ||
|
||
if (args[index] != OptionName) return; | ||
|
||
if (index + 1 >= args.Length || string.IsNullOrEmpty(args[index + 1])) | ||
{ | ||
Console.WriteLine($"The '-out' option requires a valid file name."); | ||
return; | ||
} | ||
appSettings.outImagePath = args[++index]; | ||
|
||
|
||
} | ||
|
||
private static void HandleTextFileOption(string[] args, ref AppSettings appSettings) | ||
{ | ||
appSettings.textFile = args[0]; | ||
} | ||
|
||
private static void HandleFontOption(string[] args, ref CloudDrawingSettings settings, int index) | ||
{ | ||
const string OptionName = "-font"; | ||
|
||
if (args[index] != OptionName) return; | ||
|
||
if (index + 1 >= args.Length || string.IsNullOrEmpty(args[index + 1])) | ||
{ | ||
Console.WriteLine($"The '-font' option requires a valid font family name."); | ||
return; | ||
} | ||
|
||
settings.FontFamily = new FontFamily(args[++index]); | ||
} | ||
|
||
private static void HandleFontSizeOption(string[] args, ref CloudDrawingSettings settings, int index) | ||
{ | ||
const string OptionName = "-fontsize"; | ||
|
||
if (args[index] != OptionName) return; | ||
|
||
if (index + 1 >= args.Length || !int.TryParse(args[index + 1], out _)) | ||
{ | ||
Console.WriteLine($"The '-fontsize' option requires a valid integer value."); | ||
return; | ||
} | ||
|
||
if (int.Parse(args[++index]) <= 0) | ||
{ | ||
Console.WriteLine($"The '-fontsize' option requires a positive integer value."); | ||
return; | ||
} | ||
|
||
settings.FontSize = int.Parse(args[index]); | ||
} | ||
|
||
private static void HandleColorOption(string[] args, ref CloudDrawingSettings settings, int index) | ||
{ | ||
const string OptionName = "-color"; | ||
|
||
if (args[index] != OptionName) return; | ||
|
||
if (index + 1 >= args.Length) // || !Color.TryParse(args[index + 1], out _)) | ||
{ | ||
Console.WriteLine("The '-color' option requires a valid color value."); | ||
return; | ||
} | ||
|
||
settings.Colors.Add(Color.FromName(args[++index])); | ||
} | ||
|
||
private static void HandleSizeOption(string[] args, ref CloudDrawingSettings settings, int index) | ||
{ | ||
const string OptionName = "-size"; | ||
|
||
if (args[index] != OptionName) return; | ||
if (index + 2 >= args.Length || !int.TryParse(args[index + 1], out _) || !int.TryParse(args[index + 2], out _)) | ||
{ | ||
Console.WriteLine($"The '-size' option requires two valid integer value."); | ||
return; | ||
} | ||
|
||
if (int.Parse(args[index + 1]) <= 0 || int.Parse(args[index + 2]) <= 0) | ||
{ | ||
Console.WriteLine($"The '-size' option requires two positive integer value."); | ||
return; | ||
} | ||
|
||
settings.Size = new Size(int.Parse(args[++index]), int.Parse(args[++index])); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using TagsCloudContainer.FrequencyAnalyzers; | ||
using TagsCloudContainer.TextTools; | ||
|
||
namespace TagsCloudContainer | ||
{ | ||
public class DependencyInjectionConfig | ||
{ | ||
public static IServiceCollection AddCustomServices(IServiceCollection services) | ||
{ | ||
services.AddScoped<TextFileReader>(); | ||
services.AddScoped<FrequencyAnalyzer>(); | ||
This comment was marked as resolved.
Sorry, something went wrong. 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. ITextReader и IAnalyzer сделал Singleton, т.к. чтение из файлы + тяжелые операции. |
||
|
||
return services; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
namespace TagsCloudContainer.FrequencyAnalyzers | ||
{ | ||
public class FrequencyAnalyzer : IAnalyzer | ||
{ | ||
private readonly TextPreprocessing preprocessor; | ||
|
||
private readonly Dictionary<string, int> wordFrequency; | ||
public FrequencyAnalyzer() | ||
{ | ||
wordFrequency = new Dictionary<string, int>(); | ||
preprocessor = new TextPreprocessing("excludedWords.txt"); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
} | ||
|
||
public void Analyze(string text) | ||
{ | ||
foreach (var word in preprocessor.Preprocess(text)) | ||
{ | ||
if (wordFrequency.ContainsKey(word.ToLower())) | ||
{ | ||
wordFrequency[word]++; | ||
} | ||
else | ||
{ | ||
wordFrequency.Add(word, 1); | ||
} | ||
} | ||
} | ||
|
||
public IEnumerable<(string, int)> GetAnalyzedText() | ||
{ | ||
foreach (KeyValuePair<string, int> pair in wordFrequency) | ||
{ | ||
yield return (pair.Key, pair.Value); | ||
} | ||
} | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
|
||
public void SaveToFile(string filePath) | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
using (StreamWriter writer = new StreamWriter(filePath)) | ||
{ | ||
foreach (KeyValuePair<string, int> pair in wordFrequency) | ||
{ | ||
writer.WriteLine($"{pair.Key}: {pair.Value}"); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace TagsCloudContainer.FrequencyAnalyzers | ||
{ | ||
public interface IAnalyzer | ||
{ | ||
public abstract void Analyze(string text); | ||
public abstract IEnumerable<(string, int)> GetAnalyzedText(); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
namespace TagsCloudContainer.FrequencyAnalyzers | ||
{ | ||
public class TextPreprocessing | ||
{ | ||
private readonly HashSet<string> excludedWords = new HashSet<string>(); | ||
//private const string excludedWordsPath = "excludedWords.txt"; | ||
public TextPreprocessing(string excludedWordsPath) | ||
{ | ||
if (File.Exists(excludedWordsPath)) | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
StreamReader reader = new StreamReader(excludedWordsPath); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
excludedWords = reader.ReadToEnd() | ||
.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToHashSet(); | ||
} | ||
} | ||
public IEnumerable<string> Preprocess(string text) | ||
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
var words = text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries) | ||
.Select(x => x.ToLower()); | ||
foreach (var word in words) | ||
{ | ||
if (!excludedWords.Contains(word)) | ||
yield return word; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Drawing; | ||
using TagsCloudContainer.CLI; | ||
using TagsCloudContainer.FrequencyAnalyzers; | ||
using TagsCloudContainer.TextTools; | ||
using TagsCloudVisualization; | ||
|
||
namespace TagsCloudContainer | ||
{ | ||
public static class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
var services = DependencyInjectionConfig.AddCustomServices(new ServiceCollection()); | ||
var serviceProvider = services.BuildServiceProvider(); | ||
|
||
var reader = serviceProvider.GetService<TextFileReader>(); | ||
var analyzer = serviceProvider.GetService<FrequencyAnalyzer>(); | ||
|
||
if (args.Length < 1) | ||
{ | ||
CommandLineArgs.PrintUsage(); | ||
return; | ||
} | ||
|
||
var settings = CommandLineArgs.CreateSettingsObject(args); | ||
|
||
CommandLineArgs.ParseCommandLineArguments(settings.Item1, settings.Item2, args); | ||
|
||
|
||
string text = reader.ReadText(settings.Item2.textFile); | ||
|
||
analyzer.Analyze(text); | ||
|
||
var center = new Point(settings.Item1.Size.Width / 2, settings.Item1.Size.Height / 2); | ||
|
||
var pointsProvider = new SpiralPointsProvider(center); | ||
|
||
var layouter = new TagsCloudLayouter(center, pointsProvider, settings.Item1, analyzer.GetAnalyzedText()); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
|
||
layouter.ToImage().Save(settings.Item2.outImagePath); | ||
Console.WriteLine("Resulting image saved to " + settings.Item2.outImagePath); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"profiles": { | ||
"TagsCloudContainer": { | ||
"commandName": "Project", | ||
"commandLineArgs": "sample.txt -font Calibri -size 500 500 -out testout.png" | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace TagsCloudContainer.SettingsClasses | ||
{ | ||
public class AppSettings | ||
{ | ||
public string textFile; | ||
|
||
public string outImagePath = "cloud.png"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Drawing; | ||
using TagsCloudVisualization; | ||
|
||
namespace TagsCloudContainer.SettingsClasses | ||
{ | ||
public class CloudDrawingSettings | ||
{ | ||
public FontFamily FontFamily = new FontFamily("Arial"); | ||
public float FontSize = 12; | ||
public IList<Color> Colors = new List<Color>() { Color.AliceBlue }; | ||
public Size Size = new Size(600, 600); | ||
public IPointsProvider PointsProvider; | ||
|
||
public CloudDrawingSettings() | ||
{ | ||
|
||
} | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Drawing; | ||
|
||
namespace TagsCloudVisualization | ||
{ | ||
public interface IPointsProvider | ||
{ | ||
public IEnumerable<Point> Points(); | ||
public void Reset(); | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System.Drawing; | ||
using TagsCloudVisualization; | ||
|
||
namespace TagsCloudContainer.TagCloudBuilder | ||
{ | ||
public class RandomPointsProvider : IPointsProvider | ||
{ | ||
private Random rnd = new Random(); | ||
private readonly Point Center; | ||
private int pointNumber = 0; | ||
|
||
public RandomPointsProvider(Point center) | ||
{ | ||
Center = center; | ||
} | ||
|
||
public IEnumerable<Point> Points() | ||
{ | ||
while (pointNumber < 10000000) // Limit number of returned points for safety reason | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
{ | ||
yield return new Point(rnd.Next(0, Center.X * 2), rnd.Next(0, Center.Y * 2)); | ||
} | ||
throw new ArgumentException("Reach end of placing points"); | ||
} | ||
|
||
public void Reset() | ||
{ | ||
rnd = new Random(); | ||
pointNumber = 0; | ||
} | ||
} | ||
} |
This comment was marked as resolved.
Sorry, something went wrong.