diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7204538 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,57 @@ +name: Build + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + compiler: [gcc, clang] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up build environment + run: | + sudo apt-get update + sudo apt-get install -y gcc g++ cmake libcfitsio-dev zlib1g-dev libssl-dev libzip-dev libnova-dev libfmt-dev gettext + + - name: Install GCC 13 and G++ 13 + if: matrix.compiler == 'gcc' + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get update + sudo apt-get install -y gcc-13 g++-13 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 60 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 60 + + - name: Install Clang 18 + if: matrix.compiler == 'clang' + run: | + sudo apt-get install -y clang-18 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 60 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 60 + + - name: Build project + run: | + mkdir build + cd build + cmake -DCMAKE_CXX_COMPILER=${{ matrix.compiler }}++ .. + make + + - name: Run tests + run: | + cd build + ctest + + - name: Package project + run: | + cd build + make package diff --git a/.gitignore b/.gitignore index 018eeab..589f457 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ .cache/ build/ -test/ \ No newline at end of file +test/ diff --git a/CMakeLists.txt b/CMakeLists.txt index a603492..35ca064 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ find_package(Curses REQUIRED) add_executable(lithium-next ${lithium_src_dir}/app.cpp) -target_link_libraries(lithium-next PRIVATE +target_link_libraries(lithium-next PRIVATE pybind11::module pybind11::lto lithium_components @@ -71,4 +71,4 @@ add_subdirectory(example) add_subdirectory(tests) # Enable folder grouping in IDEs -set_property(GLOBAL PROPERTY USE_FOLDERS ON) \ No newline at end of file +set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/README.md b/README.md index acd5fa5..e527056 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,89 @@ # lithium-next Next Generation of Lithium + +## Project Description + +Lithium-Next is an open-source astrophotography terminal designed to provide a comprehensive solution for managing and automating astrophotography tasks. The project aims to offer a user-friendly interface, robust features, and seamless integration with various astrophotography equipment and software. + +### Features + +- Automated build process using GitHub Actions +- Support for multiple compilers (GCC and Clang) +- Detailed project configuration using CMake +- Pre-commit hooks for code quality checks +- Integration with CodeQL for code analysis +- Comprehensive logging and debugging support +- Modular architecture for easy extension and customization + +## GitHub Actions Workflows + +### Build Workflow + +The `build.yml` workflow automates the build process for the project. It includes steps for checking out the repository, setting up the build environment, building the project, running tests, and packaging the project. + +#### Triggering the Workflow + +The `build.yml` workflow is triggered on push and pull request events to the `master` branch. This ensures that the project is built, tested, and packaged automatically on every push and pull request to the `master` branch. + +## Development Environment Setup + +To set up the development environment for Lithium-Next, follow these steps: + +1. Clone the repository: + ```bash + git clone https://github.com/ElementAstro/lithium-next.git + cd lithium-next + ``` + +2. Install the required dependencies: + ```bash + sudo apt-get update + sudo apt-get install -y gcc g++ cmake libcfitsio-dev zlib1g-dev libssl-dev libzip-dev libnova-dev libfmt-dev gettext + ``` + +3. Set up the pre-commit hooks: + ```bash + pre-commit install + ``` + +4. Build the project: + ```bash + mkdir build + cd build + cmake .. + make + ``` + +5. Run the tests: + ```bash + ctest + ``` + +6. Package the project: + ```bash + make package + ``` + +7. To build with Clang, ensure Clang 18 or higher is installed and set the compiler: + ```bash + sudo apt-get install -y clang-18 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 60 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 60 + mkdir build-clang + cd build-clang + cmake -DCMAKE_CXX_COMPILER=clang++ .. + make + ``` + +8. To build with GCC 13, ensure GCC 13 is installed and set the compiler: + ```bash + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get update + sudo apt-get install -y gcc-13 g++-13 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 60 + sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 60 + mkdir build-gcc + cd build-gcc + cmake -DCMAKE_CXX_COMPILER=g++ .. + make + ``` diff --git a/cmake/compiler_options.cmake b/cmake/compiler_options.cmake index 3b8bdba..db4eba8 100644 --- a/cmake/compiler_options.cmake +++ b/cmake/compiler_options.cmake @@ -124,4 +124,4 @@ if(CMAKE_BUILD_TYPE MATCHES "Release") target_compile_options(${PROJECT_NAME} PRIVATE /GL) target_link_options(${PROJECT_NAME} PRIVATE /LTCG) endif() -endif() \ No newline at end of file +endif() diff --git a/cmake/policies.cmake b/cmake/policies.cmake index e2c69c8..949a75f 100644 --- a/cmake/policies.cmake +++ b/cmake/policies.cmake @@ -6,4 +6,4 @@ if(POLICY CMP0043) endif() if(POLICY CMP0148) cmake_policy(SET CMP0148 NEW) -endif() \ No newline at end of file +endif() diff --git a/config/package_managers.json b/config/package_managers.json index d4f27e3..786bfa1 100644 --- a/config/package_managers.json +++ b/config/package_managers.json @@ -79,4 +79,4 @@ "searchCommand": "winget search {name}" } ] -} \ No newline at end of file +} diff --git a/example/components/example1.cpp b/example/components/example1.cpp index b0e89ee..6ce33d4 100644 --- a/example/components/example1.cpp +++ b/example/components/example1.cpp @@ -28,4 +28,4 @@ class LoggerComponent : public Component { ATOM_MODULE(logger, [](auto& component) { component.def("logMessage", &LoggerComponent::logMessage, "Log message"); -}) \ No newline at end of file +}) diff --git a/example/components/main.cpp b/example/components/main.cpp index d3b2f43..98abe00 100644 --- a/example/components/main.cpp +++ b/example/components/main.cpp @@ -72,4 +72,4 @@ int main() { } return 0; -} \ No newline at end of file +} diff --git a/example/config/main.cpp b/example/config/main.cpp index 9f5a084..6f98034 100644 --- a/example/config/main.cpp +++ b/example/config/main.cpp @@ -83,4 +83,4 @@ int main() { } return 0; -} \ No newline at end of file +} diff --git a/example/task/main.cpp b/example/task/main.cpp index c1ca405..0fe0f18 100644 --- a/example/task/main.cpp +++ b/example/task/main.cpp @@ -120,4 +120,4 @@ int main() { } return 0; -} \ No newline at end of file +} diff --git a/modules/image/CMakeLists.txt b/modules/image/CMakeLists.txt index 15b1d88..fcc16af 100644 --- a/modules/image/CMakeLists.txt +++ b/modules/image/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(lithium_image +project(lithium_image VERSION 1.0.0 LANGUAGES C CXX ) @@ -20,8 +20,8 @@ include_directories(src) # 创建共享库 add_library(${PROJECT_NAME} SHARED ${SOURCES}) -target_include_directories(${PROJECT_NAME} - PUBLIC +target_include_directories(${PROJECT_NAME} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include ${OpenCV_INCLUDE_DIRS} @@ -41,4 +41,4 @@ set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} ) -add_subdirectory(examples) \ No newline at end of file +add_subdirectory(examples) diff --git a/modules/image/examples/CMakeLists.txt b/modules/image/examples/CMakeLists.txt index efba132..14a870e 100644 --- a/modules/image/examples/CMakeLists.txt +++ b/modules/image/examples/CMakeLists.txt @@ -14,4 +14,3 @@ foreach(CPP_FILE ${CPP_FILES}) add_executable(${EXE_NAME} ${CPP_FILE}) target_link_libraries(${EXE_NAME} ${LIBRARIES_TO_LINK}) endforeach() - diff --git a/modules/image/examples/thumbhash.cpp b/modules/image/examples/thumbhash.cpp index 15efa5b..245ae83 100644 --- a/modules/image/examples/thumbhash.cpp +++ b/modules/image/examples/thumbhash.cpp @@ -90,4 +90,4 @@ int main() { std::cerr << "Error occurred: " << e.what() << std::endl; return -1; } -} \ No newline at end of file +} diff --git a/modules/image/src/base64.cpp b/modules/image/src/base64.cpp index 6ce5031..1454841 100644 --- a/modules/image/src/base64.cpp +++ b/modules/image/src/base64.cpp @@ -122,4 +122,4 @@ auto base64Decode(std::string const& encoded_string) -> std::string { } return result; -} \ No newline at end of file +} diff --git a/modules/image/src/base64.hpp b/modules/image/src/base64.hpp index 8e14775..9e7cf5c 100644 --- a/modules/image/src/base64.hpp +++ b/modules/image/src/base64.hpp @@ -21,4 +21,4 @@ auto base64Encode(unsigned char const* bytes_to_encode, */ auto base64Decode(std::string const& encoded_string) -> std::string; -#endif // LITHIUM_IMAGE_BASE64_HPP \ No newline at end of file +#endif // LITHIUM_IMAGE_BASE64_HPP diff --git a/modules/image/src/binning.cpp b/modules/image/src/binning.cpp index bba5ecb..03927e9 100644 --- a/modules/image/src/binning.cpp +++ b/modules/image/src/binning.cpp @@ -247,4 +247,4 @@ template void process_mono_bin(std::span srcData, uint32_t camxbin, uint32_t camybin); template void process_mono_bin(std::span srcData, cv::Mat& result, uint32_t srcStride, - uint32_t camxbin, uint32_t camybin); \ No newline at end of file + uint32_t camxbin, uint32_t camybin); diff --git a/modules/image/src/binning.hpp b/modules/image/src/binning.hpp index 873e34f..1cd3198 100644 --- a/modules/image/src/binning.hpp +++ b/modules/image/src/binning.hpp @@ -116,4 +116,4 @@ cv::Mat processWithBinning(std::span srcData, uint32_t width, uint32_t newWidth, uint32_t newHeight, uint32_t camxbin, uint32_t camybin, bool isColor); -#endif // LITHIUM_MODULE_IMAGE_BINNING_HPP \ No newline at end of file +#endif // LITHIUM_MODULE_IMAGE_BINNING_HPP diff --git a/modules/image/src/hist.cpp b/modules/image/src/hist.cpp index e7a14e4..edacc41 100644 --- a/modules/image/src/hist.cpp +++ b/modules/image/src/hist.cpp @@ -227,4 +227,4 @@ auto drawHistogram(const cv::Mat& hist, int histSize, int width, LOG_F(INFO, "Histogram visualization completed in {}ms", duration.count()); return histImage; -} \ No newline at end of file +} diff --git a/modules/image/src/hist.hpp b/modules/image/src/hist.hpp index 1654d72..b817981 100644 --- a/modules/image/src/hist.hpp +++ b/modules/image/src/hist.hpp @@ -20,4 +20,4 @@ auto drawHistogram(const cv::Mat& hist, int histSize = DEFAULT_HIST_SIZE, int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT) -> cv::Mat; -#endif // HIST_HPP \ No newline at end of file +#endif // HIST_HPP diff --git a/modules/image/src/imgio.cpp b/modules/image/src/imgio.cpp index d2aafce..a2449f3 100644 --- a/modules/image/src/imgio.cpp +++ b/modules/image/src/imgio.cpp @@ -464,4 +464,4 @@ int saveFitsAsPNG(const std::string& fitsFileName, bool isColor, int cameraBin, LOG_F(INFO, "Image processing and saving completed successfully: {}", fileName); return 0; -} \ No newline at end of file +} diff --git a/modules/image/src/imgio.hpp b/modules/image/src/imgio.hpp index 773b47a..fbc6471 100644 --- a/modules/image/src/imgio.hpp +++ b/modules/image/src/imgio.hpp @@ -86,4 +86,4 @@ auto saveMatTo16BitPng( auto saveMatToFits(const cv::Mat& image, const std::string& output_path = "/dev/shm/MatToFITS.fits") -> bool; -#endif \ No newline at end of file +#endif diff --git a/modules/image/src/imgutils.hpp b/modules/image/src/imgutils.hpp index f427aec..b6740a1 100644 --- a/modules/image/src/imgutils.hpp +++ b/modules/image/src/imgutils.hpp @@ -147,4 +147,4 @@ auto eightSymmetryCircleCheck(const cv::Mat& rect_contour, auto fourSymmetryCircleCheck(const cv::Mat& rect_contour, const cv::Point& center, float radius) -> int; -#endif // LITHIUM_IMAGE_UTILS_HPP \ No newline at end of file +#endif // LITHIUM_IMAGE_UTILS_HPP diff --git a/modules/image/src/test_base64.hpp b/modules/image/src/test_base64.hpp index 8789256..60457b8 100644 --- a/modules/image/src/test_base64.hpp +++ b/modules/image/src/test_base64.hpp @@ -43,8 +43,8 @@ TEST_F(Base64Test, EncodeStandardString) { // RFC 4648 Test Vectors TEST_F(Base64Test, EncodeRFCTestVectors) { for (const auto& [input, expected] : testVectors) { - EXPECT_EQ(base64Encode(reinterpret_cast(input.c_str()), - input.length()), + EXPECT_EQ(base64Encode(reinterpret_cast(input.c_str()), + input.length()), expected); } } @@ -74,7 +74,7 @@ TEST_F(Base64Test, DecodeRFCTestVectors) { } } -// Padding Tests +// Padding Tests TEST_F(Base64Test, HandlePadding) { EXPECT_EQ(base64Decode("YQ=="), "a"); // 1 byte, 2 padding chars EXPECT_EQ(base64Decode("YWI="), "ab"); // 2 bytes, 1 padding char @@ -102,7 +102,7 @@ TEST_F(Base64Test, RoundtripStrings) { TEST_F(Base64Test, RoundtripBinaryData) { std::string encoded = base64Encode(binaryData.data(), binaryData.size()); std::string decoded = base64Decode(encoded); - EXPECT_EQ(std::vector(decoded.begin(), decoded.end()), + EXPECT_EQ(std::vector(decoded.begin(), decoded.end()), binaryData); } @@ -130,4 +130,4 @@ TEST_F(Base64Test, HandleLongStrings) { TEST_F(Base64Test, HandleWhitespace) { EXPECT_EQ(base64Decode("SG Vs\nbG8="), "Hello"); -} \ No newline at end of file +} diff --git a/modules/image/src/test_binning.hpp b/modules/image/src/test_binning.hpp index caee9ea..26862fa 100644 --- a/modules/image/src/test_binning.hpp +++ b/modules/image/src/test_binning.hpp @@ -12,7 +12,7 @@ class BinningTest : public ::testing::Test { smallImage = cv::Mat(100, 100, CV_8UC1, cv::Scalar(128)); largeImage = cv::Mat(3000, 3000, CV_8UC1, cv::Scalar(128)); colorImage = cv::Mat(100, 100, CV_8UC3, cv::Scalar(64, 128, 192)); - + // Create images with different bit depths image8bit = cv::Mat(100, 100, CV_8UC1, cv::Scalar(128)); image16bit = cv::Mat(100, 100, CV_16UC1, cv::Scalar(32768)); @@ -98,7 +98,7 @@ TEST_F(BinningTest, BinningPreservesAverageIntensity) { cv::Scalar originalMean = cv::mean(smallImage); auto result = processMatWithBinAvg(smallImage, 2, 2, false, true); cv::Scalar binnedMean = cv::mean(result); - + EXPECT_NEAR(originalMean[0], binnedMean[0], 1.0); } @@ -122,4 +122,4 @@ TEST_F(BinningTest, LargeBinningFactors) { EXPECT_GT(cv::mean(result)[0], 0); } -} // namespace \ No newline at end of file +} // namespace diff --git a/modules/image/src/test_imgio.hpp b/modules/image/src/test_imgio.hpp index 9dd4a5d..07a8aaf 100644 --- a/modules/image/src/test_imgio.hpp +++ b/modules/image/src/test_imgio.hpp @@ -158,4 +158,4 @@ TEST_F(ImgIOTest, LoadMultipleImagesWithMixedValidity) { "white.jpg"}; auto images = loadImages(testDir.string(), filenames); ASSERT_EQ(images.size(), 2); // Only valid images should be loaded -} \ No newline at end of file +} diff --git a/modules/image/src/test_imgutils.hpp b/modules/image/src/test_imgutils.hpp index 2e1f435..877ef49 100644 --- a/modules/image/src/test_imgutils.hpp +++ b/modules/image/src/test_imgutils.hpp @@ -131,4 +131,4 @@ TEST_F(ImgUtilsTest, ExtremeDimensions) { cv::Mat wideImg(10, 1000, CV_8UC3, cv::Scalar(128, 128, 128)); EXPECT_NO_THROW(autoWhiteBalance(wideImg)); -} \ No newline at end of file +} diff --git a/modules/image/src/test_thumbhash.hpp b/modules/image/src/test_thumbhash.hpp index 87ad0f4..4278d0c 100644 --- a/modules/image/src/test_thumbhash.hpp +++ b/modules/image/src/test_thumbhash.hpp @@ -125,4 +125,4 @@ TEST_F(ThumbHashTest, HashValueRangeTest) { ASSERT_FALSE(std::isinf(value)); } } -} // namespace \ No newline at end of file +} // namespace diff --git a/modules/image/src/thumbhash.cpp b/modules/image/src/thumbhash.cpp index 42b90e0..4cfc281 100644 --- a/modules/image/src/thumbhash.cpp +++ b/modules/image/src/thumbhash.cpp @@ -318,4 +318,4 @@ auto base64Decode(const std::string& encoded) -> std::vector { LOG_F(ERROR, "Exception in base64Decode: {}", e.what()); throw; } -} \ No newline at end of file +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 167b0ce..f2f978b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,4 +7,4 @@ function(add_subdirectories_recursively start_dir) endif() endforeach() endfunction() -add_subdirectories_recursively(${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file +add_subdirectories_recursively(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/client/astap/astap.cpp b/src/client/astap/astap.cpp index dc9841f..ef532a5 100644 --- a/src/client/astap/astap.cpp +++ b/src/client/astap/astap.cpp @@ -240,4 +240,4 @@ ATOM_MODULE(solver_astap, [](Component& component) { "Define a new solver instance."); LOG_F(INFO, "Registered solver_astap module."); -}); \ No newline at end of file +}); diff --git a/src/client/astrometry/astrometry.cpp b/src/client/astrometry/astrometry.cpp index 55feb96..245dd1e 100644 --- a/src/client/astrometry/astrometry.cpp +++ b/src/client/astrometry/astrometry.cpp @@ -21,7 +21,7 @@ static auto astrometrySolver = std::make_shared("solver.astrometry"); -AstrometrySolver::AstrometrySolver(std::string name) +AstrometrySolver::AstrometrySolver(std::string name) : AtomSolver(std::move(name)) { DLOG_F(INFO, "Initializing Astrometry Solver..."); } @@ -440,10 +440,10 @@ PlateSolveResult AstrometrySolver::solve( const std::string& imageFilePath, const std::optional& initialCoordinates, double fovW, double fovH, int imageWidth, int imageHeight) { - + std::string command = buildCommand(imageFilePath, initialCoordinates, fovW, fovH); std::string output; - + try { output = atom::system::executeCommand(command); } catch (const std::exception& e) { @@ -458,10 +458,10 @@ std::future AstrometrySolver::async_solve( const std::string& imageFilePath, const std::optional& initialCoordinates, double fovW, double fovH, int imageWidth, int imageHeight) { - + return std::async(std::launch::async, [this, imageFilePath, initialCoordinates, fovW, fovH, imageWidth, imageHeight]() { - return this->solve(imageFilePath, initialCoordinates, + return this->solve(imageFilePath, initialCoordinates, fovW, fovH, imageWidth, imageHeight); }); } @@ -496,7 +496,7 @@ std::string AstrometrySolver::buildCommand( const std::string& imageFilePath, const std::optional& coords, double fovW, double fovH) { - + std::ostringstream cmd; cmd << "solve-field" << " --overwrite" @@ -518,7 +518,7 @@ std::string AstrometrySolver::buildCommand( PlateSolveResult AstrometrySolver::parseSolveOutput(const std::string& output) { PlateSolveResult result; - + // 使用wcsinfo来解析WCS文件 std::string wcsFile = getOutputPath(output); if (!std::filesystem::exists(wcsFile)) { @@ -527,10 +527,10 @@ PlateSolveResult AstrometrySolver::parseSolveOutput(const std::string& output) { } std::string wcsinfo = atom::system::executeCommand("wcsinfo " + wcsFile); - + // 解析wcsinfo输出... // 这里需要添加实际的解析逻辑来设置result的各个字段 - + result.success = true; return result; } @@ -559,4 +559,4 @@ ATOM_MODULE(astrometry, [](Component &component) { "Astap solver"); LOG_F(INFO, "Registered astrometry module."); -}); \ No newline at end of file +}); diff --git a/src/client/astrometry/astrometry.hpp b/src/client/astrometry/astrometry.hpp index 228a390..6819de9 100644 --- a/src/client/astrometry/astrometry.hpp +++ b/src/client/astrometry/astrometry.hpp @@ -177,4 +177,4 @@ class AstrometrySolver : public AtomSolver { PlateSolveResult parseSolveOutput(const std::string& output); }; -#endif \ No newline at end of file +#endif diff --git a/src/client/astrometry/client.py b/src/client/astrometry/client.py index 529eb96..f9a7d6f 100644 --- a/src/client/astrometry/client.py +++ b/src/client/astrometry/client.py @@ -37,14 +37,14 @@ class Tan: def __init__(self, wcsfn, wcsext=0): with fits.open(wcsfn) as hdul: header = hdul[wcsext].header - self.crval = [header['CRVAL1'], header['CRVAL2']] - self.crpix = [header['CRPIX1'], header['CRPIX2']] + self.crval = [header["CRVAL1"], header["CRVAL2"]] + self.crpix = [header["CRPIX1"], header["CRPIX2"]] self.cd = [ - [header['CD1_1'], header['CD1_2']], - [header['CD2_1'], header['CD2_2']] + [header["CD1_1"], header["CD1_2"]], + [header["CD2_1"], header["CD2_2"]], ] - self.imagew = header['NAXIS1'] - self.imageh = header['NAXIS2'] + self.imagew = header["NAXIS1"] + self.imageh = header["NAXIS2"] def world_to_pixel(self, ra, dec): # Convert world coordinates to pixel coordinates @@ -72,7 +72,7 @@ def pixel_to_world(self, x, y): class Client: - default_url = 'https://nova.astrometry.net/api/' + default_url = "https://nova.astrometry.net/api/" def __init__(self, apiurl=default_url): self.session = None @@ -85,7 +85,7 @@ def send_request(self, service, args=None, file_args=None): if args is None: args = {} if self.session is not None: - args.update({'session': self.session}) + args.update({"session": self.session}) logger.debug(f"Request Arguments: {args}") json_data = json.dumps(args) @@ -97,40 +97,40 @@ def send_request(self, service, args=None, file_args=None): data = b"" if file_args: - boundary_key = ''.join(random.choices('0123456789', k=19)) - boundary = f'==============={boundary_key}==' - headers['Content-Type'] = f'multipart/form-data; boundary="{boundary}"' + boundary_key = "".join(random.choices("0123456789", k=19)) + boundary = f"==============={boundary_key}==" + headers["Content-Type"] = f'multipart/form-data; boundary="{boundary}"' data_pre = ( - f'--{boundary}\r\n' - 'Content-Type: text/plain\r\n' - 'MIME-Version: 1.0\r\n' + f"--{boundary}\r\n" + "Content-Type: text/plain\r\n" + "MIME-Version: 1.0\r\n" 'Content-disposition: form-data; name="request-json"\r\n' - '\r\n' - f'{json_data}\r\n' - f'--{boundary}\r\n' - 'Content-Type: application/octet-stream\r\n' - 'MIME-Version: 1.0\r\n' + "\r\n" + f"{json_data}\r\n" + f"--{boundary}\r\n" + "Content-Type: application/octet-stream\r\n" + "MIME-Version: 1.0\r\n" f'Content-disposition: form-data; name="file"; filename="{file_args[0]}"\r\n' - '\r\n' - ).encode('utf-8') - data_post = f'\r\n--{boundary}--\r\n'.encode('utf-8') + "\r\n" + ).encode("utf-8") + data_post = f"\r\n--{boundary}--\r\n".encode("utf-8") data = data_pre + file_args[1] + data_post else: - headers['Content-Type'] = 'application/x-www-form-urlencoded' - data = urlencode({'request-json': json_data}).encode('utf-8') + headers["Content-Type"] = "application/x-www-form-urlencoded" + data = urlencode({"request-json": json_data}).encode("utf-8") try: request = Request(url=url, headers=headers, data=data) with urlopen(request) as response: status_code = response.status logger.debug(f"Received HTTP status code: {status_code}") - response_text = response.read().decode('utf-8') + response_text = response.read().decode("utf-8") logger.debug(f"Received response: {response_text}") result = json.loads(response_text) - if result.get('status') == 'error': - err_msg = result.get('errormessage', '(none)') - raise RequestError(f'Server error message: {err_msg}') + if result.get("status") == "error": + err_msg = result.get("errormessage", "(none)") + raise RequestError(f"Server error message: {err_msg}") return result except (HTTPError, URLError) as e: logger.error(f"HTTP Error: {e}") @@ -140,40 +140,40 @@ def send_request(self, service, args=None, file_args=None): raise def login(self, apikey): - args = {'apikey': apikey} - result = self.send_request('login', args) - sess = result.get('session') + args = {"apikey": apikey} + result = self.send_request("login", args) + sess = result.get("session") if not sess: - raise RequestError('No session in result') + raise RequestError("No session in result") self.session = sess logger.debug(f"Logged in with session: {self.session}") def _get_upload_args(self, **kwargs): args = {} params = [ - ('allow_commercial_use', 'd', str), - ('allow_modifications', 'd', str), - ('publicly_visible', 'y', str), - ('scale_units', None, str), - ('scale_type', None, str), - ('scale_lower', None, float), - ('scale_upper', None, float), - ('scale_est', None, float), - ('scale_err', None, float), - ('center_ra', None, float), - ('center_dec', None, float), - ('parity', None, int), - ('radius', None, float), - ('downsample_factor', None, int), - ('positional_error', None, float), - ('tweak_order', None, int), - ('crpix_center', None, bool), - ('invert', None, bool), - ('image_width', None, int), - ('image_height', None, int), - ('x', None, list), - ('y', None, list), - ('album', None, str), + ("allow_commercial_use", "d", str), + ("allow_modifications", "d", str), + ("publicly_visible", "y", str), + ("scale_units", None, str), + ("scale_type", None, str), + ("scale_lower", None, float), + ("scale_upper", None, float), + ("scale_est", None, float), + ("scale_err", None, float), + ("center_ra", None, float), + ("center_dec", None, float), + ("parity", None, int), + ("radius", None, float), + ("downsample_factor", None, int), + ("positional_error", None, float), + ("tweak_order", None, int), + ("crpix_center", None, bool), + ("invert", None, bool), + ("image_width", None, int), + ("image_height", None, int), + ("x", None, list), + ("y", None, list), + ("album", None, str), ] for key, default, typ in params: value = kwargs.get(key, default) @@ -186,9 +186,9 @@ def _get_upload_args(self, **kwargs): return args def url_upload(self, url, **kwargs): - args = {'url': url} + args = {"url": url} args.update(self._get_upload_args(**kwargs)) - result = self.send_request('url_upload', args) + result = self.send_request("url_upload", args) return result def upload(self, fn=None, **kwargs): @@ -198,87 +198,87 @@ def upload(self, fn=None, **kwargs): if not os.path.exists(fn): logger.error(f"File {fn} does not exist.") raise FileNotFoundError(f"File {fn} does not exist.") - with open(fn, 'rb') as f: + with open(fn, "rb") as f: file_args = (os.path.basename(fn), f.read()) - return self.send_request('upload', args, file_args) + return self.send_request("upload", args, file_args) def submission_images(self, subid): - result = self.send_request('submission_images', {'subid': subid}) - return result.get('image_ids', []) + result = self.send_request("submission_images", {"subid": subid}) + return result.get("image_ids", []) def overlay_plot(self, service, outfn, wcsfn, wcsext=0): try: wcs = Tan(wcsfn, wcsext) params = { - 'crval1': wcs.crval[0], - 'crval2': wcs.crval[1], - 'crpix1': wcs.crpix[0], - 'crpix2': wcs.crpix[1], - 'cd11': wcs.cd[0], - 'cd12': wcs.cd[1], - 'cd21': wcs.cd[2], - 'cd22': wcs.cd[3], - 'imagew': wcs.imagew, - 'imageh': wcs.imageh + "crval1": wcs.crval[0], + "crval2": wcs.crval[1], + "crpix1": wcs.crpix[0], + "crpix2": wcs.crpix[1], + "cd11": wcs.cd[0], + "cd12": wcs.cd[1], + "cd21": wcs.cd[2], + "cd22": wcs.cd[3], + "imagew": wcs.imagew, + "imageh": wcs.imageh, } - result = self.send_request(service, {'wcs': params}) - if result.get('status') == 'success': - plot_data = base64.b64decode(result['plot']) - with open(outfn, 'wb') as f: + result = self.send_request(service, {"wcs": params}) + if result.get("status") == "success": + plot_data = base64.b64decode(result["plot"]) + with open(outfn, "wb") as f: f.write(plot_data) logger.debug(f"Overlay plot saved to {outfn}") else: - logger.error( - f"Overlay plot failed with status: {result.get('status')}") + logger.error(f"Overlay plot failed with status: {result.get('status')}") except Exception as e: logger.exception("Failed to create overlay plot.") raise def sdss_plot(self, outfn, wcsfn, wcsext=0): - self.overlay_plot('sdss_image_for_wcs', outfn, wcsfn, wcsext) + self.overlay_plot("sdss_image_for_wcs", outfn, wcsfn, wcsext) def galex_plot(self, outfn, wcsfn, wcsext=0): - self.overlay_plot('galex_image_for_wcs', outfn, wcsfn, wcsext) + self.overlay_plot("galex_image_for_wcs", outfn, wcsfn, wcsext) def myjobs(self): - result = self.send_request('myjobs') - return result.get('jobs', []) + result = self.send_request("myjobs") + return result.get("jobs", []) def job_status(self, job_id, justdict=False): - result = self.send_request(f'jobs/{job_id}') + result = self.send_request(f"jobs/{job_id}") if justdict: return result else: - status = result.get('status') + status = result.get("status") logger.debug(f"Job {job_id} status: {status}") - if status == 'success': + if status == "success": logger.debug(f"Job {job_id} completed successfully.") - elif status == 'failure': + elif status == "failure": logger.debug(f"Job {job_id} failed.") else: logger.debug(f"Job {job_id} status: {status}") return status def annotate_data(self, job_id): - result = self.send_request(f'jobs/{job_id}/annotations') + result = self.send_request(f"jobs/{job_id}/annotations") return result def sub_status(self, sub_id, justdict=False): - result = self.send_request(f'submissions/{sub_id}') + result = self.send_request(f"submissions/{sub_id}") if justdict: return result else: - return result.get('status') + return result.get("status") def jobs_by_tag(self, tag, exact=False): - exact_option = 'exact=yes' if exact else '' + exact_option = "exact=yes" if exact else "" result = self.send_request( - f'jobs_by_tag?query={quote(tag.strip())}&{exact_option}') + f"jobs_by_tag?query={quote(tag.strip())}&{exact_option}" + ) return result def delete_job(self, job_id): try: - result = self.send_request(f'jobs/{job_id}/delete') + result = self.send_request(f"jobs/{job_id}/delete") return result except RequestError as e: logger.error(f"Failed to delete job {job_id}: {e}") @@ -288,88 +288,157 @@ def delete_job(self, job_id): def main(): logger.debug(f"Run arguments: {sys.argv}") parser = argparse.ArgumentParser() - parser.add_argument('--server', default=Client.default_url, - help='Set the base server URL') parser.add_argument( - '--apikey', '-k', help='Astrometry.net API key; if not specified, will check environment variable AN_API_KEY') - parser.add_argument('--upload', '-u', help='Upload file') + "--server", default=Client.default_url, help="Set the base server URL" + ) parser.add_argument( - '--upload-xy', help='Upload FITS x,y table in JSON format') - parser.add_argument('--wait', '-w', action='store_true', - help='Monitor job status after submission') + "--apikey", + "-k", + help="Astrometry.net API key; if not specified, will check environment variable AN_API_KEY", + ) + parser.add_argument("--upload", "-u", help="Upload file") + parser.add_argument("--upload-xy", help="Upload FITS x,y table in JSON format") parser.add_argument( - '--wcs', help='Download generated wcs.fits file and save to specified filename; defaults to --wait if using --urlupload or --upload') + "--wait", "-w", action="store_true", help="Monitor job status after submission" + ) parser.add_argument( - '--newfits', help='Download generated new image fits file and save to specified filename; defaults to --wait if using --urlupload or --upload') + "--wcs", + help="Download generated wcs.fits file and save to specified filename; defaults to --wait if using --urlupload or --upload", + ) parser.add_argument( - '--corr', help='Download generated corr.fits file and save to specified filename; defaults to --wait if using --urlupload or --upload') + "--newfits", + help="Download generated new image fits file and save to specified filename; defaults to --wait if using --urlupload or --upload", + ) parser.add_argument( - '--kmz', help='Download generated kmz file and save to specified filename; defaults to --wait if using --urlupload or --upload') + "--corr", + help="Download generated corr.fits file and save to specified filename; defaults to --wait if using --urlupload or --upload", + ) parser.add_argument( - '--annotate', '-a', help='Store annotation information in specified file in JSON format; defaults to --wait if using --urlupload or --upload') - parser.add_argument('--urlupload', '-U', - help='Upload file from specified URL') - parser.add_argument('--scale-units', choices=[ - 'arcsecperpix', 'arcminwidth', 'degwidth', 'focalmm'], help='Units for scale estimation') - parser.add_argument('--scale-lower', type=float, - help='Lower bound for scale') - parser.add_argument('--scale-upper', type=float, - help='Upper bound for scale') - parser.add_argument('--scale-est', type=float, help='Scale estimate') - parser.add_argument('--scale-err', type=float, - help='Scale estimate error (percentage)') - parser.add_argument('--ra', dest='center_ra', type=float, help='RA center') - parser.add_argument('--dec', dest='center_dec', - type=float, help='Dec center') - parser.add_argument('--radius', type=float, - help='Search radius around RA, Dec center') - parser.add_argument('--downsample', type=int, - help='Downsample image by this factor') - parser.add_argument('--positional_error', type=float, - help='Number of pixels a star may deviate from its true position') + "--kmz", + help="Download generated kmz file and save to specified filename; defaults to --wait if using --urlupload or --upload", + ) parser.add_argument( - '--parity', choices=['0', '1'], help='Parity of the image (flipping)') - parser.add_argument('--tweak-order', type=int, - help='SIP distortion order (default: 2)') - parser.add_argument('--crpix-center', action='store_true', - help='Set reference point to image center') - parser.add_argument('--invert', action='store_true', - help='Invert image before detecting sources') - parser.add_argument('--image-width', type=int, - help='Set image width for x,y list') - parser.add_argument('--image-height', type=int, - help='Set image height for x,y list') - parser.add_argument('--album', type=str, - help='Add image to album with specified title string') - parser.add_argument('--sdss', nargs=2, metavar=('WCSFILE', - 'OUTFILE'), help='Plot SDSS image for given WCS file') - parser.add_argument('--galex', nargs=2, metavar=('WCSFILE', - 'OUTFILE'), help='Plot GALEX image for given WCS file') - parser.add_argument('--jobid', '-i', type=int, - help='Retrieve results for jobId instead of submitting new image') - parser.add_argument('--substatus', '-s', help='Get submission status') - parser.add_argument('--jobstatus', '-j', help='Get job status') - parser.add_argument('--jobs', '-J', action='store_true', - help='Get all my jobs') - parser.add_argument('--jobsbyexacttag', '-T', - help='Get list of jobs with exact tag match') - parser.add_argument('--jobsbytag', '-t', - help='Get list of jobs associated with given tag') - parser.add_argument('--private', '-p', dest='public', action='store_const', - const='n', default='y', help='Hide this submission from other users') - parser.add_argument('--allow_mod_sa', '-m', dest='allow_mod', action='store_const', - const='sa', default='d', help='Allow derivative works under the same license') - parser.add_argument('--no_mod', '-M', dest='allow_mod', action='store_const', - const='n', default='d', help='Do not allow derivative works') - parser.add_argument('--no_commercial', '-c', dest='allow_commercial', - action='store_const', const='n', default='d', help='Prohibit commercial use') + "--annotate", + "-a", + help="Store annotation information in specified file in JSON format; defaults to --wait if using --urlupload or --upload", + ) + parser.add_argument("--urlupload", "-U", help="Upload file from specified URL") + parser.add_argument( + "--scale-units", + choices=["arcsecperpix", "arcminwidth", "degwidth", "focalmm"], + help="Units for scale estimation", + ) + parser.add_argument("--scale-lower", type=float, help="Lower bound for scale") + parser.add_argument("--scale-upper", type=float, help="Upper bound for scale") + parser.add_argument("--scale-est", type=float, help="Scale estimate") + parser.add_argument( + "--scale-err", type=float, help="Scale estimate error (percentage)" + ) + parser.add_argument("--ra", dest="center_ra", type=float, help="RA center") + parser.add_argument("--dec", dest="center_dec", type=float, help="Dec center") + parser.add_argument( + "--radius", type=float, help="Search radius around RA, Dec center" + ) + parser.add_argument( + "--downsample", type=int, help="Downsample image by this factor" + ) + parser.add_argument( + "--positional_error", + type=float, + help="Number of pixels a star may deviate from its true position", + ) + parser.add_argument( + "--parity", choices=["0", "1"], help="Parity of the image (flipping)" + ) + parser.add_argument( + "--tweak-order", type=int, help="SIP distortion order (default: 2)" + ) + parser.add_argument( + "--crpix-center", + action="store_true", + help="Set reference point to image center", + ) + parser.add_argument( + "--invert", action="store_true", help="Invert image before detecting sources" + ) + parser.add_argument("--image-width", type=int, help="Set image width for x,y list") + parser.add_argument( + "--image-height", type=int, help="Set image height for x,y list" + ) + parser.add_argument( + "--album", type=str, help="Add image to album with specified title string" + ) + parser.add_argument( + "--sdss", + nargs=2, + metavar=("WCSFILE", "OUTFILE"), + help="Plot SDSS image for given WCS file", + ) + parser.add_argument( + "--galex", + nargs=2, + metavar=("WCSFILE", "OUTFILE"), + help="Plot GALEX image for given WCS file", + ) + parser.add_argument( + "--jobid", + "-i", + type=int, + help="Retrieve results for jobId instead of submitting new image", + ) + parser.add_argument("--substatus", "-s", help="Get submission status") + parser.add_argument("--jobstatus", "-j", help="Get job status") + parser.add_argument("--jobs", "-J", action="store_true", help="Get all my jobs") + parser.add_argument( + "--jobsbyexacttag", "-T", help="Get list of jobs with exact tag match" + ) + parser.add_argument( + "--jobsbytag", "-t", help="Get list of jobs associated with given tag" + ) + parser.add_argument( + "--private", + "-p", + dest="public", + action="store_const", + const="n", + default="y", + help="Hide this submission from other users", + ) + parser.add_argument( + "--allow_mod_sa", + "-m", + dest="allow_mod", + action="store_const", + const="sa", + default="d", + help="Allow derivative works under the same license", + ) + parser.add_argument( + "--no_mod", + "-M", + dest="allow_mod", + action="store_const", + const="n", + default="d", + help="Do not allow derivative works", + ) + parser.add_argument( + "--no_commercial", + "-c", + dest="allow_commercial", + action="store_const", + const="n", + default="d", + help="Prohibit commercial use", + ) opt = parser.parse_args() - apikey = opt.apikey or os.environ.get('AN_API_KEY') + apikey = opt.apikey or os.environ.get("AN_API_KEY") if not apikey: parser.print_help() logger.error( - 'API key must be specified with --apikey or set the environment variable AN_API_KEY') + "API key must be specified with --apikey or set the environment variable AN_API_KEY" + ) sys.exit(1) client = Client(apiurl=opt.server) @@ -388,40 +457,56 @@ def main(): wait = True upload_args = { - 'allow_commercial_use': opt.allow_commercial, - 'allow_modifications': opt.allow_mod, - 'publicly_visible': opt.public + "allow_commercial_use": opt.allow_commercial, + "allow_modifications": opt.allow_mod, + "publicly_visible": opt.public, } if opt.scale_lower and opt.scale_upper: - upload_args.update(scale_lower=opt.scale_lower, - scale_upper=opt.scale_upper, scale_type='ul') + upload_args.update( + scale_lower=opt.scale_lower, + scale_upper=opt.scale_upper, + scale_type="ul", + ) elif opt.scale_est and opt.scale_err: - upload_args.update(scale_est=opt.scale_est, - scale_err=opt.scale_err, scale_type='ev') + upload_args.update( + scale_est=opt.scale_est, scale_err=opt.scale_err, scale_type="ev" + ) elif opt.scale_lower or opt.scale_upper: - upload_args.update(scale_type='ul') + upload_args.update(scale_type="ul") if opt.scale_lower: - upload_args['scale_lower'] = opt.scale_lower + upload_args["scale_lower"] = opt.scale_lower if opt.scale_upper: - upload_args['scale_upper'] = opt.scale_upper - - for key in ['scale_units', 'center_ra', 'center_dec', 'radius', 'downsample', 'positional_error', - 'tweak_order', 'crpix_center', 'invert', 'image_width', 'image_height', 'album']: + upload_args["scale_upper"] = opt.scale_upper + + for key in [ + "scale_units", + "center_ra", + "center_dec", + "radius", + "downsample", + "positional_error", + "tweak_order", + "crpix_center", + "invert", + "image_width", + "image_height", + "album", + ]: value = getattr(opt, key, None) if value is not None: upload_args[key] = value if opt.parity is not None: - upload_args['parity'] = int(opt.parity) + upload_args["parity"] = int(opt.parity) if opt.upload: upload_result = client.upload(opt.upload, **upload_args) elif opt.upload_xy: try: from astrometry.util.fits import fits_table + T = fits_table(opt.upload_xy) - upload_args.update(x=[float(x) - for x in T.x], y=[float(y) for y in T.y]) + upload_args.update(x=[float(x) for x in T.x], y=[float(y) for y in T.y]) upload_result = client.upload(**upload_args) except ImportError as e: logger.error("Cannot import fits_table to upload xy data.") @@ -432,11 +517,11 @@ def main(): logger.error("No upload source specified.") sys.exit(1) - if upload_result['status'] != 'success': + if upload_result["status"] != "success": logger.error(f"Upload failed: {upload_result.get('status')}") sys.exit(1) - sub_id = upload_result['subid'] + sub_id = upload_result["subid"] if wait and not solved_id: if not sub_id: @@ -444,7 +529,7 @@ def main(): sys.exit(1) while True: status_result = client.sub_status(sub_id, justdict=True) - jobs = status_result.get('jobs', []) + jobs = status_result.get("jobs", []) if any(jobs): solved_id = next((j for j in jobs if j is not None), None) if solved_id is not None: @@ -453,17 +538,17 @@ def main(): time.sleep(5) while True: job_result = client.job_status(solved_id, justdict=True) - status = job_result.get('status') - if status == 'success': + status = job_result.get("status") + if status == "success": break - elif status == 'failure': + elif status == "failure": logger.error("Image analysis failed.") sys.exit(1) time.sleep(5) if solved_id: retrieve_items = [] - base_url = opt.server.replace('/api/', '') + base_url = opt.server.replace("/api/", "") if opt.wcs: url = f"{base_url}/wcs_file/{solved_id}" retrieve_items.append((url, opt.wcs)) @@ -480,7 +565,7 @@ def main(): for url, filename in retrieve_items: logger.debug(f"Downloading file from {url} to {filename}") try: - with urlopen(url) as response, open(filename, 'wb') as out_file: + with urlopen(url) as response, open(filename, "wb") as out_file: shutil.copyfileobj(response, out_file) logger.debug(f"Saved to {filename}") except Exception as e: @@ -489,7 +574,7 @@ def main(): if opt.annotate: annotation_data = client.annotate_data(solved_id) - with open(opt.annotate, 'w') as f: + with open(opt.annotate, "w") as f: json.dump(annotation_data, f) logger.debug(f"Annotation data saved to {opt.annotate}") @@ -521,11 +606,11 @@ def main(): # Additional functionality: Delete a job if opt.delete_job: delete_result = client.delete_job(opt.delete_job) - if delete_result and delete_result.get('status') == 'success': + if delete_result and delete_result.get("status") == "success": logger.debug(f"Job {opt.delete_job} deleted successfully.") else: logger.error(f"Failed to delete job {opt.delete_job}.") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/src/client/indi/CMakeLists.txt b/src/client/indi/CMakeLists.txt index d49d49d..4c4aece 100644 --- a/src/client/indi/CMakeLists.txt +++ b/src/client/indi/CMakeLists.txt @@ -52,4 +52,4 @@ endif() # Create the module library add_library(lithium_client_indi SHARED ${SOURCE_FILES} ${HEADER_FILES}) -target_link_libraries(lithium_client_indi PUBLIC ${LIBS}) \ No newline at end of file +target_link_libraries(lithium_client_indi PUBLIC ${LIBS}) diff --git a/src/client/indi/async_system_command.cpp b/src/client/indi/async_system_command.cpp index ff35678..bd19ef1 100644 --- a/src/client/indi/async_system_command.cpp +++ b/src/client/indi/async_system_command.cpp @@ -160,4 +160,4 @@ std::string AsyncSystemCommand::getLastOutput() const { int AsyncSystemCommand::getLastExitStatus() const { std::lock_guard lock(mutex_); return last_exit_status_; -} \ No newline at end of file +} diff --git a/src/client/indi/async_system_command.hpp b/src/client/indi/async_system_command.hpp index 9171893..6604ec2 100644 --- a/src/client/indi/async_system_command.hpp +++ b/src/client/indi/async_system_command.hpp @@ -86,4 +86,4 @@ class AsyncSystemCommand { std::unordered_map env_vars_; std::string last_output_; int last_exit_status_; -}; \ No newline at end of file +}; diff --git a/src/client/indi/collection.cpp b/src/client/indi/collection.cpp index d15a9bf..d1f0ff8 100644 --- a/src/client/indi/collection.cpp +++ b/src/client/indi/collection.cpp @@ -221,4 +221,4 @@ auto INDIDriverCollection::getFamilies() LOG_F(ERROR, "No families found"); } return families; -} \ No newline at end of file +} diff --git a/src/client/indi/collection.hpp b/src/client/indi/collection.hpp index 678e53b..53dbe78 100644 --- a/src/client/indi/collection.hpp +++ b/src/client/indi/collection.hpp @@ -102,4 +102,4 @@ class INDIDriverCollection { drivers_; ///< A list of parsed drivers. }; -#endif // LITHIUM_INDISERVER_COLLECTION_HPP \ No newline at end of file +#endif // LITHIUM_INDISERVER_COLLECTION_HPP diff --git a/src/client/indi/container.hpp b/src/client/indi/container.hpp index 9d9a6c5..49557c7 100644 --- a/src/client/indi/container.hpp +++ b/src/client/indi/container.hpp @@ -45,4 +45,4 @@ class INDIDeviceContainer { custom(custom) {} }; -#endif // LITHIUM_INDISERVER_CONTAINER_HPP \ No newline at end of file +#endif // LITHIUM_INDISERVER_CONTAINER_HPP diff --git a/src/client/indi/database.cpp b/src/client/indi/database.cpp index ac67f90..39fcb36 100644 --- a/src/client/indi/database.cpp +++ b/src/client/indi/database.cpp @@ -222,4 +222,4 @@ void Database::saveProfileCustomDriver(const json& driver) { LOG_F(INFO, "Saving custom driver: {}", driver.dump()); db_["custom_drivers"].push_back(driver); save(); -} \ No newline at end of file +} diff --git a/src/client/indi/database.hpp b/src/client/indi/database.hpp index 3a651e2..ba2c431 100644 --- a/src/client/indi/database.hpp +++ b/src/client/indi/database.hpp @@ -132,4 +132,4 @@ class Database { json db_; ///< The JSON object representing the database. static constexpr const char* CURRENT_VERSION = "0.1.6"; ///< The current version of the database schema. -}; \ No newline at end of file +}; diff --git a/src/client/indi/driverlist.cpp b/src/client/indi/driverlist.cpp index 1531b68..0a8ea62 100644 --- a/src/client/indi/driverlist.cpp +++ b/src/client/indi/driverlist.cpp @@ -183,4 +183,4 @@ auto readDriversListFromFiles(std::string_view filename, std::string_view path) LOG_F(INFO, "Completed reading drivers list from files"); return {driversListFrom, devGroupsFrom, devicesFrom}; -} \ No newline at end of file +} diff --git a/src/client/indi/driverlist.hpp b/src/client/indi/driverlist.hpp index 27b88ab..fb98b9f 100644 --- a/src/client/indi/driverlist.hpp +++ b/src/client/indi/driverlist.hpp @@ -71,4 +71,4 @@ auto parseDevicesFromPath(const std::string& path, auto readDriversListFromFiles(std::string_view filename, std::string_view path) -> std::tuple, std::vector>; -#endif // LITHIUM_INDISERVER_DRIVERLIST_HPP \ No newline at end of file +#endif // LITHIUM_INDISERVER_DRIVERLIST_HPP diff --git a/src/client/indi/iconnector.hpp b/src/client/indi/iconnector.hpp index fdd1d5c..0a8f43e 100644 --- a/src/client/indi/iconnector.hpp +++ b/src/client/indi/iconnector.hpp @@ -132,4 +132,4 @@ class INDIConnector : public Connector { #endif }; -#endif // LITHIUM_INDISERVER_CONNECTOR_HPP \ No newline at end of file +#endif // LITHIUM_INDISERVER_CONNECTOR_HPP diff --git a/src/client/indi/indihub_agent.cpp b/src/client/indi/indihub_agent.cpp index 435a67e..0fe739b 100644 --- a/src/client/indi/indihub_agent.cpp +++ b/src/client/indi/indihub_agent.cpp @@ -117,4 +117,4 @@ bool IndiHubAgent::isRunning() const { std::string IndiHubAgent::getMode() const { LOG_F(INFO, "Getting IndiHubAgent mode: {}", mode_); return mode_; -} \ No newline at end of file +} diff --git a/src/client/indi/indihub_agent.hpp b/src/client/indi/indihub_agent.hpp index eff8328..e021817 100644 --- a/src/client/indi/indihub_agent.hpp +++ b/src/client/indi/indihub_agent.hpp @@ -80,4 +80,4 @@ class IndiHubAgent { async_cmd_; ///< The asynchronous system command for running the agent. std::unique_ptr command_thread_; ///< The thread for running the asynchronous command. -}; \ No newline at end of file +}; diff --git a/src/client/indi/indiserver.hpp b/src/client/indi/indiserver.hpp index 254b064..3e70ba2 100644 --- a/src/client/indi/indiserver.hpp +++ b/src/client/indi/indiserver.hpp @@ -116,7 +116,7 @@ class INDIManager { * @param mode The running mode. * @return True if the agent was started successfully, false otherwise. */ - bool startIndiHub(const std::string& profile, + bool startIndiHub(const std::string& profile, const std::string& mode = INDIHUB_AGENT_DEFAULT_MODE); /** @@ -142,4 +142,4 @@ class INDIManager { std::unique_ptr indihub_agent; ///< IndiHub agent instance }; -#endif // LITHIUM_INDISERVER_HPP \ No newline at end of file +#endif // LITHIUM_INDISERVER_HPP diff --git a/src/client/phd2/profile.hpp b/src/client/phd2/profile.hpp index e69183c..b4dc15a 100644 --- a/src/client/phd2/profile.hpp +++ b/src/client/phd2/profile.hpp @@ -244,4 +244,4 @@ class PHD2ProfileSettingHandler { private: class Impl; ///< Forward declaration of the implementation class. std::unique_ptr pImpl; ///< Pointer to the implementation. -}; \ No newline at end of file +}; diff --git a/src/client/stellarsolver/CMakeLists.txt b/src/client/stellarsolver/CMakeLists.txt index 02b2d7b..338c553 100644 --- a/src/client/stellarsolver/CMakeLists.txt +++ b/src/client/stellarsolver/CMakeLists.txt @@ -34,4 +34,4 @@ target_link_libraries(ssbindings PRIVATE # 启用 Qt MOC set_target_properties(ssbindings PROPERTIES AUTOMOC ON -) \ No newline at end of file +) diff --git a/src/client/stellarsolver/binding.cpp b/src/client/stellarsolver/binding.cpp index cdc8f22..7340720 100644 --- a/src/client/stellarsolver/binding.cpp +++ b/src/client/stellarsolver/binding.cpp @@ -61,4 +61,4 @@ PYBIND11_MODULE(ssbindings, m) { .def("wcs_to_pixel", &SS::wcsToPixel) LOG_F(INFO, "ssbindings module initialized successfully"); -} \ No newline at end of file +} diff --git a/src/client/stellarsolver/config.h b/src/client/stellarsolver/config.h index e7badaf..14303b8 100644 --- a/src/client/stellarsolver/config.h +++ b/src/client/stellarsolver/config.h @@ -11,10 +11,10 @@ class SolverConfig { void setQuickMode(); // 快速模式,精度较低 void setPreciseMode(); // 精确模式,耗时较长 void setBalancedMode(); // 平衡模式 - + // 自定义配置 void setCustomParameters(const SSolver::Parameters& params); - + // 获取当前配置 const SSolver::Parameters& getParameters() const; diff --git a/src/client/stellarsolver/statistic.hpp b/src/client/stellarsolver/statistic.hpp index c7fba8d..94b5b34 100644 --- a/src/client/stellarsolver/statistic.hpp +++ b/src/client/stellarsolver/statistic.hpp @@ -193,4 +193,4 @@ class FitsImageStatistic { }; } // namespace lithium::client -#endif // LITHIUM_CLIENT_STELLARSOLVER_STATISTIC_HPP \ No newline at end of file +#endif // LITHIUM_CLIENT_STELLARSOLVER_STATISTIC_HPP diff --git a/src/client/stellarsolver/stellarsolver.cpp b/src/client/stellarsolver/stellarsolver.cpp index a4c8874..99e6ca4 100644 --- a/src/client/stellarsolver/stellarsolver.cpp +++ b/src/client/stellarsolver/stellarsolver.cpp @@ -476,4 +476,4 @@ auto SS::findStarsByStellarSolver(bool AllStars, } return stars; -} \ No newline at end of file +} diff --git a/src/client/stellarsolver/stellarsolver.hpp b/src/client/stellarsolver/stellarsolver.hpp index 0c1a4ae..9d58861 100644 --- a/src/client/stellarsolver/stellarsolver.hpp +++ b/src/client/stellarsolver/stellarsolver.hpp @@ -77,14 +77,14 @@ class SS : public QObject { // 新增方法 bool initSolver(const QString& configFile = QString()); - + // 异步处理方法 void extractAsync(bool calculateHFR = false); void solveAsync(); - + // 批量处理 bool batchProcess(const QStringList& files); - + // 性能监控 struct PerformanceStats { double extractionTime; @@ -120,7 +120,7 @@ private slots: std::vector bufferData_; QString lastError_; PerformanceStats perfStats_; - + void processError(const QString& error); void updatePerformanceStats(); -}; \ No newline at end of file +}; diff --git a/src/components/CMakeLists.txt b/src/components/CMakeLists.txt index 26c5e02..defe481 100644 --- a/src/components/CMakeLists.txt +++ b/src/components/CMakeLists.txt @@ -17,7 +17,7 @@ set(PROJECT_FILES system_dependency.cpp tracker.cpp version.cpp - + debug/dump.cpp debug/dynamic.cpp debug/elf.cpp diff --git a/src/components/debug/dump.hpp b/src/components/debug/dump.hpp index 1a1df80..1dd559b 100644 --- a/src/components/debug/dump.hpp +++ b/src/components/debug/dump.hpp @@ -142,12 +142,12 @@ class CoreDumpAnalyzer { [[nodiscard]] auto getMemoryMap() const -> std::string; [[nodiscard]] auto findMemoryLeaks() const -> std::string; [[nodiscard]] auto analyzeLockContention() const -> std::string; - + // 导出功能 void exportToJson(const std::string& filename) const; void exportToXml(const std::string& filename) const; void generateHtmlReport(const std::string& filename) const; - + // 配置选项 void setSymbolSearchPaths(const std::vector& paths); void setAnalysisDepth(int depth); @@ -176,4 +176,4 @@ class CoreDumpAnalyzer { } // namespace lithium::addon -#endif // COREDUMPANALYZER_H \ No newline at end of file +#endif // COREDUMPANALYZER_H diff --git a/src/components/debug/dynamic.cpp b/src/components/debug/dynamic.cpp index 1213dff..5fb0dd7 100644 --- a/src/components/debug/dynamic.cpp +++ b/src/components/debug/dynamic.cpp @@ -344,4 +344,4 @@ bool DynamicLibraryParser::verifyLibrary( void DynamicLibraryParser::clearCache() { impl_->clearCache(); } -} // namespace lithium::addon \ No newline at end of file +} // namespace lithium::addon diff --git a/src/components/debug/dynamic.hpp b/src/components/debug/dynamic.hpp index 8c8d443..0731149 100644 --- a/src/components/debug/dynamic.hpp +++ b/src/components/debug/dynamic.hpp @@ -91,4 +91,4 @@ class DynamicLibraryParser { } // namespace lithium::addon -#endif // LITHIUM_ADDON_DEBUG_DYNAMIC_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_DEBUG_DYNAMIC_HPP diff --git a/src/components/debug/elf.hpp b/src/components/debug/elf.hpp index 29eb0a4..5599c1a 100644 --- a/src/components/debug/elf.hpp +++ b/src/components/debug/elf.hpp @@ -252,7 +252,7 @@ class ElfParser { [[nodiscard]] auto calculateChecksum() const -> uint64_t; [[nodiscard]] auto isStripped() const -> bool; [[nodiscard]] auto getDependencies() const -> std::vector; - + // 性能优化相关 void enableCache(bool enable = true); void setParallelProcessing(bool enable = true); diff --git a/src/components/dependency.cpp b/src/components/dependency.cpp index c84a47f..8b3ebc4 100644 --- a/src/components/dependency.cpp +++ b/src/components/dependency.cpp @@ -636,4 +636,4 @@ auto DependencyGraph::validateDependencies(const Node& node) const -> bool { return true; } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/dependency.hpp b/src/components/dependency.hpp index 7c9a5cf..921af7b 100644 --- a/src/components/dependency.hpp +++ b/src/components/dependency.hpp @@ -287,4 +287,4 @@ class DependencyGraph { }; } // namespace lithium -#endif // LITHIUM_ADDON_DEPENDENCY_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_DEPENDENCY_HPP diff --git a/src/components/loader.cpp b/src/components/loader.cpp index 8792ded..eb4962d 100644 --- a/src/components/loader.cpp +++ b/src/components/loader.cpp @@ -58,7 +58,7 @@ auto ModuleLoader::loadModule(const std::string& path, const std::string& name) -> bool { DLOG_F(INFO, "Loading module: {} from path: {}", name, path); std::unique_lock lock(sharedMutex_); - + if (hasModule(name)) { LOG_F(ERROR, "Module {} already loaded", name); return false; @@ -80,7 +80,7 @@ auto ModuleLoader::loadModule(const std::string& path, LOG_F(ERROR, "Failed to load module {}: {}", name, ex.what()); return false; } - + LOG_F(INFO, "Module {} loaded successfully", name); return true; } @@ -295,9 +295,9 @@ auto ModuleLoader::getModuleByHash(std::size_t hash) return nullptr; } -auto ModuleLoader::getDependencies(const std::string& name) const +auto ModuleLoader::getDependencies(const std::string& name) const -> std::vector { return dependencyGraph_.getDependencies(name); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/loader.hpp b/src/components/loader.hpp index 8d7e428..45dc38e 100644 --- a/src/components/loader.hpp +++ b/src/components/loader.hpp @@ -294,7 +294,7 @@ class ModuleLoader { * @param name The name of the module. * @return A future representing the loading result. */ - auto loadModuleAsync(const std::string& path, const std::string& name) + auto loadModuleAsync(const std::string& path, const std::string& name) -> std::future; }; @@ -348,4 +348,4 @@ auto ModuleLoader::getInstancePointer( } // namespace lithium -#endif // LITHIUM_ADDON_LOADER_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_LOADER_HPP diff --git a/src/components/manager.cpp b/src/components/manager.cpp index 2fb7447..beeaa3e 100644 --- a/src/components/manager.cpp +++ b/src/components/manager.cpp @@ -745,4 +745,4 @@ auto ComponentManager::getLastError() -> std::string { void ComponentManager::clearErrors() { impl_->lastError_.clear(); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/manager.hpp b/src/components/manager.hpp index afcd395..2aa0a5c 100644 --- a/src/components/manager.hpp +++ b/src/components/manager.hpp @@ -259,4 +259,4 @@ class ComponentManager { auto initializeComponent(const std::string& name) -> bool; }; -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/module.hpp b/src/components/module.hpp index 5084b8b..01617c0 100644 --- a/src/components/module.hpp +++ b/src/components/module.hpp @@ -101,4 +101,4 @@ struct ModuleInfo { } ATOM_ALIGNAS(32) stats; ///< Statistics about the module. } ATOM_ALIGNAS(128); -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/system_dependency.cpp b/src/components/system_dependency.cpp index 08b05e2..0462669 100644 --- a/src/components/system_dependency.cpp +++ b/src/components/system_dependency.cpp @@ -881,4 +881,4 @@ auto DependencyManager::getPackageManagers() const return pImpl_->getPackageManagers(); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/system_dependency.hpp b/src/components/system_dependency.hpp index 2ed3e38..7008127 100644 --- a/src/components/system_dependency.hpp +++ b/src/components/system_dependency.hpp @@ -144,4 +144,4 @@ class DependencyManager { } // namespace lithium -#endif // LITHIUM_ADDON_DEPENDENCY_MANAGER_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_DEPENDENCY_MANAGER_HPP diff --git a/src/components/tracker.hpp b/src/components/tracker.hpp index 5c10cb1..8c586fd 100644 --- a/src/components/tracker.hpp +++ b/src/components/tracker.hpp @@ -198,4 +198,4 @@ class FileTracker { }; } // namespace lithium -#endif // LITHIUM_ADDON_TRACKER_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_TRACKER_HPP diff --git a/src/components/version.cpp b/src/components/version.cpp index fe0aeff..eb340e0 100644 --- a/src/components/version.cpp +++ b/src/components/version.cpp @@ -250,4 +250,4 @@ auto VersionRange::overlaps(const VersionRange& other) const -> bool { return true; } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/components/version.hpp b/src/components/version.hpp index 0cca192..c4b665e 100644 --- a/src/components/version.hpp +++ b/src/components/version.hpp @@ -362,4 +362,4 @@ struct VersionRange { } // namespace lithium -#endif \ No newline at end of file +#endif diff --git a/src/config/CMakeLists.txt b/src/config/CMakeLists.txt index 1b521e6..c7df3a9 100644 --- a/src/config/CMakeLists.txt +++ b/src/config/CMakeLists.txt @@ -34,4 +34,4 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_LIBS}) # Install target to install the static library to a specified location install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} -) \ No newline at end of file +) diff --git a/src/config/configor.cpp b/src/config/configor.cpp index 56b24f5..fae32ce 100644 --- a/src/config/configor.cpp +++ b/src/config/configor.cpp @@ -373,4 +373,4 @@ auto ConfigManager::listPaths() const -> std::vector { return atom::io::checkFileTypeInFolder(configDir, {".json"}, atom::io::FileOption::PATH); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/config/configor_macro.hpp b/src/config/configor_macro.hpp index 60328ef..a7baf79 100644 --- a/src/config/configor_macro.hpp +++ b/src/config/configor_macro.hpp @@ -53,4 +53,4 @@ LOG_F(WARNING, "Config value for {} not found", path); \ THROW_OBJ_NOT_EXIST("Config value for", path); \ } \ - } while (0) \ No newline at end of file + } while (0) diff --git a/src/config/json5.hpp b/src/config/json5.hpp index c1b0725..c1d463d 100644 --- a/src/config/json5.hpp +++ b/src/config/json5.hpp @@ -137,4 +137,4 @@ inline auto convertJSON5toJSON(const std::string &json5) -> std::string { } // namespace internal } // namespace lithium -#endif \ No newline at end of file +#endif diff --git a/src/database/orm.cpp b/src/database/orm.cpp index 04e828e..e550f19 100644 --- a/src/database/orm.cpp +++ b/src/database/orm.cpp @@ -54,4 +54,4 @@ bool CacheManager::get(const std::string& key, std::string& value) { } return false; } -} // namespace lithium::database \ No newline at end of file +} // namespace lithium::database diff --git a/src/database/orm.hpp b/src/database/orm.hpp index 968c9a1..fe759af 100644 --- a/src/database/orm.hpp +++ b/src/database/orm.hpp @@ -675,4 +675,4 @@ std::vector Table::executeQuery(const std::string& sql) { } // namespace lithium::database -#endif // LITHIUM_DATABASE_ORM_HPP \ No newline at end of file +#endif // LITHIUM_DATABASE_ORM_HPP diff --git a/src/debug/suggestion.cpp b/src/debug/suggestion.cpp index 894fbf0..259334a 100644 --- a/src/debug/suggestion.cpp +++ b/src/debug/suggestion.cpp @@ -351,4 +351,4 @@ auto SuggestionEngine::Implementation::getSuggestionDetails( return details; } -} // namespace lithium::debug \ No newline at end of file +} // namespace lithium::debug diff --git a/src/debug/suggestion.hpp b/src/debug/suggestion.hpp index 9e4ade4..1178e42 100644 --- a/src/debug/suggestion.hpp +++ b/src/debug/suggestion.hpp @@ -142,4 +142,4 @@ class SuggestionEngine { } // namespace lithium::debug -#endif // LITHIUM_DEBUG_SUGGESTION_HPP \ No newline at end of file +#endif // LITHIUM_DEBUG_SUGGESTION_HPP diff --git a/src/debug/terminal.cpp b/src/debug/terminal.cpp index 6c57580..4a4a5ff 100644 --- a/src/debug/terminal.cpp +++ b/src/debug/terminal.cpp @@ -541,4 +541,4 @@ std::vector ConsoleTerminal::getCommandSuggestions( return {}; } -} // namespace lithium::debug \ No newline at end of file +} // namespace lithium::debug diff --git a/src/debug/terminal.hpp b/src/debug/terminal.hpp index 6dec510..1cdfd30 100644 --- a/src/debug/terminal.hpp +++ b/src/debug/terminal.hpp @@ -155,4 +155,4 @@ extern ConsoleTerminal* globalConsoleTerminal; } // namespace lithium::debug -#endif // LITHIUM_DEBUG_TERMINAL_HPP \ No newline at end of file +#endif // LITHIUM_DEBUG_TERMINAL_HPP diff --git a/src/device/indi/camera.cpp b/src/device/indi/camera.cpp index e63dc4e..3f74fba 100644 --- a/src/device/indi/camera.cpp +++ b/src/device/indi/camera.cpp @@ -934,7 +934,7 @@ AtomCameraFrame INDICamera::getFrameInfo() const { INDI::PropertyNumber ccdFrame = device_.getProperty("CCD_FRAME"); if (ccdFrame.isValid()) { frame.resolution.width = ccdFrame[2].getValue(); - frame.resolution.height = ccdFrame[3].getValue(); + frame.resolution.height = ccdFrame[3].getValue(); } return frame; diff --git a/src/device/indi/filterwheel.cpp b/src/device/indi/filterwheel.cpp index 286c510..c087b79 100644 --- a/src/device/indi/filterwheel.cpp +++ b/src/device/indi/filterwheel.cpp @@ -276,4 +276,4 @@ ATOM_MODULE(filterwheel_indi, [](Component &component) { "Define a new filterwheel instance."); LOG_F(INFO, "Registered filterwheel_indi module."); -}); \ No newline at end of file +}); diff --git a/src/device/indi/focuser.cpp b/src/device/indi/focuser.cpp index 28f3f2f..121cfbc 100644 --- a/src/device/indi/focuser.cpp +++ b/src/device/indi/focuser.cpp @@ -570,4 +570,4 @@ ATOM_MODULE(focuser_indi, [](Component &component) { "Define a new focuser instance."); LOG_F(INFO, "Registered focuser_indi module."); -}); \ No newline at end of file +}); diff --git a/src/device/indi/focuser.hpp b/src/device/indi/focuser.hpp index 76c2014..180e0a3 100644 --- a/src/device/indi/focuser.hpp +++ b/src/device/indi/focuser.hpp @@ -104,4 +104,4 @@ class INDIFocuser : public INDI::BaseClient, public AtomFocuser { int delay_msec_; }; -#endif \ No newline at end of file +#endif diff --git a/src/device/indi/telescope.hpp b/src/device/indi/telescope.hpp index 585b66e..cd36ff1 100644 --- a/src/device/indi/telescope.hpp +++ b/src/device/indi/telescope.hpp @@ -157,4 +157,4 @@ class INDITelescope : public INDI::BaseClient, public AtomTelescope { DomePolicy domePolicy_; }; -#endif \ No newline at end of file +#endif diff --git a/src/device/manager.hpp b/src/device/manager.hpp index f2c8d74..4d90874 100644 --- a/src/device/manager.hpp +++ b/src/device/manager.hpp @@ -33,21 +33,21 @@ class DeviceManager { public: DeviceManager(); ~DeviceManager(); - + // 禁用拷贝 DeviceManager(const DeviceManager&) = delete; DeviceManager& operator=(const DeviceManager&) = delete; - + // 设备管理接口 void addDevice(const std::string& type, std::shared_ptr device); void removeDevice(const std::string& type, std::shared_ptr device); void removeDeviceByName(const std::string& name); std::unordered_map>> getDevices() const; - + // 主设备管理 void setPrimaryDevice(const std::string& type, std::shared_ptr device); std::shared_ptr getPrimaryDevice(const std::string& type) const; - + // 设备操作接口 void connectAllDevices(); void disconnectAllDevices(); @@ -55,14 +55,14 @@ class DeviceManager { void disconnectDevicesByType(const std::string& type); void connectDeviceByName(const std::string& name); void disconnectDeviceByName(const std::string& name); - + // 查询接口 std::shared_ptr getDeviceByName(const std::string& name) const; std::shared_ptr findDeviceByName(const std::string& name) const; std::vector> findDevicesByType(const std::string& type) const; bool isDeviceConnected(const std::string& name) const; std::string getDeviceType(const std::string& name) const; - + // 设备生命周期管理 bool initializeDevice(const std::string& name); bool destroyDevice(const std::string& name); @@ -75,4 +75,4 @@ class DeviceManager { } // namespace lithium -#endif // LITHIUM_DEVICE_MANAGER_HPP \ No newline at end of file +#endif // LITHIUM_DEVICE_MANAGER_HPP diff --git a/src/device/template/focuser.hpp b/src/device/template/focuser.hpp index 994a7e3..eddbfc4 100644 --- a/src/device/template/focuser.hpp +++ b/src/device/template/focuser.hpp @@ -52,4 +52,4 @@ class AtomFocuser : public AtomDriver { // 获取调焦器温度 virtual auto getExternalTemperature() -> std::optional = 0; virtual auto getChipTemperature() -> std::optional = 0; -}; \ No newline at end of file +}; diff --git a/src/device/template/solver.hpp b/src/device/template/solver.hpp index fa5ed1c..d83748b 100644 --- a/src/device/template/solver.hpp +++ b/src/device/template/solver.hpp @@ -64,4 +64,4 @@ class AtomSolver : public AtomDriver { virtual std::string getOutputPath( const std::string& imageFilePath) const = 0; -}; \ No newline at end of file +}; diff --git a/src/device/template/telescope.hpp b/src/device/template/telescope.hpp index 69e3125..579a110 100644 --- a/src/device/template/telescope.hpp +++ b/src/device/template/telescope.hpp @@ -97,4 +97,4 @@ class AtomTelescope : public AtomDriver { virtual auto syncToRADECJNow(double raHours, double decDegrees) -> bool = 0; virtual auto getAZALT() -> std::optional> = 0; virtual auto setAZALT(double azDegrees, double altDegrees) -> bool = 0; -}; \ No newline at end of file +}; diff --git a/src/script/check.cpp b/src/script/check.cpp index dd35fc6..ba17141 100644 --- a/src/script/check.cpp +++ b/src/script/check.cpp @@ -626,4 +626,4 @@ AnalysisResult ScriptAnalyzer::analyzeWithOptions( return impl_->analyzeWithOptions(script, options); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/script/check.hpp b/src/script/check.hpp index 9c12a61..e9f3537 100644 --- a/src/script/check.hpp +++ b/src/script/check.hpp @@ -161,4 +161,4 @@ class ScriptAnalyzer : public NonCopyable { }; } // namespace lithium -#endif // LITHIUM_SCRIPT_CHECKER_HPP \ No newline at end of file +#endif // LITHIUM_SCRIPT_CHECKER_HPP diff --git a/src/server/command.hpp b/src/server/command.hpp index b9e929d..6ee13f6 100644 --- a/src/server/command.hpp +++ b/src/server/command.hpp @@ -428,4 +428,4 @@ auto CommandDispatcher::quickDispatch( } } // namespace lithium::app -#endif // LITHIUM_APP_COMMAND_HPP \ No newline at end of file +#endif // LITHIUM_APP_COMMAND_HPP diff --git a/src/server/command/component.hpp b/src/server/command/component.hpp index b7cb7fe..546000e 100644 --- a/src/server/command/component.hpp +++ b/src/server/command/component.hpp @@ -578,4 +578,4 @@ class HooksManager { }; } // namespace lithium -#endif \ No newline at end of file +#endif diff --git a/src/server/command/focuser.hpp b/src/server/command/focuser.hpp index 5ab3491..ac83a85 100644 --- a/src/server/command/focuser.hpp +++ b/src/server/command/focuser.hpp @@ -5,4 +5,4 @@ namespace lithium::middleware {} // namespace lithium::middleware -#endif // LITHIUM_SERVER_MIDDLEWARE_FOCUSER_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_MIDDLEWARE_FOCUSER_HPP diff --git a/src/server/command/guider.hpp b/src/server/command/guider.hpp index cd2f8da..8d821df 100644 --- a/src/server/command/guider.hpp +++ b/src/server/command/guider.hpp @@ -144,4 +144,4 @@ inline void guiderFocalLength(int focalLength) { } } // namespace lithium::middleware -#endif // LITHIUM_SERVER_COMMAND_GUIDER_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_COMMAND_GUIDER_HPP diff --git a/src/server/command/image.hpp b/src/server/command/image.hpp index 518d35b..4600fc2 100644 --- a/src/server/command/image.hpp +++ b/src/server/command/image.hpp @@ -393,7 +393,7 @@ inline void readImageFile(const std::string& message) { auto cameraBin = camera->getBinning(); auto isColor = camera->isColor(); auto processBin = false; - LOG_F(DEBUG, "Camera settings - Binning: {}, IsColor: {}, ProcessBin: {}", + LOG_F(DEBUG, "Camera settings - Binning: {}, IsColor: {}, ProcessBin: {}", cameraBin, isColor, processBin); // 检查组件 @@ -411,7 +411,7 @@ inline void readImageFile(const std::string& message) { auto result = std::any_cast( component->dispatch("save_fits_as_png", imagePath, isColor, cameraBin, processBin, vueImagePath)); - + if (result == -1) { LOG_F(ERROR, "Failed to save FITS as PNG - Operation returned -1"); return; @@ -424,9 +424,9 @@ inline void readImageFile(const std::string& message) { LOG_F(ERROR, "Unexpected error while saving FITS: {}", e.what()); return; } - + LOG_F(INFO, "readImageFile operation completed successfully"); } } // namespace lithium::middleware -#endif // LITHIUM_SERVER_MIDDLEWARE_IMAGE_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_MIDDLEWARE_IMAGE_HPP diff --git a/src/server/command/location.hpp b/src/server/command/location.hpp index 05a76c4..c522a63 100644 --- a/src/server/command/location.hpp +++ b/src/server/command/location.hpp @@ -72,4 +72,4 @@ inline void getCurrentLocation() { } } // namespace lithium::middleware -#endif \ No newline at end of file +#endif diff --git a/src/server/command/telescope.cpp b/src/server/command/telescope.cpp index 2178ec9..b894a12 100644 --- a/src/server/command/telescope.cpp +++ b/src/server/command/telescope.cpp @@ -164,4 +164,4 @@ void mountGoto(double ra, double dec) { 1000, 10, 0); LOG_F(INFO, "mountGoto: Exiting function"); } -} // namespace lithium::middleware \ No newline at end of file +} // namespace lithium::middleware diff --git a/src/server/command/telescope.hpp b/src/server/command/telescope.hpp index ba93460..220dfb6 100644 --- a/src/server/command/telescope.hpp +++ b/src/server/command/telescope.hpp @@ -13,6 +13,6 @@ void mountHome(); void mountSync(); void mountSpeedSwitch(); void mountGoto(double ra, double dec); -} // namespace lithium::middleware +} // namespace lithium::middleware -#endif // LITHIUM_SERVER_MIDDLEWARE_TELESCOPE_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_MIDDLEWARE_TELESCOPE_HPP diff --git a/src/server/command/usb.hpp b/src/server/command/usb.hpp index abd0a51..5720cc8 100644 --- a/src/server/command/usb.hpp +++ b/src/server/command/usb.hpp @@ -113,4 +113,4 @@ inline void usbCheck() { } } // namespace lithium::middleware -#endif // LITHIUM_SERVER_MIDDLEWARE_USB_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_MIDDLEWARE_USB_HPP diff --git a/src/server/controller/components.hpp b/src/server/controller/components.hpp index d78b551..cdb2699 100644 --- a/src/server/controller/components.hpp +++ b/src/server/controller/components.hpp @@ -358,4 +358,4 @@ class ModuleController : public Controller { inline std::weak_ptr ModuleController::mModuleLoader; -#endif // LITHIUM_SERVER_CONTROLLER_MODULE_CONTROLLER_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_CONTROLLER_MODULE_CONTROLLER_HPP diff --git a/src/server/controller/config.hpp b/src/server/controller/config.hpp index 4a499cf..c9efc16 100644 --- a/src/server/controller/config.hpp +++ b/src/server/controller/config.hpp @@ -389,4 +389,4 @@ class ConfigController : public Controller { inline std::weak_ptr ConfigController::mConfigManager; -#endif // LITHIUM_SERVER_CONTROLLER_CONFIG_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_CONTROLLER_CONFIG_HPP diff --git a/src/server/controller/controller.hpp b/src/server/controller/controller.hpp index 3095203..2593a68 100644 --- a/src/server/controller/controller.hpp +++ b/src/server/controller/controller.hpp @@ -9,4 +9,4 @@ class Controller { virtual void registerRoutes(crow::SimpleApp &app) = 0; }; -#endif \ No newline at end of file +#endif diff --git a/src/server/controller/python.hpp b/src/server/controller/python.hpp index 0c328f2..0f7811d 100644 --- a/src/server/controller/python.hpp +++ b/src/server/controller/python.hpp @@ -254,4 +254,4 @@ class PythonController : public Controller { } }; -#endif // LITHIUM_ASYNC_PYTHON_CONTROLLER_HPP \ No newline at end of file +#endif // LITHIUM_ASYNC_PYTHON_CONTROLLER_HPP diff --git a/src/server/controller/script.hpp b/src/server/controller/script.hpp index d51f1f9..930d0f2 100644 --- a/src/server/controller/script.hpp +++ b/src/server/controller/script.hpp @@ -545,4 +545,4 @@ class ScriptController : public Controller { inline std::weak_ptr ScriptController::mScriptManager; inline std::weak_ptr ScriptController::mScriptAnalyzer; -#endif // LITHIUM_SERVER_CONTROLLER_SCRIPT_HPP \ No newline at end of file +#endif // LITHIUM_SERVER_CONTROLLER_SCRIPT_HPP diff --git a/src/server/controller/search.hpp b/src/server/controller/search.hpp index c847378..0a6e64e 100644 --- a/src/server/controller/search.hpp +++ b/src/server/controller/search.hpp @@ -468,4 +468,4 @@ class SearchController : public Controller { inline std::weak_ptr SearchController::mSearchEngine; -#endif // LITHIUM_ASYNC_SEARCH_ENGINE_CONTROLLER_HPP \ No newline at end of file +#endif // LITHIUM_ASYNC_SEARCH_ENGINE_CONTROLLER_HPP diff --git a/src/server/controller/sequencer.hpp b/src/server/controller/sequencer.hpp index e6d6b6c..1de5ff0 100644 --- a/src/server/controller/sequencer.hpp +++ b/src/server/controller/sequencer.hpp @@ -473,4 +473,4 @@ class SequenceController : public Controller { inline std::weak_ptr SequenceController::mExposureSequence; -#endif // LITHIUM_ASYNC_EXPOSURE_SEQUENCE_CONTROLLER_HPP \ No newline at end of file +#endif // LITHIUM_ASYNC_EXPOSURE_SEQUENCE_CONTROLLER_HPP diff --git a/src/server/eventloop.hpp b/src/server/eventloop.hpp index 477c28e..a923032 100644 --- a/src/server/eventloop.hpp +++ b/src/server/eventloop.hpp @@ -233,7 +233,7 @@ class EventLoop { // 添加任务池相关字段 Task* next_pooled = nullptr; bool is_active = true; - + // 添加任务类型标识 enum class Type { Normal, @@ -241,12 +241,12 @@ class EventLoop { Periodic, Cancelable } type = Type::Normal; - + // 对象池分配器 static void* operator new(size_t size) { return task_pool.allocate(); } - + static void operator delete(void* ptr) { task_pool.deallocate(static_cast(ptr)); } @@ -264,31 +264,31 @@ class EventLoop { free_list_ = free_list_->next_pooled; return task; } - + void deallocate(Task* task) { std::lock_guard lock(pool_mutex_); task->next_pooled = free_list_; free_list_ = task; } - + private: Task* free_list_ = nullptr; std::mutex pool_mutex_; }; - + static TaskPool task_pool; - + // 添加高性能任务队列 struct TaskQueue { std::array, 3> priority_queues; // 高中低三个优先级队列 std::mutex mutex; - + void push(Task&& task) { std::lock_guard lock(mutex); int queue_index = task.priority > 0 ? 0 : (task.priority < 0 ? 2 : 1); priority_queues[queue_index].push(std::move(task)); } - + bool pop(Task& task) { std::lock_guard lock(mutex); for (auto& queue : priority_queues) { @@ -301,7 +301,7 @@ class EventLoop { return false; } }; - + TaskQueue task_queue_; std::priority_queue tasks_; @@ -436,4 +436,4 @@ auto EventLoop::postCancelable(F&& f, std::atomic& cancel_flag) } } // namespace lithium::app -#endif // EVENT_LOOP_HPP \ No newline at end of file +#endif // EVENT_LOOP_HPP diff --git a/src/server/middleware.hpp b/src/server/middleware.hpp index 82cff39..acbc4e7 100644 --- a/src/server/middleware.hpp +++ b/src/server/middleware.hpp @@ -38,4 +38,4 @@ struct RequestLogger : crow::ILocalMiddleware { } }; -#endif // MIDDLEWARE_H \ No newline at end of file +#endif // MIDDLEWARE_H diff --git a/src/server/rate_limiter.hpp b/src/server/rate_limiter.hpp index 0c01788..77e1410 100644 --- a/src/server/rate_limiter.hpp +++ b/src/server/rate_limiter.hpp @@ -119,4 +119,4 @@ class RateLimiter { void record_request_time(std::chrono::steady_clock::time_point now); }; -#endif // RATE_LIMITER_H \ No newline at end of file +#endif // RATE_LIMITER_H diff --git a/src/server/websocket.cpp b/src/server/websocket.cpp index 0026678..9b5047a 100644 --- a/src/server/websocket.cpp +++ b/src/server/websocket.cpp @@ -547,4 +547,4 @@ std::chrono::steady_clock::time_point WebSocketServer::get_last_activity_time( } // 如果找不到记录,返回一个很久以前的时间点 return std::chrono::steady_clock::now() - std::chrono::hours(24); -} \ No newline at end of file +} diff --git a/src/server/websocket.hpp b/src/server/websocket.hpp index 6aac2cd..bce20c7 100644 --- a/src/server/websocket.hpp +++ b/src/server/websocket.hpp @@ -258,12 +258,12 @@ class WebSocketServer { int compression_level_{6}; // 记录每个连接的最后活动时间 - std::unordered_map last_activity_times_; - + // 更新连接的最后活动时间 void update_activity_time(crow::websocket::connection* conn); - + // 获取连接的最后活动时间 std::chrono::steady_clock::time_point get_last_activity_time( crow::websocket::connection* conn) const; @@ -316,4 +316,4 @@ void handle_long_task(crow::websocket::connection& conn, * @param conn Reference to the WebSocket connection. * @param msg The message received. */ -void handle_json(crow::websocket::connection& conn, const std::string& msg); \ No newline at end of file +void handle_json(crow::websocket::connection& conn, const std::string& msg); diff --git a/src/target/engine.cpp b/src/target/engine.cpp index 2eb792f..f735d8c 100644 --- a/src/target/engine.cpp +++ b/src/target/engine.cpp @@ -1234,4 +1234,4 @@ auto SearchEngine::getCacheStats() const -> std::string { return ss.str(); } -} // namespace lithium::target \ No newline at end of file +} // namespace lithium::target diff --git a/src/target/engine.hpp b/src/target/engine.hpp index 0ef7bda..2459f74 100644 --- a/src/target/engine.hpp +++ b/src/target/engine.hpp @@ -274,4 +274,4 @@ class SearchEngine { } // namespace lithium::target -#endif // STAR_SEARCH_SEARCH_HPP \ No newline at end of file +#endif // STAR_SEARCH_SEARCH_HPP diff --git a/src/target/preference.cpp b/src/target/preference.cpp index 31ec5b7..1a86cff 100644 --- a/src/target/preference.cpp +++ b/src/target/preference.cpp @@ -466,4 +466,4 @@ void AdvancedRecommendationEngine::loadModel(const std::string& filename) { file.close(); LOG_F(INFO, "Model loaded successfully from {}", filename); -} \ No newline at end of file +} diff --git a/src/target/preference.hpp b/src/target/preference.hpp index b1bdae9..9b3a994 100644 --- a/src/target/preference.hpp +++ b/src/target/preference.hpp @@ -118,16 +118,16 @@ class AdvancedRecommendationEngine { // 简化的公共接口 void addRatings(const std::vector>& ratings); void addItems(const std::vector>>& items); - - auto recommend(const std::string& user, int topN = 5) + + auto recommend(const std::string& user, int topN = 5) -> std::vector>; - + auto predict(const std::string& user, const std::string& item) -> double; - + // 新增方法 void optimize(); void clear(); auto getStats() -> std::string; }; -#endif // ADVANCED_RECOMMENDATION_ENGINE_H \ No newline at end of file +#endif // ADVANCED_RECOMMENDATION_ENGINE_H diff --git a/src/target/reader.hpp b/src/target/reader.hpp index 885d2a9..a4f591f 100644 --- a/src/target/reader.hpp +++ b/src/target/reader.hpp @@ -67,7 +67,7 @@ class DictReader { void enableFieldValidation(bool enable); [[nodiscard]] auto getLineNumber() const -> size_t; void reset(); - + // 批量读取方法 auto readRows(size_t count) -> std::vector>; @@ -92,7 +92,7 @@ class DictWriter { void enableChecksum(bool enable); void flush(); [[nodiscard]] auto getWrittenRows() const -> size_t; - + // 批量写入方法 void writeRows(const std::vector>& rows); diff --git a/src/task/generator.cpp b/src/task/generator.cpp index 1755bc6..1ec85ee 100644 --- a/src/task/generator.cpp +++ b/src/task/generator.cpp @@ -495,4 +495,4 @@ void TaskGenerator::resetStatistics() { LOG_F(INFO, "Statistics reset"); } -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/src/task/generator.hpp b/src/task/generator.hpp index 2ca30a2..0511a24 100644 --- a/src/task/generator.hpp +++ b/src/task/generator.hpp @@ -175,4 +175,4 @@ class TaskGenerator { } // namespace lithium -#endif // LITHIUM_TASK_GENERATOR_HPP \ No newline at end of file +#endif // LITHIUM_TASK_GENERATOR_HPP diff --git a/src/task/imagepath.cpp b/src/task/imagepath.cpp index c68be34..2411884 100644 --- a/src/task/imagepath.cpp +++ b/src/task/imagepath.cpp @@ -42,7 +42,7 @@ auto ImageInfo::hash() const -> size_t { } auto ImageInfo::isComplete() const noexcept -> bool { - return dateTime.has_value() && imageType.has_value() && + return dateTime.has_value() && imageType.has_value() && filter.has_value() && exposureTime.has_value(); } @@ -130,7 +130,7 @@ class ImagePatternParser::Impl { std::function validator) -> void { fieldValidators_[field] = std::move(validator); } - + auto setPreProcessor(std::function processor) -> void { preProcessor_ = std::move(processor); } @@ -259,7 +259,7 @@ class ImagePatternParser::Impl { -> std::optional { using namespace std::views; using namespace std::ranges; - + std::shared_lock lock(cacheMutex_); if (cache_) { if (auto cached = cache_->get(filename)) { @@ -267,7 +267,7 @@ class ImagePatternParser::Impl { } } lock.unlock(); - + std::smatch matchResult; if (!std::regex_match(filename, matchResult, fullRegexPattern_)) { LOG_F(ERROR, "Filename does not match the pattern: {}", filename); @@ -282,7 +282,7 @@ class ImagePatternParser::Impl { validator != fieldValidators_.end() && !validator->second(value)) { return false; } - + if (auto parser = parsers_.find(key); parser != parsers_.end()) { parser->second(info, value); } @@ -299,7 +299,7 @@ class ImagePatternParser::Impl { if (cache_) { cache_->put(filename, info); } - + return info; } @@ -307,17 +307,17 @@ class ImagePatternParser::Impl { [[nodiscard]] auto findFilesInDirectoryImpl(const std::filesystem::path& dir, T&& filter) const -> std::vector { std::vector results; - + for (const auto& entry : std::filesystem::recursive_directory_iterator(dir)) { if (!entry.is_regular_file()) continue; - + if (auto info = parseFilename(entry.path().string())) { if (filter(*info)) { results.push_back(std::move(*info)); } } } - + return results; } }; diff --git a/src/task/imagepath.hpp b/src/task/imagepath.hpp index f2b6ac2..d7c53a1 100644 --- a/src/task/imagepath.hpp +++ b/src/task/imagepath.hpp @@ -271,4 +271,4 @@ class ImagePatternParser { } // namespace lithium -#endif // LITHIUM_TASK_IMAGEPATH_HPP \ No newline at end of file +#endif // LITHIUM_TASK_IMAGEPATH_HPP diff --git a/src/task/sequencer.cpp b/src/task/sequencer.cpp index 2b6bd04..3c34133 100644 --- a/src/task/sequencer.cpp +++ b/src/task/sequencer.cpp @@ -993,4 +993,4 @@ auto ExposureSequence::listMacros() const -> std::vector { return taskGenerator_->listMacros(); } -} // namespace lithium::sequencer \ No newline at end of file +} // namespace lithium::sequencer diff --git a/src/task/target.cpp b/src/task/target.cpp index d2e5270..7d4f912 100644 --- a/src/task/target.cpp +++ b/src/task/target.cpp @@ -308,4 +308,4 @@ auto Target::fromJson(const json& data) -> void { loadTasksFromJson(data["tasks"]); } } -} // namespace lithium::sequencer \ No newline at end of file +} // namespace lithium::sequencer diff --git a/src/task/target.hpp b/src/task/target.hpp index a257678..96370ac 100644 --- a/src/task/target.hpp +++ b/src/task/target.hpp @@ -246,4 +246,4 @@ class Target { } // namespace lithium::sequencer -#endif // LITHIUM_TARGET_HPP \ No newline at end of file +#endif // LITHIUM_TARGET_HPP diff --git a/src/task/task.cpp b/src/task/task.cpp index 1a249df..edc431d 100644 --- a/src/task/task.cpp +++ b/src/task/task.cpp @@ -373,4 +373,4 @@ json Task::toJson() const { {"postTasks", json::array()}, }; } -} // namespace lithium::sequencer \ No newline at end of file +} // namespace lithium::sequencer diff --git a/src/task/task.hpp b/src/task/task.hpp index 3e176ee..c92a25f 100644 --- a/src/task/task.hpp +++ b/src/task/task.hpp @@ -202,4 +202,4 @@ class TaskCreator { } // namespace lithium::sequencer -#endif // TASK_HPP \ No newline at end of file +#endif // TASK_HPP diff --git a/src/task/task_camera.cpp b/src/task/task_camera.cpp index 879cebd..7a9e9b4 100644 --- a/src/task/task_camera.cpp +++ b/src/task/task_camera.cpp @@ -388,4 +388,4 @@ void CameraPreviewTask::execute(const json& params) { TakeExposureTask::execute(previewParams); } -} // namespace lithium::sequencer::task \ No newline at end of file +} // namespace lithium::sequencer::task diff --git a/src/task/task_camera.hpp b/src/task/task_camera.hpp index 30c207c..eb05900 100644 --- a/src/task/task_camera.hpp +++ b/src/task/task_camera.hpp @@ -79,4 +79,4 @@ class CameraPreviewTask : public TaskCreator { } // namespace lithium::sequencer::task -#endif // LITHIUM_TASK_SIMPLE_TASK_CAMERA_HPP \ No newline at end of file +#endif // LITHIUM_TASK_SIMPLE_TASK_CAMERA_HPP diff --git a/src/tools/calculate.cpp b/src/tools/calculate.cpp index 84420e6..1bbd3eb 100644 --- a/src/tools/calculate.cpp +++ b/src/tools/calculate.cpp @@ -125,4 +125,4 @@ auto calculateAltAz(double rightAscension, double declination, double latitude, LOG_F(INFO, "AltAz: Alt={:.6f}°, Az={:.6f}°", altDeg, azDeg); return {altDeg, azDeg}; } -} // namespace lithium::tools \ No newline at end of file +} // namespace lithium::tools diff --git a/src/tools/calculate.hpp b/src/tools/calculate.hpp index 7ccbeb6..cc89422 100644 --- a/src/tools/calculate.hpp +++ b/src/tools/calculate.hpp @@ -245,4 +245,4 @@ auto calculateRefraction(T altitude, T temperature = 10.0, } // namespace lithium::tools -#endif // LITHIUM_TOOLS_CALCULATE_HPP \ No newline at end of file +#endif // LITHIUM_TOOLS_CALCULATE_HPP diff --git a/src/tools/constant.hpp b/src/tools/constant.hpp index 282732d..eeac141 100644 --- a/src/tools/constant.hpp +++ b/src/tools/constant.hpp @@ -12,4 +12,4 @@ constexpr double K_DEGREES_IN_CIRCLE = 360.0; constexpr double K_EPSILON_VALUE = 1e-5; constexpr double K_SECONDS_IN_HOUR = 3600.0; -#endif // LITHIUM_TOOLS_CONSTANT_HPP \ No newline at end of file +#endif // LITHIUM_TOOLS_CONSTANT_HPP diff --git a/src/tools/convert.hpp b/src/tools/convert.hpp index 9bce3a0..c17a13a 100644 --- a/src/tools/convert.hpp +++ b/src/tools/convert.hpp @@ -28,7 +28,7 @@ struct SphericalCoordinates { /** * @brief Clamps a value within a specified range. - * + * * @param value The value to clamp. * @param maxVal The maximum value of the range. * @param minVal The minimum value of the range. @@ -38,7 +38,7 @@ auto rangeTo(double value, double maxVal, double minVal) -> double; /** * @brief Converts degrees to radians. - * + * * @param degree The angle in degrees. * @return The angle in radians. */ @@ -46,7 +46,7 @@ auto degreeToRad(double degree) -> double; /** * @brief Converts radians to degrees. - * + * * @param radians The angle in radians. * @return The angle in degrees. */ @@ -54,7 +54,7 @@ auto radToDegree(double radians) -> double; /** * @brief Converts hours to degrees. - * + * * @param hours The angle in hours. * @return The angle in degrees. */ @@ -62,7 +62,7 @@ auto hourToDegree(double hours) -> double; /** * @brief Converts hours to radians. - * + * * @param hours The angle in hours. * @return The angle in radians. */ @@ -70,7 +70,7 @@ auto hourToRad(double hours) -> double; /** * @brief Converts degrees to hours. - * + * * @param degrees The angle in degrees. * @return The angle in hours. */ @@ -78,7 +78,7 @@ auto degreeToHour(double degrees) -> double; /** * @brief Converts radians to hours. - * + * * @param radians The angle in radians. * @return The angle in hours. */ @@ -86,7 +86,7 @@ auto radToHour(double radians) -> double; /** * @brief Calculates the Hour Angle (HA) in degrees. - * + * * @param rightAscensionRad The Right Ascension in radians. * @param lstDegree The Local Sidereal Time in degrees. * @return The Hour Angle in degrees. @@ -95,7 +95,7 @@ auto getHaDegree(double rightAscensionRad, double lstDegree) -> double; /** * @brief Converts equatorial coordinates (RA, Dec) to horizontal coordinates (Alt, Az). - * + * * @param hourAngleRad The Hour Angle in radians. * @param declinationRad The Declination in radians. * @param latitudeRad The observer's latitude in radians. @@ -106,7 +106,7 @@ auto raDecToAltAz(double hourAngleRad, double declinationRad, /** * @brief Converts horizontal coordinates (Alt, Az) to equatorial coordinates (RA, Dec). - * + * * @param altRadian The Altitude in radians. * @param azRadian The Azimuth in radians. * @param hrRadian Reference to store the Hour Angle in radians. @@ -118,7 +118,7 @@ void altAzToRaDec(double altRadian, double azRadian, double& hrRadian, /** * @brief Converts equatorial coordinates to Cartesian coordinates. - * + * * @param rightAscension The Right Ascension in degrees. * @param declination The Declination in degrees. * @param radius The radius (distance). @@ -129,7 +129,7 @@ auto convertEquatorialToCartesian(double rightAscension, double declination, /** * @brief Converts Cartesian coordinates to spherical coordinates. - * + * * @param cartesianPoint The Cartesian coordinates. * @return The spherical coordinates, or std::nullopt if the conversion fails. */ @@ -138,7 +138,7 @@ auto convertToSphericalCoordinates(const CartesianCoordinates& cartesianPoint) /** * @brief Converts degrees, minutes, and seconds to decimal degrees. - * + * * @param degrees The degrees. * @param minutes The minutes. * @param seconds The seconds. @@ -148,7 +148,7 @@ auto dmsToDegree(int degrees, int minutes, double seconds) -> double; /** * @brief Converts radians to a string representation in degrees, minutes, and seconds (DMS). - * + * * @param radians The angle in radians. * @return The string representation in DMS format. */ @@ -156,7 +156,7 @@ auto radToDmsStr(double radians) -> std::string; /** * @brief Converts radians to a string representation in hours, minutes, and seconds (HMS). - * + * * @param radians The angle in radians. * @return The string representation in HMS format. */ @@ -164,4 +164,4 @@ auto radToHmsStr(double radians) -> std::string; } // namespace lithium::tools -#endif // LITHIUM_TOOLS_CONVERT_HPP \ No newline at end of file +#endif // LITHIUM_TOOLS_CONVERT_HPP diff --git a/src/tools/format.hpp b/src/tools/format.hpp index 4f9134e..30758ef 100644 --- a/src/tools/format.hpp +++ b/src/tools/format.hpp @@ -31,4 +31,4 @@ constexpr auto formatDec(T dec) -> std::string { seconds); } } // namespace lithium::tools -#endif // LITHIUM_TOOLS_FORMAT_HPP \ No newline at end of file +#endif // LITHIUM_TOOLS_FORMAT_HPP diff --git a/src/tools/solverutils.hpp b/src/tools/solverutils.hpp index e458ea4..28d1ff9 100644 --- a/src/tools/solverutils.hpp +++ b/src/tools/solverutils.hpp @@ -22,4 +22,4 @@ auto getFOVCorners(const WCSParams& wcs, int imageWidth, int imageHeight) -> std::vector; } // namespace lithium::tools -#endif \ No newline at end of file +#endif diff --git a/src/utils/format.hpp b/src/utils/format.hpp index 6f0cbff..ae324d4 100644 --- a/src/utils/format.hpp +++ b/src/utils/format.hpp @@ -50,4 +50,4 @@ struct formatter : formatter { return formatter::format(static_cast(r), ctx); } }; -} // namespace std \ No newline at end of file +} // namespace std diff --git a/tests/client/phd2/test_profile.cpp b/tests/client/phd2/test_profile.cpp index f71a40d..7741a64 100644 --- a/tests/client/phd2/test_profile.cpp +++ b/tests/client/phd2/test_profile.cpp @@ -226,4 +226,4 @@ TEST_F(PHD2ProfileSettingHandlerTest, FindProfilesByTelescope) { EXPECT_EQ(profiles.size(), 2); } -#endif // PHD2_PROFILE_TEST_HPP \ No newline at end of file +#endif // PHD2_PROFILE_TEST_HPP diff --git a/tests/components/debug/test_elf.cpp b/tests/components/debug/test_elf.cpp index d0615c6..3b3702a 100644 --- a/tests/components/debug/test_elf.cpp +++ b/tests/components/debug/test_elf.cpp @@ -140,4 +140,4 @@ TEST_F(ElfParserTest, ClearCache) { // No direct way to verify, but ensure no exceptions are thrown } -} // namespace lithium::test \ No newline at end of file +} // namespace lithium::test diff --git a/tests/components/test_loader.cpp b/tests/components/test_loader.cpp index fc869db..5669253 100644 --- a/tests/components/test_loader.cpp +++ b/tests/components/test_loader.cpp @@ -132,4 +132,4 @@ TEST_F(ModuleLoaderTest, LoadModulesInOrder) { EXPECT_TRUE(loader->isModuleEnabled("testModule2")); } -} // namespace lithium::test \ No newline at end of file +} // namespace lithium::test diff --git a/tests/components/test_manager.cpp b/tests/components/test_manager.cpp index 5f5305a..dd47419 100644 --- a/tests/components/test_manager.cpp +++ b/tests/components/test_manager.cpp @@ -253,4 +253,4 @@ TEST_F(ComponentManagerTest, DependencyHandling) { EXPECT_TRUE(manager->unloadComponent(params1)); } -#endif // LITHIUM_TEST_MANAGER_HPP \ No newline at end of file +#endif // LITHIUM_TEST_MANAGER_HPP diff --git a/tests/components/test_tracker.hpp b/tests/components/test_tracker.hpp index 2fc357b..34279d1 100644 --- a/tests/components/test_tracker.hpp +++ b/tests/components/test_tracker.hpp @@ -190,4 +190,4 @@ TEST_F(FileTrackerTest, GetCurrentStats) { } // namespace lithium::test -#endif // LITHIUM_ADDON_TEST_TRACKER_HPP \ No newline at end of file +#endif // LITHIUM_ADDON_TEST_TRACKER_HPP diff --git a/tests/components/test_version.cpp b/tests/components/test_version.cpp index 2960011..9625b17 100644 --- a/tests/components/test_version.cpp +++ b/tests/components/test_version.cpp @@ -143,4 +143,4 @@ TEST_F(VersionTest, VersionRangeParse) { EXPECT_TRUE(range.includeMax); } -} // namespace lithium::test \ No newline at end of file +} // namespace lithium::test diff --git a/tests/config/test_configor.cpp b/tests/config/test_configor.cpp index a0a6eac..dc373ad 100644 --- a/tests/config/test_configor.cpp +++ b/tests/config/test_configor.cpp @@ -152,4 +152,4 @@ TEST_F(ConfigManagerTest, ThreadSafety) { } } // namespace test -} // namespace lithium \ No newline at end of file +} // namespace lithium diff --git a/tests/database/test_orm.cpp b/tests/database/test_orm.cpp index d241eb7..c547ebc 100644 --- a/tests/database/test_orm.cpp +++ b/tests/database/test_orm.cpp @@ -174,4 +174,4 @@ TEST_F(CacheManagerTest, NonExistentKey) { } // namespace lithium::database::test -#endif // LITHIUM_DATABASE_TEST_ORM_HPP \ No newline at end of file +#endif // LITHIUM_DATABASE_TEST_ORM_HPP diff --git a/tests/debug/test_check.cpp b/tests/debug/test_check.cpp index bd5778f..8cb18e1 100644 --- a/tests/debug/test_check.cpp +++ b/tests/debug/test_check.cpp @@ -106,4 +106,4 @@ TEST_F(CommandCheckerTest, NoErrors) { EXPECT_EQ(errors.size(), 0); } -#endif // LITHIUM_DEBUG_TEST_CHECK_HPP \ No newline at end of file +#endif // LITHIUM_DEBUG_TEST_CHECK_HPP diff --git a/tests/debug/test_suggestion.cpp b/tests/debug/test_suggestion.cpp index 9a5c260..afa49af 100644 --- a/tests/debug/test_suggestion.cpp +++ b/tests/debug/test_suggestion.cpp @@ -74,4 +74,4 @@ TEST_F(SuggestionEngineTest, ClearCache) { EXPECT_EQ(suggestions[0], "apple"); } -#endif // LITHIUM_DEBUG_TEST_SUGGESTION_HPP \ No newline at end of file +#endif // LITHIUM_DEBUG_TEST_SUGGESTION_HPP diff --git a/tests/debug/test_terminal.cpp b/tests/debug/test_terminal.cpp index 7b38a68..0054ddc 100644 --- a/tests/debug/test_terminal.cpp +++ b/tests/debug/test_terminal.cpp @@ -104,4 +104,4 @@ TEST_F(ConsoleTerminalSuggestionsTest, SuggestionPersistence) { } // namespace lithium::debug::test -#endif // LITHIUM_DEBUG_TEST_TERMINAL_HPP \ No newline at end of file +#endif // LITHIUM_DEBUG_TEST_TERMINAL_HPP diff --git a/tests/script/test_check.cpp b/tests/script/test_check.cpp index 24b7d3e..c45ad87 100644 --- a/tests/script/test_check.cpp +++ b/tests/script/test_check.cpp @@ -150,4 +150,4 @@ TEST_F(ScriptAnalyzerTest, ScriptAnalyzer_StatisticsTracking) { EXPECT_EQ(analyzer.getTotalAnalyzed(), initial_count + 1); EXPECT_GT(analyzer.getAverageAnalysisTime(), 0.0); -} \ No newline at end of file +} diff --git a/tests/script/test_python_caller.hpp b/tests/script/test_python_caller.hpp index 98eadaa..dcd7fda 100644 --- a/tests/script/test_python_caller.hpp +++ b/tests/script/test_python_caller.hpp @@ -19,10 +19,10 @@ def process_list(items): class TestClass: def __init__(self): self.value = 42 - + def get_value(self): return self.value - + def set_value(self, val): self.value = val @@ -176,4 +176,4 @@ TEST_F(PythonWrapperTest, SysPathManagement) { } } EXPECT_TRUE(path_found); -} \ No newline at end of file +} diff --git a/tests/script/test_sheller.cpp b/tests/script/test_sheller.cpp index 6b340d2..64c6907 100644 --- a/tests/script/test_sheller.cpp +++ b/tests/script/test_sheller.cpp @@ -83,12 +83,12 @@ TEST_F(ScriptManagerTest, MaxVersionLimit) { TEST_F(ScriptManagerTest, ConcurrentExecution) { manager->registerScript("script1", "echo 'one'"); manager->registerScript("script2", "echo 'two'"); - + std::vector>> scripts = { {"script1", {}}, {"script2", {}} }; - + auto results = manager->runScriptsConcurrently(scripts); EXPECT_EQ(results.size(), 2); EXPECT_TRUE(results[0].has_value()); @@ -111,14 +111,14 @@ TEST_F(ScriptManagerTest, ProgressTracking) { sleep 1 echo "PROGRESS:100" )"); - + auto future = manager->runScriptAsync("test", {}); - + // Check progress std::this_thread::sleep_for(std::chrono::milliseconds(500)); float progress = manager->getScriptProgress("test"); EXPECT_GE(progress, 0.0f); - + future.get(); } @@ -129,11 +129,11 @@ TEST_F(ScriptManagerTest, ScriptAbortion) { sleep 1 done )"); - + auto future = manager->runScriptAsync("test", {}); std::this_thread::sleep_for(std::chrono::milliseconds(100)); manager->abortScript("test"); - + auto result = future.get(); ASSERT_TRUE(result.has_value()); EXPECT_EQ(result->second, -999); // Special abort status code @@ -154,12 +154,12 @@ TEST_F(ScriptManagerTest, ScriptLogging) { TEST_F(ScriptManagerTest, SequentialExecution) { manager->registerScript("script1", "echo 'first'"); manager->registerScript("script2", "echo 'second'"); - + std::vector>> scripts = { {"script1", {}}, {"script2", {}} }; - + auto results = manager->runScriptsSequentially(scripts); EXPECT_EQ(results.size(), 2); EXPECT_TRUE(results[0].has_value()); @@ -169,7 +169,7 @@ TEST_F(ScriptManagerTest, SequentialExecution) { TEST_F(ScriptManagerTest, ScriptOutputAndStatus) { manager->registerScript("test", "exit 42"); manager->runScript("test", {}); - + auto status = manager->getScriptStatus("test"); ASSERT_TRUE(status.has_value()); EXPECT_EQ(status.value(), 42); @@ -180,8 +180,8 @@ TEST_F(ScriptManagerTest, PowerShellSpecificFeatures) { $ErrorActionPreference = 'Stop' Write-Host "PowerShell Test" )"); - + auto result = manager->runScript("ps_test", {}); ASSERT_TRUE(result.has_value()); EXPECT_TRUE(result->first.find("PowerShell Test") != std::string::npos); -} \ No newline at end of file +} diff --git a/tests/server/controller/test_config_curl.sh b/tests/server/controller/test_config_curl.sh index 07c6bfa..683a71a 100644 --- a/tests/server/controller/test_config_curl.sh +++ b/tests/server/controller/test_config_curl.sh @@ -12,7 +12,7 @@ curl -X POST $API_URL/config/get \ -d '{"path":"'$TEST_CONFIG_PATH'"}' echo -e "\n\n" -# Test SET config +# Test SET config echo "Testing SET config..." curl -X POST $API_URL/config/set \ -H "Content-Type: application/json" \ diff --git a/tests/server/controller/test_script_curl.sh b/tests/server/controller/test_script_curl.sh index 99e6505..b8a896b 100644 --- a/tests/server/controller/test_script_curl.sh +++ b/tests/server/controller/test_script_curl.sh @@ -13,7 +13,7 @@ curl -X POST $BASE_URL/script/register \ }' echo -e "\n\n" -# Test delete script endpoint +# Test delete script endpoint echo "Testing /script/delete" curl -X POST $BASE_URL/script/delete \ -H "Content-Type: application/json" \ diff --git a/tests/server/controller/test_sequencer_curl.sh b/tests/server/controller/test_sequencer_curl.sh index fcc2016..c48a9ee 100644 --- a/tests/server/controller/test_sequencer_curl.sh +++ b/tests/server/controller/test_sequencer_curl.sh @@ -11,7 +11,7 @@ curl -X POST $BASE_URL/addTarget \ -d '{"name": "test_target"}' echo -e "\n" -# Test removeTarget endpoint +# Test removeTarget endpoint echo "Testing removeTarget..." curl -X POST $BASE_URL/removeTarget \ -H "Content-Type: application/json" \ diff --git a/tests/server/test_command.cpp b/tests/server/test_command.cpp index 40c92f1..37c01a5 100644 --- a/tests/server/test_command.cpp +++ b/tests/server/test_command.cpp @@ -200,4 +200,4 @@ TEST_F(CommandDispatcherTest, UndoRedoOperation) { EXPECT_EQ(value, 42); } -#endif // TEST_COMMAND_HPP \ No newline at end of file +#endif // TEST_COMMAND_HPP diff --git a/tests/server/test_eventloop.cpp b/tests/server/test_eventloop.cpp index 0c20941..05fa351 100644 --- a/tests/server/test_eventloop.cpp +++ b/tests/server/test_eventloop.cpp @@ -196,4 +196,4 @@ TEST_F(EventLoopTest, AdjustTaskPriority) { EXPECT_TRUE(executed); } -#endif // TEST_EVENT_LOOP_HPP \ No newline at end of file +#endif // TEST_EVENT_LOOP_HPP diff --git a/tests/target/test_engine.cpp b/tests/target/test_engine.cpp index 1d80011..3de63a1 100644 --- a/tests/target/test_engine.cpp +++ b/tests/target/test_engine.cpp @@ -191,4 +191,4 @@ TEST_F(SearchEngineTest, DataExportImport) { } // namespace lithium::target::test -#endif // TEST_ENGINE_HPP \ No newline at end of file +#endif // TEST_ENGINE_HPP diff --git a/tests/target/test_preference.hpp b/tests/target/test_preference.hpp index d0eb20b..d9766c3 100644 --- a/tests/target/test_preference.hpp +++ b/tests/target/test_preference.hpp @@ -163,4 +163,4 @@ TEST_F(AdvancedRecommendationEngineTest, ClearAndReset) { EXPECT_EQ(stats.find("Items: 0"), 0); } -} // namespace lithium::target::test \ No newline at end of file +} // namespace lithium::target::test diff --git a/tests/target/test_reader.cpp b/tests/target/test_reader.cpp index b2b1a4a..c3b050f 100644 --- a/tests/target/test_reader.cpp +++ b/tests/target/test_reader.cpp @@ -153,4 +153,4 @@ TEST_F(DictReaderTest, HandleMultipleRows) { EXPECT_FALSE(reader.next(row)); } -} // namespace lithium::target::test \ No newline at end of file +} // namespace lithium::target::test diff --git a/tests/task/test_imagepath.cpp b/tests/task/test_imagepath.cpp index 377f97f..56e2c6e 100644 --- a/tests/task/test_imagepath.cpp +++ b/tests/task/test_imagepath.cpp @@ -191,4 +191,4 @@ TEST_F(ImagePatternParserTest, PreProcessor) { } // namespace lithium::test -#endif // LITHIUM_TASK_TEST_IMAGEPATH_HPP \ No newline at end of file +#endif // LITHIUM_TASK_TEST_IMAGEPATH_HPP diff --git a/tests/task/test_target.cpp b/tests/task/test_target.cpp index 44af977..1027a6c 100644 --- a/tests/task/test_target.cpp +++ b/tests/task/test_target.cpp @@ -67,4 +67,4 @@ TEST_F(TargetTest, LoadTasksFromJson) { target->loadTasksFromJson(tasksJson); EXPECT_EQ(target->getTasks().size(), 3); -} \ No newline at end of file +} diff --git a/tests/task/test_task.cpp b/tests/task/test_task.cpp index 959d820..68f9425 100644 --- a/tests/task/test_task.cpp +++ b/tests/task/test_task.cpp @@ -99,4 +99,4 @@ TEST_F(TaskTest, ValidateParams_ArrayParams) { ASSERT_TRUE(task->validateParams(params)); ASSERT_TRUE(task->getParamErrors().empty()); -} \ No newline at end of file +} diff --git a/tests/tools/test_calculate.cpp b/tests/tools/test_calculate.cpp index 949a659..5d47783 100644 --- a/tests/tools/test_calculate.cpp +++ b/tests/tools/test_calculate.cpp @@ -12,9 +12,9 @@ class CalculateTest : public ::testing::Test { TEST_F(CalculateTest, CalculateVector) { CartesianCoordinates pointA{1.0, 2.0, 3.0}; CartesianCoordinates pointB{4.0, 6.0, 8.0}; - + auto result = calculateVector(pointA, pointB); - + EXPECT_NEAR(result.x, 3.0, EPSILON); EXPECT_NEAR(result.y, 4.0, EPSILON); EXPECT_NEAR(result.z, 5.0, EPSILON); @@ -23,9 +23,9 @@ TEST_F(CalculateTest, CalculateVector) { TEST_F(CalculateTest, CalculatePointC) { CartesianCoordinates pointA{1.0, 2.0, 3.0}; CartesianCoordinates vector{2.0, 3.0, 4.0}; - + auto result = calculatePointC(pointA, vector); - + EXPECT_NEAR(result.x, 3.0, EPSILON); EXPECT_NEAR(result.y, 5.0, EPSILON); EXPECT_NEAR(result.z, 7.0, EPSILON); @@ -35,9 +35,9 @@ TEST_F(CalculateTest, CalculateFOVStandardCamera) { int focalLength = 1000; // 1000mm double sensorWidth = 36.0; // Full frame sensor width double sensorHeight = 24.0; // Full frame sensor height - + auto result = calculateFOV(focalLength, sensorWidth, sensorHeight); - + // Expected values calculated using the formula: 2 * atan(size/(2*focal)) * 180/pi EXPECT_NEAR(result.minFOV, 1.37, 0.01); // Height angle EXPECT_NEAR(result.maxFOV, 2.06, 0.01); // Diagonal angle @@ -47,7 +47,7 @@ TEST_F(CalculateTest, CalculateFOVEdgeCases) { // Test with very large focal length auto resultLarge = calculateFOV(10000, 36.0, 24.0); EXPECT_NEAR(resultLarge.minFOV, 0.137, 0.001); - + // Test with very small focal length auto resultSmall = calculateFOV(10, 36.0, 24.0); EXPECT_NEAR(resultSmall.maxFOV, 127.0, 1.0); @@ -61,7 +61,7 @@ TEST_F(CalculateTest, CalculateGSTKnownDate) { date.tm_hour = 12; // 12:00:00 date.tm_min = 0; date.tm_sec = 0; - + double gst = calculateGST(date); EXPECT_NEAR(gst, 280.46062, 0.0001); } @@ -72,7 +72,7 @@ TEST_F(CalculateTest, CalculateAltAzKnownPosition) { double dec = 89.264; // Polaris Dec (degrees) double lat = 45.0; // Observer latitude double lon = -75.0; // Observer longitude - + std::tm date = {}; date.tm_year = 121; // 2021 date.tm_mon = 6; // July @@ -80,9 +80,9 @@ TEST_F(CalculateTest, CalculateAltAzKnownPosition) { date.tm_hour = 0; // 00:00:00 date.tm_min = 0; date.tm_sec = 0; - + auto result = calculateAltAz(ra, dec, lat, lon, date); - + // Polaris should be visible at about the observer's latitude EXPECT_NEAR(result.altitude, lat, 1.0); // Azimuth should be close to true north (0 or 360 degrees) @@ -95,7 +95,7 @@ TEST_F(CalculateTest, CalculateAltAzEquator) { double dec = 0.0; // Object on celestial equator double lat = 0.0; // Observer at equator double lon = 0.0; // At prime meridian - + std::tm date = {}; date.tm_year = 121; date.tm_mon = 6; @@ -103,9 +103,9 @@ TEST_F(CalculateTest, CalculateAltAzEquator) { date.tm_hour = 12; // Local noon date.tm_min = 0; date.tm_sec = 0; - + auto result = calculateAltAz(ra, dec, lat, lon, date); - + // Object should be near zenith EXPECT_NEAR(result.altitude, 90.0, 1.0); } @@ -116,7 +116,7 @@ TEST_F(CalculateTest, CalculateAltAzPoles) { double dec = 0.0; double lat = 90.0; // North pole double lon = 0.0; - + std::tm date = {}; date.tm_year = 121; date.tm_mon = 6; @@ -124,9 +124,9 @@ TEST_F(CalculateTest, CalculateAltAzPoles) { date.tm_hour = 0; date.tm_min = 0; date.tm_sec = 0; - + auto result = calculateAltAz(ra, dec, lat, lon, date); - + // Object should be on horizon EXPECT_NEAR(result.altitude, 0.0, 1.0); } @@ -137,7 +137,7 @@ TEST_F(CalculateTest, CalculateAltAzBelowHorizon) { double dec = 0.0; double lat = 45.0; double lon = 0.0; - + std::tm date = {}; date.tm_year = 121; date.tm_mon = 6; @@ -145,11 +145,11 @@ TEST_F(CalculateTest, CalculateAltAzBelowHorizon) { date.tm_hour = 12; // Local noon date.tm_min = 0; date.tm_sec = 0; - + auto result = calculateAltAz(ra, dec, lat, lon, date); - + // Object should be below horizon EXPECT_LT(result.altitude, 0.0); } -} // namespace lithium::tools::test \ No newline at end of file +} // namespace lithium::tools::test diff --git a/tests/tools/test_convert.cpp b/tests/tools/test_convert.cpp index 655c610..98fa1a6 100644 --- a/tests/tools/test_convert.cpp +++ b/tests/tools/test_convert.cpp @@ -29,15 +29,15 @@ TEST_F(ConvertTest, HourConversions) { EXPECT_NEAR(hourToDegree(0.0), 0.0, EPSILON); EXPECT_NEAR(hourToDegree(12.0), 180.0, EPSILON); EXPECT_NEAR(hourToDegree(24.0), 360.0, EPSILON); - + // Hour to Radian EXPECT_NEAR(hourToRad(0.0), 0.0, EPSILON); EXPECT_NEAR(hourToRad(12.0), M_PI, EPSILON); - + // Degree to Hour EXPECT_NEAR(degreeToHour(180.0), 12.0, EPSILON); EXPECT_NEAR(degreeToHour(360.0), 24.0, EPSILON); - + // Radian to Hour EXPECT_NEAR(radToHour(M_PI), 12.0, EPSILON); EXPECT_NEAR(radToHour(2 * M_PI), 24.0, EPSILON); @@ -48,11 +48,11 @@ TEST_F(ConvertTest, RangeTo) { // Test normal range [0, 360] EXPECT_NEAR(rangeTo(400.0, 360.0, 0.0), 40.0, EPSILON); EXPECT_NEAR(rangeTo(-30.0, 360.0, 0.0), 330.0, EPSILON); - + // Test hour range [0, 24] EXPECT_NEAR(rangeTo(25.0, 24.0, 0.0), 1.0, EPSILON); EXPECT_NEAR(rangeTo(-1.0, 24.0, 0.0), 23.0, EPSILON); - + // Test multiple wraps EXPECT_NEAR(rangeTo(720.0, 360.0, 0.0), 0.0, EPSILON); EXPECT_NEAR(rangeTo(-720.0, 360.0, 0.0), 0.0, EPSILON); @@ -64,7 +64,7 @@ TEST_F(ConvertTest, EquatorialToCartesian) { EXPECT_NEAR(result.x, 1.0, EPSILON); EXPECT_NEAR(result.y, 0.0, EPSILON); EXPECT_NEAR(result.z, 0.0, EPSILON); - + result = convertEquatorialToCartesian(90.0, 0.0, 1.0); EXPECT_NEAR(result.x, 0.0, EPSILON); EXPECT_NEAR(result.y, 1.0, EPSILON); @@ -77,7 +77,7 @@ TEST_F(ConvertTest, CartesianToSpherical) { ASSERT_TRUE(result.has_value()); EXPECT_NEAR(result->rightAscension, 0.0, EPSILON); EXPECT_NEAR(result->declination, 0.0, EPSILON); - + // Test null case CartesianCoordinates zero{0.0, 0.0, 0.0}; EXPECT_FALSE(convertToSphericalCoordinates(zero).has_value()); @@ -87,7 +87,7 @@ TEST_F(ConvertTest, RaDecToAltAz) { // Object at zenith auto result = raDecToAltAz(0.0, M_PI/2, M_PI/2); EXPECT_NEAR(result[0], M_PI/2, EPSILON); // altitude = 90° - + // Object at horizon result = raDecToAltAz(0.0, 0.0, 0.0); EXPECT_NEAR(result[0], 0.0, EPSILON); // altitude = 0° @@ -98,7 +98,7 @@ TEST_F(ConvertTest, AltAzToRaDec) { // Test zenith case altAzToRaDec(M_PI/2, 0.0, hr, dec, M_PI/4); // 45° latitude EXPECT_NEAR(dec, M_PI/4, EPSILON); - + // Test horizon case altAzToRaDec(0.0, 0.0, hr, dec, 0.0); // equator EXPECT_NEAR(dec, 0.0, EPSILON); @@ -108,10 +108,10 @@ TEST_F(ConvertTest, AltAzToRaDec) { TEST_F(ConvertTest, DMSConversion) { // Positive angle EXPECT_NEAR(dmsToDegree(30, 30, 30.0), 30.508333, 0.000001); - + // Negative angle EXPECT_NEAR(dmsToDegree(-30, 30, 30.0), -30.508333, 0.000001); - + // Zero case EXPECT_NEAR(dmsToDegree(0, 0, 0.0), 0.0, EPSILON); } @@ -133,13 +133,13 @@ TEST_F(ConvertTest, EdgeCases) { // Very large angles EXPECT_NO_THROW(rangeTo(1e6, 360.0, 0.0)); EXPECT_NO_THROW(radToDmsStr(1e6)); - + // Very small angles EXPECT_NEAR(degreeToRad(1e-6), 1e-6 * M_PI / 180.0, EPSILON); - + // NaN handling in string conversions EXPECT_NO_THROW(radToDmsStr(std::numeric_limits::quiet_NaN())); EXPECT_NO_THROW(radToHmsStr(std::numeric_limits::quiet_NaN())); } -} // namespace lithium::tools::test \ No newline at end of file +} // namespace lithium::tools::test diff --git a/tests/tools/test_croods.cpp b/tests/tools/test_croods.cpp index 39abb57..d75017e 100644 --- a/tests/tools/test_croods.cpp +++ b/tests/tools/test_croods.cpp @@ -155,4 +155,4 @@ TEST_F(CroodsTest, EdgeCases) { EXPECT_FALSE(emptyInfo.empty()); } -} // namespace lithium::tools::test \ No newline at end of file +} // namespace lithium::tools::test diff --git a/tests/tools/test_libastro.cpp b/tests/tools/test_libastro.cpp index 31fc6a8..bc08ccb 100644 --- a/tests/tools/test_libastro.cpp +++ b/tests/tools/test_libastro.cpp @@ -7,9 +7,9 @@ class LibAstroTest : public ::testing::Test { protected: static constexpr double EPSILON = 1e-6; static constexpr double J2000_JD = 2451545.0; - + // Helper to create date - double getJulianDate(int year, int month, int day, + double getJulianDate(int year, int month, int day, int hour=0, int min=0, int sec=0) { std::tm time = {}; time.tm_year = year - 1900; @@ -35,7 +35,7 @@ TEST_F(LibAstroTest, AngleConversions) { TEST_F(LibAstroTest, Nutation) { double jd = J2000_JD; // Test at J2000.0 epoch auto [nutLon, nutObl] = getNutation(jd); - + // Values from astronomical almanac for J2000.0 EXPECT_NEAR(nutLon, -0.00337, 0.001); EXPECT_NEAR(nutObl, 0.00278, 0.001); @@ -45,12 +45,12 @@ TEST_F(LibAstroTest, Nutation) { TEST_F(LibAstroTest, ApplyNutation) { EquatorialCoordinates pos{12.0, 45.0}; // 12h RA, 45° Dec double jd = J2000_JD; - + auto result = applyNutation(pos, jd); // Verify nutation is small but non-zero EXPECT_NE(result.rightAscension, pos.rightAscension); EXPECT_NE(result.declination, pos.declination); - + // Test reversibility auto reversed = applyNutation(result, jd, true); EXPECT_NEAR(reversed.rightAscension, pos.rightAscension, 0.0001); @@ -61,7 +61,7 @@ TEST_F(LibAstroTest, ApplyNutation) { TEST_F(LibAstroTest, ApplyAberration) { EquatorialCoordinates pos{6.0, 30.0}; // 6h RA, 30° Dec double jd = J2000_JD; - + auto result = applyAberration(pos, jd); // Aberration should be small but measurable EXPECT_NE(result.rightAscension, pos.rightAscension); @@ -74,7 +74,7 @@ TEST_F(LibAstroTest, ApplyPrecession) { EquatorialCoordinates pos{0.0, 0.0}; // Vernal equinox double startJD = J2000_JD; double endJD = startJD + 36525.0; // One century - + auto result = applyPrecession(pos, startJD, endJD); // Expect significant precession over a century EXPECT_NE(result.rightAscension, pos.rightAscension); @@ -86,7 +86,7 @@ TEST_F(LibAstroTest, EquatorialToHorizontal) { EquatorialCoordinates eq{0.0, 90.0}; // North celestial pole GeographicCoordinates obs{0.0, 45.0, 0.0}; // 45°N latitude double jd = J2000_JD; - + auto hz = equatorialToHorizontal(eq, obs, jd); EXPECT_NEAR(hz.altitude, 45.0, 0.1); // Altitude should equal latitude } @@ -95,11 +95,11 @@ TEST_F(LibAstroTest, HorizontalToEquatorial) { HorizontalCoordinates hz{0.0, 45.0}; // Due north, 45° altitude GeographicCoordinates obs{0.0, 45.0, 0.0}; double jd = J2000_JD; - + auto eq = horizontalToEquatorial(hz, obs, jd); // Convert back to horizontal auto hz2 = equatorialToHorizontal(eq, obs, jd); - + EXPECT_NEAR(hz2.azimuth, hz.azimuth, 0.1); EXPECT_NEAR(hz2.altitude, hz.altitude, 0.1); } @@ -108,10 +108,10 @@ TEST_F(LibAstroTest, HorizontalToEquatorial) { TEST_F(LibAstroTest, ObservedToJ2000) { EquatorialCoordinates observed{12.0, 45.0}; double jd = getJulianDate(2020, 1, 1); - + auto j2000 = observedToJ2000(observed, jd); auto backToObserved = j2000ToObserved(j2000, jd); - + EXPECT_NEAR(backToObserved.rightAscension, observed.rightAscension, 0.0001); EXPECT_NEAR(backToObserved.declination, observed.declination, 0.0001); } @@ -122,14 +122,14 @@ TEST_F(LibAstroTest, EdgeCases) { EquatorialCoordinates pole{0.0, 90.0}; GeographicCoordinates obs{0.0, 90.0, 0.0}; double jd = J2000_JD; - + auto hz = equatorialToHorizontal(pole, obs, jd); EXPECT_NEAR(hz.altitude, 90.0, 0.1); - + // Test around meridian EquatorialCoordinates meridian{0.0, 0.0}; auto hzMeridian = equatorialToHorizontal(meridian, obs, jd); EXPECT_NEAR(hzMeridian.azimuth, 180.0, 0.1); } -} // namespace lithium::tools::test \ No newline at end of file +} // namespace lithium::tools::test diff --git a/tests/tools/test_solverutils.cpp b/tests/tools/test_solverutils.cpp index 9163dcc..c496543 100644 --- a/tests/tools/test_solverutils.cpp +++ b/tests/tools/test_solverutils.cpp @@ -152,4 +152,4 @@ TEST_F(SolverUtilsTest, GetFOVCornersZeroDimensions) { } } -} // namespace lithium::tools::test \ No newline at end of file +} // namespace lithium::tools::test