diff --git a/FinalExercise/Blocks.cpp b/FinalExercise/Blocks.cpp new file mode 100644 index 0000000..6583cc5 --- /dev/null +++ b/FinalExercise/Blocks.cpp @@ -0,0 +1,112 @@ +#include "pch.h" +#include "Blocks.h" +#include + +double identity::Calculate(const double input) +{ + return input; +} + +std::wstring identity::GetName() +{ + return L"identity"; +} + +std::wstringstream identity::GetArgumentsType() +{ + std::wstringstream ss(L"\nNo additional params"); + return ss; +} + +int identity::GetNumberOfParams() +{ + return 0; +} + +std::wstringstream identity::GetParamValues() +{ + std::wstringstream ss; + ss << "()"; + return ss; +} + +addition::addition(const double a) : BlockWithOneParam(a) +{ +} + +double addition::Calculate(const double input) +{ + return input + param; +} + +std::wstring addition::GetName() +{ + return L"addition"; +} + +multiplication::multiplication(double a) : BlockWithOneParam(a) +{ +} + +double multiplication::Calculate(const double input) +{ + return input * param; +} + +std::wstring multiplication::GetName() +{ + return L"multiplication"; +} + +power::power(double a) : BlockWithOneParam(a) +{ +} + +double power::Calculate(const double input) +{ + return std::pow(input, param); +} + +std::wstring power::GetName() +{ + return L"power"; +} + +limit::limit(double a, double b) : BlockWithTwoParams(a, b) +{ +} + +double limit::Calculate(const double input) +{ + return std::clamp(input, param1, param2); +} + +std::wstring limit::GetName() +{ + return L"limit"; +} + +condition::condition(double a) : BlockWithOneParam(a) +{ +} + +double condition::Calculate(const double input) +{ + if (input == param) + { + return 0; + } + else if (input < param) + { + return -1; + } + else + { + return 1; + } +} + +std::wstring condition::GetName() +{ + return L"condition"; +} diff --git a/FinalExercise/Blocks.h b/FinalExercise/Blocks.h new file mode 100644 index 0000000..a0b016e --- /dev/null +++ b/FinalExercise/Blocks.h @@ -0,0 +1,143 @@ +#pragma once +#include + +class Block +{ +public: + virtual ~Block() = default; + + virtual double Calculate(double input) = 0; + virtual std::wstring GetName() = 0; + virtual std::wstringstream GetArgumentsType() = 0; + virtual int GetNumberOfParams() = 0; + virtual std::wstringstream GetParamValues() = 0; +}; + +template +class BlockWithOneParam : public Block +{ +public: + + BlockWithOneParam(T a) : param(a) + { + } + std::wstringstream GetArgumentsType() override + { + std::wstringstream ss; + ss << "\nAdd 1 additional argument:" << + "\nargument type " << typeid(param).name() << std::endl; + return ss; + } + + int GetNumberOfParams() override + { + return 1; + } + + std::wstringstream GetParamValues() override + { + std::wstringstream ss; + ss << "(" << param << ")"; + return ss; + } + +protected: + T param; +}; + +template +class BlockWithTwoParams : public Block +{ +public: + BlockWithTwoParams(T1 a, T2 b) : param1(a), param2(b) + { + } + + std::wstringstream GetArgumentsType() override + { + std::wstringstream ss; + ss << "\nAdd 2 additional arguments:" << + "\n1. argument type " << typeid(param1).name() << + "\n2. argument type " << typeid(param2).name() << std::endl; + return ss; + } + + int GetNumberOfParams() override + { + return 2; + } + + std::wstringstream GetParamValues() override + { + std::wstringstream ss; + ss << "(" << param1 << ", " << param2 << ")"; + return ss; + } + +protected: + T1 param1; + T2 param2; +}; + +class identity : public Block +{ +public: + double Calculate(double input) override; + std::wstring GetName() override; + std::wstringstream GetArgumentsType() override; + int GetNumberOfParams() override; + std::wstringstream GetParamValues() override; +}; + +class addition : public BlockWithOneParam +{ +public: + addition(double a); + double Calculate(double input) override; + std::wstring GetName() override; +}; + +class multiplication : public BlockWithOneParam +{ +public: + multiplication(double a); + double Calculate(double input) override; + std::wstring GetName() override; +}; + +class power : public BlockWithOneParam +{ +public: + power(double a); + double Calculate(double input) override; + std::wstring GetName() override; +}; + +class limit : public BlockWithTwoParams +{ +public: + limit(double a, double b); + double Calculate(double input) override; + std::wstring GetName() override; +}; + +class condition : public BlockWithOneParam +{ +public: + condition(double a); + double Calculate(double input) override; + std::wstring GetName() override; +}; + +enum class BlockId +{ + identity = 1, + addition = 2, + multiplication = 3, + power = 4, + limit = 5, + condition = 6 +}; + +const BlockId BlockIds[] = { BlockId::identity, BlockId::addition, BlockId::multiplication, + BlockId::power, BlockId::limit, BlockId::condition }; diff --git a/FinalExercise/Factory.cpp b/FinalExercise/Factory.cpp new file mode 100644 index 0000000..1c78802 --- /dev/null +++ b/FinalExercise/Factory.cpp @@ -0,0 +1,217 @@ +#include "pch.h" +#include "Factory.h" +#include +#include +#include + +void StreamToConsole(const std::wostream& stream) +{ + std::wcout << stream.rdbuf() << std::endl; +} + +factory::factory() : seq(), availableBlocks(), + userCommandsMessage("0 = display sequence\n" + "1 = add block\n" + "2 = delete block\n" + "3 = move desired block to begin\n" + "4 = insert input value and evaluate through sequence\n" + "5 = insert file name with input values, evaluate for each input and store result to file \n\n") +{ + fillAvailableBlocks(); +} + +std::string factory::GetUserCommandsMessage() +{ + return userCommandsMessage; +} + +std::unique_ptr factory::block_factory(const BlockId id, const std::vector& params) +{ + switch (id) + { + case BlockId::identity: + return std::make_unique(); + case BlockId::addition: + return std::make_unique(params[0]); + case BlockId::multiplication: + return std::make_unique(params[0]); + case BlockId::power: + return std::make_unique(params[0]); + case BlockId::limit: + return std::make_unique(params[0], params[1]); + case BlockId::condition: + return std::make_unique(params[0]); + default: + return nullptr; + } +} + +std::string factory::run(const int input) +{ + std::string userMessage; + bool save = false; + switch (input) + { + case 0: + userMessage = CaseDisplaySequence(); + break; + case 1: + userMessage = CaseAddBlock(); + save = true; + break; + case 2: + userMessage = CaseDeleteBlock(); + save = true; + break; + case 3: + userMessage = CaseMoveToBegin(); + save = true; + break; + case 4: + userMessage = CaseExecuteSequence(); + break; + case 5: + userMessage = CaseExecuteSequenceFromFile(); + break; + default: + std::string message("\nUndefined input value, please enter valid command \n\n"); + userMessage = message.append(userCommandsMessage); + break; + } + + if (save) + { + SaveSequenceToFile(); + } + + return userMessage; +} + +void factory::fillAvailableBlocks() +{ + std::wstringstream ss; + ss << "Available blocks: " << std::endl; + std::vector v = { 0.0, 0.0 }; + for (auto it = std::begin(BlockIds); it != std::end(BlockIds); ++it) + { + availableBlocks[*it] = block_factory(*it, v); + ss << static_cast(*it) << " - " << + availableBlocks[*it]->GetName() << std::endl; + } + + availableBlocksMessage = ss.str(); +} + +std::string factory::CaseDisplaySequence() +{ + std::wstringstream stream = seq.displaySequence(); + StreamToConsole(stream); + + return std::string("\nSequence displayed \n\n"); +} + +std::pair factory::requestAdditionalParams(const int id) +{ + int num = 0; + std::wstringstream ss(L""); + auto it = availableBlocks.find(static_cast(id)); + if (it != availableBlocks.end()) + { + ss = it->second->GetArgumentsType(); + num = it->second->GetNumberOfParams(); + } + else + { + ss << L"Block with id " << id << " doesn't exist!" << std::endl; + } + + return std::make_pair(num, ss.str()); +} + +std::string factory::CaseAddBlock() +{ + std::wcout << availableBlocksMessage; + + int id; + std::cin >> id; + + std::pair pair = requestAdditionalParams(id); + std::wcout << pair.second; + + // store additional params to vector and call block_factory + std::vector v; + double param; + for (int i = 0; i < pair.first; ++i) + { + std::cin >> param; + v.push_back(param); + } + + seq.addBlock(block_factory(static_cast(id), v)); + + return std::string("\nBlock added \n\n"); +} + +std::string factory::CaseDeleteBlock() +{ + std::cout << "\nEnter index of the block in the sequence that will be deleted\n"; + int index; + std::cin >> index; + + bool ok = seq.deleteBlock(index); + std::string message = ok ? "\nBlock deleted \n\n" : + "\nBlock with entered index doesn't exist \n\n"; + + return message; +} + +std::string factory::CaseMoveToBegin() +{ + std::cout << "\nEnter index of block that will be moved to begin\n"; + + int index; + std::cin >> index; + bool ok = seq.moveToBegin(index); + std::string message = ok ? "\nSelected block moved to begin \n\n" : + "\nBlock with entered index doesn't exist \n\n"; + + return message; +} + +std::string factory::CaseExecuteSequence() +{ + std::cout << "\nInsert input value for sequence evaluation" << std::endl; + double value; + std::cin >> value; + value = seq.executeSequence(value); + std::cout << "\nResult = " << value << std::endl; + + return std::string("\nInput value evaluated through sequence \n\n"); +} + +std::string factory::CaseExecuteSequenceFromFile() +{ + std::cout << "\nEnter file name with input values:\n"; + + std::wstring file; + std::wcin >> file; + + bool ok = seq.executeSequenceFromFile(file); + + std::string message = ok ? "\nSequence executed with values from selected file and result stored in Results.txt \n\n" + : "\nFile with input values not found!"; + + return message; +} + +void factory::SaveSequenceToFile() +{ + std::wstringstream stream = seq.displaySequence(); + + std::wofstream f("Sequence.txt"); + std::wstring s; + while (stream >> s) + { + f << s << std::endl; + } +} diff --git a/FinalExercise/Factory.h b/FinalExercise/Factory.h new file mode 100644 index 0000000..e87d1b5 --- /dev/null +++ b/FinalExercise/Factory.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include +#include "Sequence.h" + +class factory +{ +public: + factory(); + std::string run(const int input); + std::string GetUserCommandsMessage(); + +private: + Sequence seq; + std::map> availableBlocks; + std::wstring availableBlocksMessage; + std::string userCommandsMessage; + + std::unique_ptr block_factory(const BlockId id, const std::vector& params); + void fillAvailableBlocks(); + std::pair requestAdditionalParams(const int id); + + std::string CaseDisplaySequence(); + std::string CaseAddBlock(); + std::string CaseDeleteBlock(); + std::string CaseMoveToBegin(); + std::string CaseExecuteSequence(); + std::string CaseExecuteSequenceFromFile(); + + void SaveSequenceToFile(); +}; + +void StreamToConsole(const std::wostream& stream); diff --git a/FinalExercise/FinalExercise.cpp b/FinalExercise/FinalExercise.cpp new file mode 100644 index 0000000..067fec5 Binary files /dev/null and b/FinalExercise/FinalExercise.cpp differ diff --git a/FinalExercise/FinalExercise.vcxproj b/FinalExercise/FinalExercise.vcxproj new file mode 100644 index 0000000..190b5a8 --- /dev/null +++ b/FinalExercise/FinalExercise.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {0B6AE6AF-1ED5-440F-BEFB-ACE5B590D117} + Win32Proj + FinalExercise + 10.0.17134.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + + + Console + true + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + + + Console + true + true + true + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/FinalExercise/FinalExercise.vcxproj.filters b/FinalExercise/FinalExercise.vcxproj.filters new file mode 100644 index 0000000..8fce3bc --- /dev/null +++ b/FinalExercise/FinalExercise.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/FinalExercise/Inputs.txt b/FinalExercise/Inputs.txt new file mode 100644 index 0000000..8da1224 --- /dev/null +++ b/FinalExercise/Inputs.txt @@ -0,0 +1,13 @@ +10.0 +250.5 +5 +27.9 +45.66 +389.4 +879.7 +999 +1300 +455.66 +28.2 +800 +1646.9 \ No newline at end of file diff --git a/FinalExercise/Results.txt b/FinalExercise/Results.txt new file mode 100644 index 0000000..799f71c --- /dev/null +++ b/FinalExercise/Results.txt @@ -0,0 +1,13 @@ +231 +400 +231 +231 +325 +400 +400 +400 +400 +400 +231 +400 +400 diff --git a/FinalExercise/Sequence.cpp b/FinalExercise/Sequence.cpp new file mode 100644 index 0000000..8d3d16e --- /dev/null +++ b/FinalExercise/Sequence.cpp @@ -0,0 +1,86 @@ +#include "pch.h" +#include "Sequence.h" +#include +#include + +Sequence::Sequence() : blocks() +{ +} + +void Sequence::addBlock(std::unique_ptr block) +{ + blocks.push_back(std::move(block)); +} + +double Sequence::executeSequence(double input) +{ + for (auto i = blocks.cbegin(); i != blocks.cend(); ++i) + { + input = (*i)->Calculate(input); + } + + return input; +} + +bool Sequence::deleteBlock(int index) +{ + --index; + bool ok = false; + if (index < blocks.size() && index >= 0) + { + blocks.erase(blocks.begin() + index); + ok = true; + } + + return ok; +} + +bool Sequence::moveToBegin(int index) +{ + --index; + bool ok = false; + if (index < blocks.size() && index >= 0) + { + std::rotate(blocks.begin(), blocks.begin()+index, blocks.begin()+index+1); + ok = true; + } + return ok; +} + +std::wstringstream Sequence::displaySequence() +{ + std::wstringstream stream(L""); + stream << "Sequence:" << '\n'; + int index = 1; + + for (auto i = blocks.cbegin(); i != blocks.cend(); ++i) + { + stream << index << "." << (*i)->GetName() << (*i)->GetParamValues().str() << " "; + + index++; + } + + return stream; +} + +bool Sequence::executeSequenceFromFile(const std::wstring& file) +{ + std::ifstream f(file); + std::istream_iterator in(f), ends; + std::vector inputs; + std::copy(in, ends, std::back_inserter(inputs)); + + if (inputs.size() == 0) + { + return false; + } + + std::ofstream outFile("Results.txt"); + for(auto it = inputs.begin(); it != inputs.end(); ++it) + { + double output = executeSequence(*it); + outFile << output << std::endl; + } + + return true; +} diff --git a/FinalExercise/Sequence.h b/FinalExercise/Sequence.h new file mode 100644 index 0000000..5b7ec90 --- /dev/null +++ b/FinalExercise/Sequence.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include "Blocks.h" + +class Sequence +{ +public: + Sequence(); + void addBlock(std::unique_ptr); + double executeSequence(double input); + bool deleteBlock(int index); + bool moveToBegin(int index); + std::wstringstream displaySequence(); + bool executeSequenceFromFile(const std::wstring& file); + +private: + std::vector> blocks; +}; diff --git a/FinalExercise/Sequence.txt b/FinalExercise/Sequence.txt new file mode 100644 index 0000000..dd568eb --- /dev/null +++ b/FinalExercise/Sequence.txt @@ -0,0 +1,12 @@ +Sequence: +1.limit(10.5, +1500) +2.condition(45.66) +3.multiplication(2) +4.addition(10.4) +5.power(2) +6.identity() +7.multiplication(2.5) +8.addition(54.6) +9.limit(10.5, +400) diff --git a/FinalExercise/pch.cpp b/FinalExercise/pch.cpp new file mode 100644 index 0000000..a38f8a3 Binary files /dev/null and b/FinalExercise/pch.cpp differ diff --git a/FinalExercise/pch.h b/FinalExercise/pch.h new file mode 100644 index 0000000..d87432d Binary files /dev/null and b/FinalExercise/pch.h differ diff --git a/UnitTests/UnitTests.vcxproj b/UnitTests/UnitTests.vcxproj new file mode 100644 index 0000000..071a372 --- /dev/null +++ b/UnitTests/UnitTests.vcxproj @@ -0,0 +1,186 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {944ADC78-92E9-45A2-AA22-0D83E3B92BC6} + Win32Proj + UnitTests + 10.0.17134.0 + NativeUnitTestProject + + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + DynamicLibrary + true + v141 + Unicode + false + + + DynamicLibrary + false + v141 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + + NotUsing + Level3 + Disabled + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + stdcpp17 + + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + NotUsing + Level3 + Disabled + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + true + stdcpp17 + + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + NotUsing + MaxSpeed + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + stdcpp17 + + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Level3 + NotUsing + MaxSpeed + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + stdcpp17 + + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + NotUsing + + + NotUsing + + + NotUsing + + + NotUsing + + + + + + + + \ No newline at end of file diff --git a/UnitTests/UnitTests.vcxproj.filters b/UnitTests/UnitTests.vcxproj.filters new file mode 100644 index 0000000..0167980 --- /dev/null +++ b/UnitTests/UnitTests.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {eadd901c-c19c-4afe-9b19-4bdc1bfe2603} + + + + + Header Files + + + Code + + + + + Source Files + + + Code + + + \ No newline at end of file diff --git a/UnitTests/targetver.h b/UnitTests/targetver.h new file mode 100644 index 0000000..90e767b --- /dev/null +++ b/UnitTests/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/UnitTests/test.cpp b/UnitTests/test.cpp new file mode 100644 index 0000000..d4ebcce --- /dev/null +++ b/UnitTests/test.cpp @@ -0,0 +1,71 @@ +#include "CppUnitTest.h" +#include "../FinalExercise/Blocks.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +TEST_CLASS(test_blocks) +{ +public: + + TEST_METHOD(IdentityBlock) + { + identity i; + double result = i.Calculate(5.6); + Assert::AreEqual(5.6, result); + Assert::AreEqual(std::wstring(L"identity"), i.GetName()); + Assert::AreEqual(0, i.GetNumberOfParams()); + } + + TEST_METHOD(additionBlock) + { + addition a(115.5); + double result = a.Calculate(10.0); + Assert::AreEqual(125.5, result); + Assert::AreEqual(std::wstring(L"addition"), a.GetName()); + Assert::AreEqual(1, a.GetNumberOfParams()); + } + + TEST_METHOD(multiplicationBlock) + { + multiplication m(2.5); + double result = m.Calculate(10.0); + Assert::AreEqual(25.0, result); + Assert::AreEqual(std::wstring(L"multiplication"), m.GetName()); + Assert::AreEqual(1, m.GetNumberOfParams()); + } + + TEST_METHOD(powerBlock) + { + power p(3.0); + double result = p.Calculate(5.0); + Assert::AreEqual(125.0, result); + Assert::AreEqual(std::wstring(L"power"), p.GetName()); + Assert::AreEqual(1, p.GetNumberOfParams()); + } + + TEST_METHOD(limitBlock) + { + limit l(10.0, 550.0); + double result = l.Calculate(200.7); + Assert::AreEqual(200.7, result); + result = l.Calculate(0.0); + Assert::AreEqual(10.0, result); + result = l.Calculate(1000.0); + Assert::AreEqual(550.0, result); + Assert::AreEqual(std::wstring(L"limit"), l.GetName()); + Assert::AreEqual(2, l.GetNumberOfParams()); + } + + TEST_METHOD(conditionBlock) + { + condition c(105.5); + double result = c.Calculate(40.0); + Assert::AreEqual(-1.0, result); + result = c.Calculate(105.5); + Assert::AreEqual(0.0, result); + result = c.Calculate(5555.5); + Assert::AreEqual(1.0, result); + Assert::AreEqual(std::wstring(L"condition"), c.GetName()); + Assert::AreEqual(1, c.GetNumberOfParams()); + } +};