mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-11-04 01:40:04 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			266 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <scwx/qt/settings/map_settings.hpp>
 | 
						|
#include <scwx/qt/config/radar_site.hpp>
 | 
						|
#include <scwx/qt/settings/settings_variable.hpp>
 | 
						|
#include <scwx/qt/util/json.hpp>
 | 
						|
#include <scwx/common/products.hpp>
 | 
						|
#include <scwx/util/logger.hpp>
 | 
						|
 | 
						|
#include <array>
 | 
						|
#include <execution>
 | 
						|
 | 
						|
#include <boost/json.hpp>
 | 
						|
 | 
						|
namespace scwx
 | 
						|
{
 | 
						|
namespace qt
 | 
						|
{
 | 
						|
namespace settings
 | 
						|
{
 | 
						|
 | 
						|
static const std::string logPrefix_ = "scwx::qt::settings::map_settings";
 | 
						|
static const auto        logger_    = scwx::util::Logger::Create(logPrefix_);
 | 
						|
 | 
						|
static constexpr std::size_t kCount_            = 4u;
 | 
						|
static const std::string     kDefaultRadarSite_ = "KLSX";
 | 
						|
 | 
						|
static const std::string kMapStyleName_ {"map_style"};
 | 
						|
static const std::string kRadarSiteName_ {"radar_site"};
 | 
						|
static const std::string kRadarProductGroupName_ {"radar_product_group"};
 | 
						|
static const std::string kRadarProductName_ {"radar_product"};
 | 
						|
 | 
						|
static const std::string                   kDefaultMapStyle_ {"?"};
 | 
						|
static const std::string kDefaultRadarProductGroupString_ = "L3";
 | 
						|
static const std::array<std::string, kCount_> kDefaultRadarProduct_ {
 | 
						|
   "N0B", "N0G", "N0C", "N0X"};
 | 
						|
 | 
						|
class MapSettings::Impl
 | 
						|
{
 | 
						|
public:
 | 
						|
   struct MapData
 | 
						|
   {
 | 
						|
      SettingsVariable<std::string> mapStyle_ {kMapStyleName_};
 | 
						|
      SettingsVariable<std::string> radarSite_ {kRadarSiteName_};
 | 
						|
      SettingsVariable<std::string> radarProductGroup_ {
 | 
						|
         kRadarProductGroupName_};
 | 
						|
      SettingsVariable<std::string> radarProduct_ {kRadarProductName_};
 | 
						|
   };
 | 
						|
 | 
						|
   explicit Impl()
 | 
						|
   {
 | 
						|
      for (std::size_t i = 0; i < kCount_; i++)
 | 
						|
      {
 | 
						|
         map_[i].mapStyle_.SetDefault(kDefaultMapStyle_);
 | 
						|
         map_[i].radarSite_.SetDefault(kDefaultRadarSite_);
 | 
						|
         map_[i].radarProductGroup_.SetDefault(
 | 
						|
            kDefaultRadarProductGroupString_);
 | 
						|
         map_[i].radarProduct_.SetDefault(kDefaultRadarProduct_[i]);
 | 
						|
 | 
						|
         map_[i].radarSite_.SetValidator(
 | 
						|
            [](const std::string& value)
 | 
						|
            {
 | 
						|
               // Radar site must exist
 | 
						|
               return config::RadarSite::Get(value) != nullptr;
 | 
						|
            });
 | 
						|
 | 
						|
         map_[i].radarProductGroup_.SetValidator(
 | 
						|
            [](const std::string& value)
 | 
						|
            {
 | 
						|
               // Radar product group must be valid
 | 
						|
               common::RadarProductGroup radarProductGroup =
 | 
						|
                  common::GetRadarProductGroup(value);
 | 
						|
               return radarProductGroup != common::RadarProductGroup::Unknown;
 | 
						|
            });
 | 
						|
 | 
						|
         map_[i].radarProduct_.SetValidator(
 | 
						|
            [this, i](const std::string& value)
 | 
						|
            {
 | 
						|
               common::RadarProductGroup radarProductGroup =
 | 
						|
                  common::GetRadarProductGroup(
 | 
						|
                     map_[i].radarProductGroup_.GetValue());
 | 
						|
 | 
						|
               if (radarProductGroup == common::RadarProductGroup::Level2)
 | 
						|
               {
 | 
						|
                  // Radar product must be valid
 | 
						|
                  return common::GetLevel2Product(value) !=
 | 
						|
                         common::Level2Product::Unknown;
 | 
						|
               }
 | 
						|
               else
 | 
						|
               {
 | 
						|
                  // TODO: Validate level 3 product
 | 
						|
                  return true;
 | 
						|
               }
 | 
						|
            });
 | 
						|
 | 
						|
         variables_.insert(variables_.cend(),
 | 
						|
                           {&map_[i].mapStyle_,
 | 
						|
                            &map_[i].radarSite_,
 | 
						|
                            &map_[i].radarProductGroup_,
 | 
						|
                            &map_[i].radarProduct_});
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   ~Impl() {}
 | 
						|
 | 
						|
   void SetDefaults(std::size_t i)
 | 
						|
   {
 | 
						|
      map_[i].mapStyle_.SetValueToDefault();
 | 
						|
      map_[i].radarSite_.SetValueToDefault();
 | 
						|
      map_[i].radarProductGroup_.SetValueToDefault();
 | 
						|
      map_[i].radarProduct_.SetValueToDefault();
 | 
						|
   }
 | 
						|
 | 
						|
   friend void tag_invoke(boost::json::value_from_tag,
 | 
						|
                          boost::json::value& jv,
 | 
						|
                          const MapData&      data)
 | 
						|
   {
 | 
						|
      jv = {{kMapStyleName_, data.mapStyle_.GetValue()},
 | 
						|
            {kRadarSiteName_, data.radarSite_.GetValue()},
 | 
						|
            {kRadarProductGroupName_, data.radarProductGroup_.GetValue()},
 | 
						|
            {kRadarProductName_, data.radarProduct_.GetValue()}};
 | 
						|
   }
 | 
						|
 | 
						|
   friend bool operator==(const MapData& lhs, const MapData& rhs)
 | 
						|
   {
 | 
						|
      return (lhs.mapStyle_ == rhs.mapStyle_ && //
 | 
						|
              lhs.radarSite_ == rhs.radarSite_ &&
 | 
						|
              lhs.radarProductGroup_ == rhs.radarProductGroup_ &&
 | 
						|
              lhs.radarProduct_ == rhs.radarProduct_);
 | 
						|
   }
 | 
						|
 | 
						|
   std::array<MapData, kCount_>       map_ {};
 | 
						|
   std::vector<SettingsVariableBase*> variables_ {};
 | 
						|
};
 | 
						|
 | 
						|
MapSettings::MapSettings() :
 | 
						|
    SettingsCategory("maps"), p(std::make_unique<Impl>())
 | 
						|
{
 | 
						|
   RegisterVariables(p->variables_);
 | 
						|
   SetDefaults();
 | 
						|
 | 
						|
   p->variables_.clear();
 | 
						|
}
 | 
						|
MapSettings::~MapSettings() = default;
 | 
						|
 | 
						|
MapSettings::MapSettings(MapSettings&&) noexcept            = default;
 | 
						|
MapSettings& MapSettings::operator=(MapSettings&&) noexcept = default;
 | 
						|
 | 
						|
std::size_t MapSettings::count() const
 | 
						|
{
 | 
						|
   return kCount_;
 | 
						|
}
 | 
						|
 | 
						|
SettingsVariable<std::string>& MapSettings::map_style(std::size_t i) const
 | 
						|
{
 | 
						|
   return p->map_[i].mapStyle_;
 | 
						|
}
 | 
						|
 | 
						|
SettingsVariable<std::string>& MapSettings::radar_site(std::size_t i) const
 | 
						|
{
 | 
						|
   return p->map_[i].radarSite_;
 | 
						|
}
 | 
						|
 | 
						|
SettingsVariable<std::string>&
 | 
						|
MapSettings::radar_product_group(std::size_t i) const
 | 
						|
{
 | 
						|
   return p->map_[i].radarProductGroup_;
 | 
						|
}
 | 
						|
 | 
						|
SettingsVariable<std::string>& MapSettings::radar_product(std::size_t i) const
 | 
						|
{
 | 
						|
   return p->map_[i].radarProduct_;
 | 
						|
}
 | 
						|
 | 
						|
bool MapSettings::Shutdown()
 | 
						|
{
 | 
						|
   bool dataChanged = false;
 | 
						|
 | 
						|
   // Commit settings that are managed separate from the settings dialog
 | 
						|
   for (std::size_t i = 0; i < kCount_; ++i)
 | 
						|
   {
 | 
						|
      Impl::MapData& mapRecordSettings = p->map_[i];
 | 
						|
 | 
						|
      dataChanged |= mapRecordSettings.mapStyle_.Commit();
 | 
						|
   }
 | 
						|
 | 
						|
   return dataChanged;
 | 
						|
}
 | 
						|
 | 
						|
bool MapSettings::ReadJson(const boost::json::object& json)
 | 
						|
{
 | 
						|
   bool validated = true;
 | 
						|
 | 
						|
   const boost::json::value* value = json.if_contains(name());
 | 
						|
 | 
						|
   if (value != nullptr && value->is_array())
 | 
						|
   {
 | 
						|
      const boost::json::array& mapArray = value->as_array();
 | 
						|
 | 
						|
      for (std::size_t i = 0; i < kCount_; ++i)
 | 
						|
      {
 | 
						|
         if (i < mapArray.size() && mapArray.at(i).is_object())
 | 
						|
         {
 | 
						|
            const boost::json::object& mapRecord = mapArray.at(i).as_object();
 | 
						|
            Impl::MapData&             mapRecordSettings = p->map_[i];
 | 
						|
 | 
						|
            // Load JSON Elements
 | 
						|
            validated &= mapRecordSettings.mapStyle_.ReadValue(mapRecord);
 | 
						|
            validated &= mapRecordSettings.radarSite_.ReadValue(mapRecord);
 | 
						|
            validated &=
 | 
						|
               mapRecordSettings.radarProductGroup_.ReadValue(mapRecord);
 | 
						|
 | 
						|
            bool productValidated =
 | 
						|
               mapRecordSettings.radarProduct_.ReadValue(mapRecord);
 | 
						|
            if (!productValidated)
 | 
						|
            {
 | 
						|
               // Product was set to default, reset group to default to match
 | 
						|
               mapRecordSettings.radarProductGroup_.SetValueToDefault();
 | 
						|
               validated = false;
 | 
						|
            }
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            logger_->warn(
 | 
						|
               "Too few array entries, resetting record {} to defaults", i + 1);
 | 
						|
            validated = false;
 | 
						|
            p->SetDefaults(i);
 | 
						|
         }
 | 
						|
      }
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      if (value == nullptr)
 | 
						|
      {
 | 
						|
         logger_->warn("Key is not present, resetting to defaults");
 | 
						|
      }
 | 
						|
      else if (!value->is_array())
 | 
						|
      {
 | 
						|
         logger_->warn("Invalid json, resetting to defaults");
 | 
						|
      }
 | 
						|
 | 
						|
      SetDefaults();
 | 
						|
      validated = false;
 | 
						|
   }
 | 
						|
 | 
						|
   return validated;
 | 
						|
}
 | 
						|
 | 
						|
void MapSettings::WriteJson(boost::json::object& json) const
 | 
						|
{
 | 
						|
   boost::json::value object = boost::json::value_from(p->map_);
 | 
						|
   json.insert_or_assign(name(), object);
 | 
						|
}
 | 
						|
 | 
						|
MapSettings& MapSettings::Instance()
 | 
						|
{
 | 
						|
   static MapSettings mapSettings_;
 | 
						|
   return mapSettings_;
 | 
						|
}
 | 
						|
 | 
						|
bool operator==(const MapSettings& lhs, const MapSettings& rhs)
 | 
						|
{
 | 
						|
   return (lhs.p->map_ == rhs.p->map_);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace settings
 | 
						|
} // namespace qt
 | 
						|
} // namespace scwx
 |