diff --git a/checkAmount/checkAmount.sln b/checkAmount/checkAmount.sln
new file mode 100644
index 0000000..528815a
--- /dev/null
+++ b/checkAmount/checkAmount.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.13.35806.99 d17.13
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CheckAmount", "checkAmount\CheckAmount.csproj", "{1AB54304-E937-42B8-929C-533823038651}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1AB54304-E937-42B8-929C-533823038651}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1AB54304-E937-42B8-929C-533823038651}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1AB54304-E937-42B8-929C-533823038651}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1AB54304-E937-42B8-929C-533823038651}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {06282FD8-DD37-410B-853D-14580665948A}
+ EndGlobalSection
+EndGlobal
diff --git a/checkAmount/checkAmount/CheckAmount.csproj b/checkAmount/checkAmount/CheckAmount.csproj
new file mode 100644
index 0000000..d764014
--- /dev/null
+++ b/checkAmount/checkAmount/CheckAmount.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git "a/checkAmount/checkAmount/CheckAmount\320\241alculator.cs" "b/checkAmount/checkAmount/CheckAmount\320\241alculator.cs"
new file mode 100644
index 0000000..f7ae808
--- /dev/null
+++ "b/checkAmount/checkAmount/CheckAmount\320\241alculator.cs"
@@ -0,0 +1,168 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+namespace CheckAmount;
+
+using System.Security.Cryptography;
+using System.Text;
+
+///
+/// Calculates the checksum (hash amount) for a given file or directory structure.
+///
+public class CheckAmountСalculator
+{
+ private const int BufferSize = 4096;
+
+ ///
+ /// Initiates the single-threaded checksum calculation.
+ ///
+ /// The path to the file or directory.
+ /// The MD5 hash.
+ /// Thrown if the path does not exist.
+ public string Calculate(string path)
+ {
+ byte[] hashBytes;
+
+ if (File.Exists(path))
+ {
+ hashBytes = this.CalculateFileCheckAmount(path);
+ }
+ else if (Directory.Exists(path))
+ {
+ hashBytes = this.CalculateDirectoryCheckAmount(path);
+ }
+ else
+ {
+ throw new FileNotFoundException("Путь не найден");
+ }
+
+ return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
+ }
+
+ ///
+ /// Initiates the multi-threaded checksum calculation for directories.
+ ///
+ /// The path to the file or directory.
+ /// The MD5 hash.
+ /// Thrown if the path does not exist.
+ public string CalculateMultiThreaded(string path)
+ {
+ byte[] hashBytes;
+
+ if (File.Exists(path))
+ {
+ hashBytes = this.CalculateFileCheckAmount(path);
+ }
+ else if (Directory.Exists(path))
+ {
+ hashBytes = this.CalculateDirectoryAmountThreaded(path);
+ }
+ else
+ {
+ throw new FileNotFoundException("Путь не найден");
+ }
+
+ return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
+ }
+
+ private byte[] CalculateFileCheckAmount(string filePath)
+ {
+ string fileName = Path.GetFileName(filePath);
+ byte[] fileNameBytes = Encoding.UTF8.GetBytes(fileName);
+ using (MD5 md = MD5.Create())
+ using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ md.TransformBlock(fileNameBytes, 0, fileNameBytes.Length, fileNameBytes, 0);
+
+ byte[] buffer = new byte[BufferSize];
+ int bytesRead;
+
+ while ((bytesRead = fileStream.Read(buffer, 0, BufferSize)) > 0)
+ {
+ md.TransformBlock(buffer, 0, bytesRead, buffer, 0);
+ }
+
+ md.TransformFinalBlock(new byte[0], 0, 0);
+ return md.Hash!;
+ }
+ }
+
+ private byte[] CalculateDirectoryCheckAmount(string dirPath)
+ {
+ string dirName = new DirectoryInfo(dirPath).Name;
+ byte[] dirNameBytes = Encoding.UTF8.GetBytes(dirName);
+
+ string[] subDirs = Directory.GetDirectories(dirPath);
+ string[] files = Directory.GetFiles(dirPath);
+
+ Array.Sort(subDirs);
+ Array.Sort(files);
+
+ using (MemoryStream stream = new MemoryStream())
+ {
+ stream.Write(dirNameBytes, 0, dirNameBytes.Length);
+
+ foreach (string subDir in subDirs)
+ {
+ byte[] subDirHash = this.CalculateDirectoryCheckAmount(subDir);
+ stream.Write(subDirHash, 0, subDirHash.Length);
+ }
+
+ foreach (string file in files)
+ {
+ byte[] fileHash = this.CalculateFileCheckAmount(file);
+ stream.Write(fileHash, 0, fileHash.Length);
+ }
+
+ stream.Position = 0;
+ using (MD5 md = MD5.Create())
+ {
+ return md.ComputeHash(stream);
+ }
+ }
+ }
+
+ private byte[] CalculateDirectoryAmountThreaded(string dirPath)
+ {
+ string dirName = new DirectoryInfo(dirPath).Name;
+ byte[] dirNameBytes = Encoding.UTF8.GetBytes(dirName);
+
+ string[] subDirs = Directory.GetDirectories(dirPath);
+ string[] files = Directory.GetFiles(dirPath);
+
+ Array.Sort(subDirs);
+ Array.Sort(files);
+
+ List> tasks = new List>();
+
+ foreach (string subDir in subDirs)
+ {
+ tasks.Add(Task.Run(() => this.CalculateDirectoryAmountThreaded(subDir)));
+ }
+
+ foreach (string file in files)
+ {
+ tasks.Add(Task.Run(() => this.CalculateFileCheckAmount(file)));
+ }
+
+ Task.WaitAll(tasks.ToArray());
+
+ using (MemoryStream stream = new MemoryStream())
+ {
+ stream.Write(dirNameBytes, 0, dirNameBytes.Length);
+
+ foreach (Task task in tasks)
+ {
+ byte[] resultHash = task.Result;
+ stream.Write(resultHash, 0, resultHash.Length);
+ }
+
+ stream.Position = 0;
+ using (MD5 md = MD5.Create())
+ {
+ return md.ComputeHash(stream);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/checkAmount/checkAmount/Program.cs b/checkAmount/checkAmount/Program.cs
new file mode 100644
index 0000000..807a042
--- /dev/null
+++ b/checkAmount/checkAmount/Program.cs
@@ -0,0 +1,27 @@
+//
+// Copyright (c) Kalinin Andrew. All rights reserved.
+//
+
+using System.Diagnostics;
+using CheckAmount;
+
+string testDir = @"..\..\..\TestDir";
+
+Stopwatch sw = new Stopwatch();
+CheckAmountСalculator calculator = new CheckAmountСalculator();
+
+sw.Start();
+string checkAmountOneThread = calculator.Calculate(testDir);
+sw.Stop();
+long timeOne = sw.ElapsedMilliseconds;
+Console.WriteLine($"Хеш: {checkAmountOneThread}");
+Console.WriteLine($"Время(однопоточный запуск): {timeOne} мс");
+
+sw.Restart();
+string checkAmountMulti = calculator.CalculateMultiThreaded(testDir);
+sw.Stop();
+long timeMulti = sw.ElapsedMilliseconds;
+Console.WriteLine($"Хеш: {checkAmountMulti}");
+Console.WriteLine($"Время(однопоточный запуск): {timeMulti} мс");
+
+Console.WriteLine($"Хеши совпадают {checkAmountMulti == checkAmountOneThread}");
\ No newline at end of file
diff --git a/checkAmount/checkAmount/TestDir/SubDir/TestFileInSubDir.txt b/checkAmount/checkAmount/TestDir/SubDir/TestFileInSubDir.txt
new file mode 100644
index 0000000..53c33d5
--- /dev/null
+++ b/checkAmount/checkAmount/TestDir/SubDir/TestFileInSubDir.txt
@@ -0,0 +1 @@
+dajskdhasjkdhfsdkfnkdsngkdfnfk;fksdfnkjsdfhkjdsnfksdanfskl
\ No newline at end of file
diff --git a/checkAmount/checkAmount/TestDir/TestFileInTestDir.txt b/checkAmount/checkAmount/TestDir/TestFileInTestDir.txt
new file mode 100644
index 0000000..bda685a
--- /dev/null
+++ b/checkAmount/checkAmount/TestDir/TestFileInTestDir.txt
@@ -0,0 +1 @@
+dasdasfgfdgsddsfbskdfns
\ No newline at end of file
diff --git a/checkAmount/checkAmount/stylecop.json b/checkAmount/checkAmount/stylecop.json
new file mode 100644
index 0000000..c7ed419
--- /dev/null
+++ b/checkAmount/checkAmount/stylecop.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "documentationRules": {
+ "companyName": "Kalinin Andrew"
+ }
+ }
+}