diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml old mode 100755 new mode 100644 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..665b2882 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.vs/ +out/ +build/ +cmake-build-*/ +*.ipch +*.db +*.log +.DS_Store +*.suo +*.user diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index f83009ea..b0b0548a --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,27 @@ -cmake_minimum_required (VERSION 3.10.2) -project (ST-2) +cmake_minimum_required(VERSION 3.10.2) +project(ST-2) set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -g") - set(tool_dest "bin") set(lib_dest "lib") set(include_dest "include/") +# Отключаем pthread на Windows +if(WIN32) + set(gtest_disable_pthreads ON) + add_definitions(-DGTEST_HAS_PTHREAD=0) +endif() + +# Подключаем Google Test +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 +) +FetchContent_MakeAvailable(googletest) + add_subdirectory(src) -add_subdirectory(test) +add_subdirectory(test) \ No newline at end of file diff --git a/include/circle.h b/include/circle.h index 50ac03e6..4f87713f 100644 --- a/include/circle.h +++ b/include/circle.h @@ -1,7 +1,23 @@ -// Copyright 2022 UNN-CS +// Copyright 2025 UNN-CS #ifndef INCLUDE_CIRCLE_H_ #define INCLUDE_CIRCLE_H_ -#include +class Circle { + private: + double radius_; + double ference_; + double area_; -#endif // INCLUDE_CIRCLE_H_ + public: + explicit Circle(double radius); + + double getRadius() const; + double getFerence() const; + double getArea() const; + + void setRadius(double radius); + void setFerence(double ference); + void setArea(double area); +}; + +#endif // INCLUDE_CIRCLE_H_ \ No newline at end of file diff --git a/include/tasks.h b/include/tasks.h new file mode 100644 index 00000000..2ccb713c --- /dev/null +++ b/include/tasks.h @@ -0,0 +1,9 @@ +// include/tasks.h +#ifndef INCLUDE_TASKS_H_ +#define INCLUDE_TASKS_H_ + +double earthRopeGap(); +double poolConcreteCost(); +double poolFenceCost(); + +#endif // INCLUDE_TASKS_H_ \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt old mode 100755 new mode 100644 index e3405007..54b7a9e7 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,30 +1,33 @@ set(header_path "${${PROJECT_NAME}_SOURCE_DIR}/include") -set(header ${header_path}/circle.h) -set(src circle.cpp) +set(header + ${header_path}/circle.h + ${header_path}/tasks.h) # tasks.h добавлен +set(src + circle.cpp + tasks.cpp) # tasks.cpp добавлен add_library(${PROJECT_NAME} SHARED - ${header} - ${src}) + ${header} + ${src}) target_include_directories(${PROJECT_NAME} - PUBLIC ${CMAKE_CURRENT_BINARY_DIR} - ${${PROJECT_NAME}_SOURCE_DIR}/include) + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} + ${${PROJECT_NAME}_SOURCE_DIR}/include) target_link_libraries(${PROJECT_NAME} - pthread) + pthread) add_executable(${PROJECT_NAME}.info main.cpp) target_include_directories(${PROJECT_NAME}.info - PUBLIC ${CMAKE_CURRENT_BINARY_DIR} - ${${PROJECT_NAME}_SOURCE_DIR}/include) + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} + ${${PROJECT_NAME}_SOURCE_DIR}/include) target_link_libraries(${PROJECT_NAME}.info - ${PROJECT_NAME}) - + ${PROJECT_NAME}) install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION "${lib_dest}" + LIBRARY DESTINATION "${lib_dest}" ARCHIVE DESTINATION "${lib_dest}" COMPONENT library) install(TARGETS ${PROJECT_NAME}.info - RUNTIME DESTINATION "${tool_dest}" + RUNTIME DESTINATION "${tool_dest}" COMPONENT library) -install(FILES ${header} DESTINATION "${include_dest}") +install(FILES ${header} DESTINATION "${include_dest}") \ No newline at end of file diff --git a/src/circle.cpp b/src/circle.cpp index 9b0d134d..4146df02 100644 --- a/src/circle.cpp +++ b/src/circle.cpp @@ -1,4 +1,41 @@ -// Copyright 2022 UNN-CS -#include +// Copyright 2025 UNN-CS #include "circle.h" +#include +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +Circle::Circle(double radius) { + setRadius(radius); +} + +double Circle::getRadius() const { + return radius_; +} + +double Circle::getFerence() const { + return ference_; +} + +double Circle::getArea() const { + return area_; +} + +void Circle::setRadius(double radius) { + radius_ = radius; + ference_ = 2.0 * M_PI * radius_; + area_ = M_PI * radius_ * radius_; +} + +void Circle::setFerence(double ference) { + ference_ = ference; + radius_ = ference_ / (2.0 * M_PI); + area_ = M_PI * radius_ * radius_; +} + +void Circle::setArea(double area) { + area_ = area; + radius_ = std::sqrt(area_ / M_PI); + ference_ = 2.0 * M_PI * radius_; +} \ No newline at end of file diff --git a/src/tasks.cpp b/src/tasks.cpp new file mode 100644 index 00000000..9381c157 --- /dev/null +++ b/src/tasks.cpp @@ -0,0 +1,32 @@ +// src/tasks.cpp +#include "tasks.h" +#include "circle.h" +#include + +double earthRopeGap() { + const double earthRadius = 6378100.0; // 6378.1 км в метрах + Circle earth(earthRadius); + double oldFerence = earth.getFerence(); + earth.setFerence(oldFerence + 1.0); + return earth.getRadius() - earthRadius; +} + +double poolConcreteCost() { + const double poolRadius = 3.0; + const double pathWidth = 1.0; + const double concretePrice = 1000.0; + + Circle pool(poolRadius); + Circle outer(poolRadius + pathWidth); + double pathArea = outer.getArea() - pool.getArea(); + return pathArea * concretePrice; +} + +double poolFenceCost() { + const double poolRadius = 3.0; + const double pathWidth = 1.0; + const double fencePrice = 2000.0; + + Circle outer(poolRadius + pathWidth); + return outer.getFerence() * fencePrice; +} \ No newline at end of file diff --git a/test/AllTests.cpp b/test/AllTests.cpp old mode 100755 new mode 100644 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt old mode 100755 new mode 100644 index 1bbc8537..ee9f667a --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,10 +1,14 @@ add_executable(${PROJECT_NAME}.test - AllTests.cpp - tests.cpp) + tests.cpp) + target_link_libraries(${PROJECT_NAME}.test - ${PROJECT_NAME} gtest pthread) + ${PROJECT_NAME} + gtest_main) + target_compile_definitions(${PROJECT_NAME}.test - PRIVATE TEST_DIR="${CMAKE_CURRENT_LIST_DIR}/test") + PRIVATE TEST_DIR="${CMAKE_CURRENT_LIST_DIR}") + +add_test(NAME ${PROJECT_NAME}_tests COMMAND ${PROJECT_NAME}.test) install(TARGETS ${PROJECT_NAME}.test - DESTINATION "${tool_dest}") + RUNTIME DESTINATION "${tool_dest}") \ No newline at end of file diff --git a/test/tests.cpp b/test/tests.cpp index fc3f9336..f397d0d3 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -1,7 +1,195 @@ -// Copyright 2025 UNN-CS Team + +// Copyright 2025 UNN-CS #include -#include #include "circle.h" +#include "tasks.h" +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// ------------------ Тесты класса Circle ------------------ + +TEST(CircleTest, ConstructorAndGetters) { + Circle c(5.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 5.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 2.0 * M_PI * 5.0); + EXPECT_DOUBLE_EQ(c.getArea(), M_PI * 25.0); +} + +TEST(CircleTest, SetRadiusUpdatesFerenceAndArea) { + Circle c(1.0); + c.setRadius(3.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 3.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 2.0 * M_PI * 3.0); + EXPECT_DOUBLE_EQ(c.getArea(), M_PI * 9.0); +} + +TEST(CircleTest, SetFerenceUpdatesRadiusAndArea) { + Circle c(1.0); + double newFerence = 4.0 * M_PI; + c.setFerence(newFerence); + EXPECT_DOUBLE_EQ(c.getFerence(), newFerence); + EXPECT_DOUBLE_EQ(c.getRadius(), 2.0); // L=4? ? R=2 + EXPECT_DOUBLE_EQ(c.getArea(), M_PI * 4.0); +} + +TEST(CircleTest, SetAreaUpdatesRadiusAndFerence) { + Circle c(1.0); + double newArea = 9.0 * M_PI; + c.setArea(newArea); + EXPECT_DOUBLE_EQ(c.getArea(), newArea); + EXPECT_DOUBLE_EQ(c.getRadius(), 3.0); // A=9? ? R=3 + EXPECT_DOUBLE_EQ(c.getFerence(), 2.0 * M_PI * 3.0); +} + +TEST(CircleTest, ZeroRadius) { + Circle c(0.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 0.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 0.0); + EXPECT_DOUBLE_EQ(c.getArea(), 0.0); +} + +TEST(CircleTest, SetRadiusZero) { + Circle c(5.0); + c.setRadius(0.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 0.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 0.0); + EXPECT_DOUBLE_EQ(c.getArea(), 0.0); +} + +TEST(CircleTest, SetFerenceZero) { + Circle c(5.0); + c.setFerence(0.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 0.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 0.0); + EXPECT_DOUBLE_EQ(c.getArea(), 0.0); +} + +TEST(CircleTest, SetAreaZero) { + Circle c(5.0); + c.setArea(0.0); + EXPECT_DOUBLE_EQ(c.getArea(), 0.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 0.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 0.0); +} + +TEST(CircleTest, ChainedSetRadius) { + Circle c(2.0); + c.setRadius(4.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 4.0); + c.setRadius(1.0); + EXPECT_DOUBLE_EQ(c.getRadius(), 1.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 2.0 * M_PI); + EXPECT_DOUBLE_EQ(c.getArea(), M_PI); +} + +TEST(CircleTest, ChainedSetFerence) { + Circle c(1.0); + c.setFerence(2.0 * M_PI); // R=1 + EXPECT_DOUBLE_EQ(c.getRadius(), 1.0); + c.setFerence(4.0 * M_PI); // R=2 + EXPECT_DOUBLE_EQ(c.getRadius(), 2.0); + EXPECT_DOUBLE_EQ(c.getArea(), M_PI * 4.0); +} + +TEST(CircleTest, ChainedSetArea) { + Circle c(1.0); + c.setArea(M_PI); // R=1 + EXPECT_DOUBLE_EQ(c.getRadius(), 1.0); + c.setArea(4.0 * M_PI); // R=2 + EXPECT_DOUBLE_EQ(c.getRadius(), 2.0); + EXPECT_DOUBLE_EQ(c.getFerence(), 4.0 * M_PI); +} + +TEST(CircleTest, Precision) { + Circle c(1.0); + c.setRadius(1.0/3.0); + double expectedRadius = 1.0/3.0; + EXPECT_NEAR(c.getRadius(), expectedRadius, 1e-12); + EXPECT_NEAR(c.getFerence(), 2.0 * M_PI * expectedRadius, 1e-12); + EXPECT_NEAR(c.getArea(), M_PI * expectedRadius * expectedRadius, 1e-12); +} + +// ------------------ Тесты задачи "Земля и верёвка" ------------------ + +TEST(EarthRopeTest, GapPositive) { + double gap = earthRopeGap(); + EXPECT_GT(gap, 0.0); + // Теоретически зазор = 1/(2?) ? 0.159 м + EXPECT_NEAR(gap, 1.0 / (2.0 * M_PI), 1e-9); +} + +TEST(EarthRopeTest, GapIndependentOfRadius) { + // Проверим, что зазор не зависит от начального радиуса (математически) + double gap = earthRopeGap(); + // Создадим круг с другим радиусом и повторим логику вручную + double testRadius = 1000.0; + Circle testCircle(testRadius); + double oldL = testCircle.getFerence(); + testCircle.setFerence(oldL + 1.0); + double newR = testCircle.getRadius(); + double manualGap = newR - testRadius; + EXPECT_NEAR(gap, manualGap, 1e-9); +} + +// ------------------ Тесты задачи "Бассейн" ------------------ + +TEST(PoolTest, ConcreteCostPositive) { + double cost = poolConcreteCost(); + EXPECT_GT(cost, 0.0); + // Площадь дорожки: ?*(4^2 - 3^2) = ?*7 ? 21.991, стоимость ? 21991 + double expectedArea = M_PI * (16.0 - 9.0); // 7? + double expectedCost = expectedArea * 1000.0; + EXPECT_NEAR(cost, expectedCost, 1e-6); +} + +TEST(PoolTest, FenceCostPositive) { + double cost = poolFenceCost(); + EXPECT_GT(cost, 0.0); + // Длина ограды: 2?*4 = 8? ? 25.133, стоимость ? 50265.48 + double expectedLength = 2.0 * M_PI * 4.0; + double expectedCost = expectedLength * 2000.0; + EXPECT_NEAR(cost, expectedCost, 1e-6); +} + +TEST(PoolTest, ConcreteCostExact) { + double cost = poolConcreteCost(); + // Точное значение: 1000 * ? * (4^2 - 3^2) = 1000 * ? * 7 = 7000? + double exact = 7000.0 * M_PI; + EXPECT_NEAR(cost, exact, 1e-6); +} + +TEST(PoolTest, FenceCostExact) { + double cost = poolFenceCost(); + // Точное значение: 2000 * 2?*4 = 2000 * 8? = 16000? + double exact = 16000.0 * M_PI; + EXPECT_NEAR(cost, exact, 1e-6); +} + +// Дополнительные тесты для проверки независимости вычислений +TEST(PoolTest, ConcreteVsManual) { + double r_inner = 3.0; + double r_outer = 4.0; + double areaPath = M_PI * (r_outer*r_outer - r_inner*r_inner); + double expected = areaPath * 1000.0; + EXPECT_DOUBLE_EQ(poolConcreteCost(), expected); +} +TEST(PoolTest, FenceVsManual) { + double r_outer = 4.0; + double length = 2.0 * M_PI * r_outer; + double expected = length * 2000.0; + EXPECT_DOUBLE_EQ(poolFenceCost(), expected); +} +// Проверка на использование класса Circle в задачах (косвенно) +TEST(PoolTest, CircleUsage) { + Circle pool(3.0); + Circle outer(4.0); + double pathArea = outer.getArea() - pool.getArea(); + double concreteCost = pathArea * 1000.0; + EXPECT_DOUBLE_EQ(concreteCost, poolConcreteCost()); +} \ No newline at end of file