From bcc7391a19e6582d7e873a4a534e9dffccd6fd22 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Wed, 6 Dec 2023 06:20:00 -0600 Subject: [PATCH] Add GetCounties to county database - Also remove mutex, as the database is only modified on initialization --- .../source/scwx/qt/config/county_database.cpp | 70 ++++++++++++++----- .../source/scwx/qt/config/county_database.hpp | 3 + .../scwx/qt/config/county_database.test.cpp | 23 ++++++ 3 files changed, 80 insertions(+), 16 deletions(-) diff --git a/scwx-qt/source/scwx/qt/config/county_database.cpp b/scwx-qt/source/scwx/qt/config/county_database.cpp index a35db04f..de968474 100644 --- a/scwx-qt/source/scwx/qt/config/county_database.cpp +++ b/scwx-qt/source/scwx/qt/config/county_database.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include @@ -25,9 +24,12 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const std::string countyDatabaseFilename_ = ":/res/db/counties.db"; +typedef std::unordered_map CountyMap; +typedef std::unordered_map StateMap; +typedef std::unordered_map FormatMap; + static bool initialized_ {false}; -static std::unordered_map countyMap_; -static std::shared_mutex countyMutex_; +static FormatMap countyDatabase_; static std::unordered_map stateMap_; void Initialize() @@ -88,8 +90,8 @@ void Initialize() return; } - // Database is open, acquire lock - std::unique_lock lock(countyMutex_); + // Ensure counties exists + countyDatabase_.emplace('C', StateMap {}); // Query database for counties rc = sqlite3_exec( @@ -102,17 +104,26 @@ void Initialize() { int status = 0; - if (columns == 2) + if (columns == 2 && std::strlen(columnText[0]) == 6) { - countyMap_.emplace(columnText[0], columnText[1]); + std::string fipsId = columnText[0]; + std::string state = fipsId.substr(0, 2); + char type = fipsId.at(2); + + countyDatabase_[type][state].emplace(fipsId, columnText[1]); } - else + else if (columns != 2) { logger_->error( "County database format error, invalid number of columns: {}", columns); status = -1; } + else + { + logger_->error("Invalid FIPS ID: {}", columnText[0]); + status = -1; + } return status; }, @@ -157,9 +168,6 @@ void Initialize() sqlite3_free(errorMessage); } - // Finished populating county map, release lock - lock.unlock(); - // Close database sqlite3_close(db); @@ -176,17 +184,47 @@ void Initialize() std::string GetCountyName(const std::string& id) { - std::shared_lock lock(countyMutex_); - - auto it = countyMap_.find(id); - if (it != countyMap_.cend()) + if (id.length() > 3) { - return it->second; + // SSFNNN + char format = id.at(2); + std::string state = id.substr(0, 2); + + auto stateIt = countyDatabase_.find(format); + if (stateIt != countyDatabase_.cend()) + { + StateMap& states = stateIt->second; + auto countyIt = states.find(state); + if (countyIt != states.cend()) + { + CountyMap& counties = countyIt->second; + auto it = counties.find(id); + if (it != counties.cend()) + { + return it->second; + } + } + } } return id; } +std::unordered_map +GetCounties(const std::string& state) +{ + std::unordered_map counties {}; + + StateMap& states = countyDatabase_.at('C'); + auto it = states.find(state); + if (it != states.cend()) + { + counties = it->second; + } + + return counties; +} + } // namespace CountyDatabase } // namespace config } // namespace qt diff --git a/scwx-qt/source/scwx/qt/config/county_database.hpp b/scwx-qt/source/scwx/qt/config/county_database.hpp index e75431ac..5cc92d3d 100644 --- a/scwx-qt/source/scwx/qt/config/county_database.hpp +++ b/scwx-qt/source/scwx/qt/config/county_database.hpp @@ -2,6 +2,7 @@ #include #include +#include #include namespace scwx @@ -15,6 +16,8 @@ namespace CountyDatabase void Initialize(); std::string GetCountyName(const std::string& id); +std::unordered_map +GetCounties(const std::string& state); } // namespace CountyDatabase } // namespace config diff --git a/test/source/scwx/qt/config/county_database.test.cpp b/test/source/scwx/qt/config/county_database.test.cpp index d9f0b3e2..1ef31353 100644 --- a/test/source/scwx/qt/config/county_database.test.cpp +++ b/test/source/scwx/qt/config/county_database.test.cpp @@ -15,6 +15,12 @@ class CountyDatabaseTest : virtual void SetUp() { scwx::qt::config::CountyDatabase::Initialize(); } }; +class CountyCountTest : + public testing::TestWithParam> +{ + virtual void SetUp() { scwx::qt::config::CountyDatabase::Initialize(); } +}; + TEST_P(CountyDatabaseTest, CountyName) { auto& [id, name] = GetParam(); @@ -24,6 +30,15 @@ TEST_P(CountyDatabaseTest, CountyName) EXPECT_EQ(actualName, name); } +TEST_P(CountyCountTest, State) +{ + auto& [state, size] = GetParam(); + + auto counties = CountyDatabase::GetCounties(state); + + EXPECT_EQ(counties.size(), size); +} + INSTANTIATE_TEST_SUITE_P( CountyDatabase, CountyDatabaseTest, @@ -33,6 +48,14 @@ INSTANTIATE_TEST_SUITE_P( std::make_pair("GMZ335", "Galveston Bay"), std::make_pair("ANZ338", "New York Harbor"))); +INSTANTIATE_TEST_SUITE_P(CountyDatabase, + CountyCountTest, + testing::Values(std::make_pair("AZ", 15), + std::make_pair("MO", 115), + std::make_pair("TX", 254), + std::make_pair("GM", 0), + std::make_pair("AN", 0))); + } // namespace config } // namespace qt } // namespace scwx