Hello GitHub
This commit is contained in:
814
src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp
Normal file
814
src/CalcViewModel/DataLoaders/CurrencyDataLoader.cpp
Normal file
@@ -0,0 +1,814 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CurrencyDataLoader.h"
|
||||
#include "UnitConverterDataConstants.h"
|
||||
#include "Common\AppResourceProvider.h"
|
||||
#include "Common\LocalizationStringUtil.h"
|
||||
#include "Common\LocalizationService.h"
|
||||
#include "Common\LocalizationSettings.h"
|
||||
|
||||
using namespace CalculatorApp;
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::Common::LocalizationServiceProperties;
|
||||
using namespace CalculatorApp::DataLoaders;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace CalculatorApp::ViewModel::CurrencyDataLoaderConstants;
|
||||
using namespace concurrency;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace UnitConversionManager;
|
||||
using namespace Windows::ApplicationModel::Resources::Core;
|
||||
using namespace Windows::Data::Json;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Globalization::DateTimeFormatting;
|
||||
using namespace Windows::Globalization::NumberFormatting;
|
||||
using namespace Windows::Storage;
|
||||
using namespace Windows::System::UserProfile;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::Web::Http;
|
||||
|
||||
static constexpr auto CURRENCY_UNIT_FROM_KEY = L"CURRENCY_UNIT_FROM_KEY";
|
||||
static constexpr auto CURRENCY_UNIT_TO_KEY = L"CURRENCY_UNIT_TO_KEY";
|
||||
|
||||
// Calculate number of 100-nanosecond intervals-per-day
|
||||
// (1 interval/100 nanosecond)(100 nanosecond/1e-7 s)(60 s/1 min)(60 min/1 hr)(24 hr/1 day) = (interval/day)
|
||||
static constexpr long long DAY_DURATION = 1LL * 60 * 60 * 24 * 10000000;
|
||||
static constexpr long long WEEK_DURATION = DAY_DURATION * 7;
|
||||
|
||||
static constexpr int FORMATTER_DIGIT_COUNT = 4;
|
||||
|
||||
static constexpr auto CACHE_TIMESTAMP_KEY = L"CURRENCY_CONVERTER_TIMESTAMP";
|
||||
static constexpr auto CACHE_LANGCODE_KEY = L"CURRENCY_CONVERTER_LANGCODE";
|
||||
static constexpr auto CACHE_DELIMITER = L"%";
|
||||
|
||||
static constexpr auto STATIC_DATA_FILENAME = L"CURRENCY_CONVERTER_STATIC_DATA.txt";
|
||||
static constexpr array<wstring_view, 5> STATIC_DATA_PROPERTIES = {
|
||||
wstring_view{ L"CountryCode", 11 },
|
||||
wstring_view{ L"CountryName", 11 },
|
||||
wstring_view{ L"CurrencyCode", 12 },
|
||||
wstring_view{ L"CurrencyName", 12 },
|
||||
wstring_view{ L"CurrencySymbol", 14 }
|
||||
};
|
||||
|
||||
static constexpr auto ALL_RATIOS_DATA_FILENAME = L"CURRENCY_CONVERTER_ALL_RATIOS_DATA.txt";
|
||||
static constexpr auto RATIO_KEY = L"Rt";
|
||||
static constexpr auto CURRENCY_CODE_KEY = L"An";
|
||||
static constexpr array<wstring_view, 2> ALL_RATIOS_DATA_PROPERTIES = {
|
||||
wstring_view{ RATIO_KEY, 2 },
|
||||
wstring_view{ CURRENCY_CODE_KEY, 2 }
|
||||
};
|
||||
|
||||
static constexpr auto DEFAULT_FROM_TO_CURRENCY_FILE_URI = L"ms-appx:///DataLoaders/DefaultFromToCurrency.json";
|
||||
static constexpr auto FROM_KEY = L"from";
|
||||
static constexpr auto TO_KEY = L"to";
|
||||
|
||||
// Fallback default values.
|
||||
static constexpr auto DEFAULT_FROM_CURRENCY = DefaultCurrencyCode.data();
|
||||
static constexpr auto DEFAULT_TO_CURRENCY = L"EUR";
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
namespace UnitConverterResourceKeys
|
||||
{
|
||||
StringReference CurrencyUnitFromKey(CURRENCY_UNIT_FROM_KEY);
|
||||
StringReference CurrencyUnitToKey(CURRENCY_UNIT_TO_KEY);
|
||||
}
|
||||
|
||||
namespace CurrencyDataLoaderConstants
|
||||
{
|
||||
StringReference CacheTimestampKey(CACHE_TIMESTAMP_KEY);
|
||||
StringReference CacheLangcodeKey(CACHE_LANGCODE_KEY);
|
||||
StringReference CacheDelimiter(CACHE_DELIMITER);
|
||||
StringReference StaticDataFilename(STATIC_DATA_FILENAME);
|
||||
StringReference AllRatiosDataFilename(ALL_RATIOS_DATA_FILENAME);
|
||||
long long DayDuration = DAY_DURATION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CurrencyDataLoader::CurrencyDataLoader(_In_ unique_ptr<ICurrencyHttpClient> client) :
|
||||
m_client(move(client)),
|
||||
m_loadStatus(CurrencyLoadStatus::NotLoaded),
|
||||
m_responseLanguage(L"en-US"),
|
||||
m_ratioFormat(L""),
|
||||
m_timestampFormat(L""),
|
||||
m_networkManager(ref new NetworkManager()),
|
||||
m_meteredOverrideSet(false)
|
||||
{
|
||||
if (GlobalizationPreferences::Languages->Size > 0)
|
||||
{
|
||||
m_responseLanguage = GlobalizationPreferences::Languages->GetAt(0);
|
||||
}
|
||||
|
||||
if (m_client != nullptr)
|
||||
{
|
||||
m_client->SetSourceCurrencyCode(StringReference(DefaultCurrencyCode.data()));
|
||||
m_client->SetResponseLanguage(m_responseLanguage);
|
||||
}
|
||||
|
||||
if (CoreWindow::GetForCurrentThread() != nullptr)
|
||||
{
|
||||
// Must have a CoreWindow to access the resource context.
|
||||
m_isRtlLanguage = LocalizationService::GetInstance()->IsRtlLayout();
|
||||
}
|
||||
|
||||
m_ratioFormatter = LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
|
||||
m_ratioFormatter->IsGrouped = true;
|
||||
m_ratioFormatter->IsDecimalPointAlwaysDisplayed = true;
|
||||
m_ratioFormatter->FractionDigits = FORMATTER_DIGIT_COUNT;
|
||||
|
||||
m_ratioFormat = AppResourceProvider::GetInstance().GetResourceString(L"CurrencyFromToRatioFormat")->Data();
|
||||
m_timestampFormat = AppResourceProvider::GetInstance().GetResourceString(L"CurrencyTimestampFormat")->Data();
|
||||
}
|
||||
|
||||
CurrencyDataLoader::~CurrencyDataLoader()
|
||||
{
|
||||
UnregisterForNetworkBehaviorChanges();
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::UnregisterForNetworkBehaviorChanges()
|
||||
{
|
||||
m_networkManager->NetworkBehaviorChanged -= m_networkBehaviorToken;
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::RegisterForNetworkBehaviorChanges()
|
||||
{
|
||||
UnregisterForNetworkBehaviorChanges();
|
||||
|
||||
m_networkBehaviorToken =
|
||||
m_networkManager->NetworkBehaviorChanged += ref new NetworkBehaviorChangedHandler([this](NetworkAccessBehavior newBehavior)
|
||||
{
|
||||
this->OnNetworkBehaviorChanged(newBehavior);
|
||||
});
|
||||
|
||||
OnNetworkBehaviorChanged(NetworkManager::GetNetworkAccessBehavior());
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::OnNetworkBehaviorChanged(NetworkAccessBehavior newBehavior)
|
||||
{
|
||||
m_networkAccessBehavior = newBehavior;
|
||||
if (m_vmCallback != nullptr)
|
||||
{
|
||||
m_vmCallback->NetworkBehaviorChanged(static_cast<int>(m_networkAccessBehavior));
|
||||
}
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::LoadFinished()
|
||||
{
|
||||
return m_loadStatus != CurrencyLoadStatus::NotLoaded;
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::LoadedFromCache()
|
||||
{
|
||||
return m_loadStatus == CurrencyLoadStatus::LoadedFromCache;
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::LoadedFromWeb()
|
||||
{
|
||||
return m_loadStatus == CurrencyLoadStatus::LoadedFromWeb;
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::ResetLoadStatus()
|
||||
{
|
||||
m_loadStatus = CurrencyLoadStatus::NotLoaded;
|
||||
}
|
||||
|
||||
#pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321
|
||||
void CurrencyDataLoader::LoadData()
|
||||
{
|
||||
RegisterForNetworkBehaviorChanges();
|
||||
|
||||
if (!LoadFinished())
|
||||
{
|
||||
create_task([this]() -> task<bool>
|
||||
{
|
||||
vector<function<task<bool>()>> loadFunctions = {
|
||||
[this]() { return TryLoadDataFromCacheAsync(); },
|
||||
[this]() { return TryLoadDataFromWebAsync(); },
|
||||
};
|
||||
|
||||
bool didLoad = false;
|
||||
for (auto& f : loadFunctions)
|
||||
{
|
||||
didLoad = co_await f();
|
||||
if (didLoad)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
co_return didLoad;
|
||||
}).then([this](bool didLoad)
|
||||
{
|
||||
UpdateDisplayedTimestamp();
|
||||
NotifyDataLoadFinished(didLoad);
|
||||
}, task_continuation_context::use_current());
|
||||
}
|
||||
};
|
||||
#pragma optimize("", on)
|
||||
|
||||
vector<UCM::Category> CurrencyDataLoader::LoadOrderedCategories()
|
||||
{
|
||||
// This function should not be called
|
||||
// The model will use the categories from UnitConverterDataLoader
|
||||
return vector<UCM::Category>();
|
||||
}
|
||||
|
||||
vector<UCM::Unit> CurrencyDataLoader::LoadOrderedUnits(const UCM::Category& /*category*/)
|
||||
{
|
||||
lock_guard<mutex> lock(m_currencyUnitsMutex);
|
||||
return m_currencyUnits;
|
||||
}
|
||||
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> CurrencyDataLoader::LoadOrderedRatios(const UCM::Unit& unit)
|
||||
{
|
||||
lock_guard<mutex> lock(m_currencyUnitsMutex);
|
||||
return m_currencyRatioMap.at(unit);
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::SupportsCategory(const UCM::Category& target)
|
||||
{
|
||||
static int currencyId = NavCategory::Serialize(ViewMode::Currency);
|
||||
return target.id == currencyId;
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::SetViewModelCallback(const shared_ptr<UCM::IViewModelCurrencyCallback>& callback)
|
||||
{
|
||||
m_vmCallback = callback;
|
||||
OnNetworkBehaviorChanged(m_networkAccessBehavior);
|
||||
}
|
||||
|
||||
pair<wstring, wstring> CurrencyDataLoader::GetCurrencySymbols(const UCM::Unit& unit1, const UCM::Unit& unit2)
|
||||
{
|
||||
lock_guard<mutex> lock(m_currencyUnitsMutex);
|
||||
|
||||
wstring symbol1 = L"";
|
||||
wstring symbol2 = L"";
|
||||
|
||||
auto itr1 = m_currencyMetadata.find(unit1);
|
||||
auto itr2 = m_currencyMetadata.find(unit2);
|
||||
if (itr1 != m_currencyMetadata.end() && itr2 != m_currencyMetadata.end())
|
||||
{
|
||||
symbol1 = (itr1->second).symbol;
|
||||
symbol2 = (itr2->second).symbol;
|
||||
}
|
||||
|
||||
return make_pair(symbol1, symbol2);
|
||||
}
|
||||
|
||||
pair<wstring, wstring> CurrencyDataLoader::GetCurrencyRatioEquality(_In_ const UCM::Unit& unit1, _In_ const UCM::Unit& unit2)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto iter = m_currencyRatioMap.find(unit1);
|
||||
if (iter != m_currencyRatioMap.end())
|
||||
{
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> ratioMap = iter->second;
|
||||
auto iter2 = ratioMap.find(unit2);
|
||||
if (iter2 != ratioMap.end())
|
||||
{
|
||||
double ratio = (iter2->second).ratio;
|
||||
|
||||
// Round the raio to FORMATTER_DIGIT_COUNT digits using int math.
|
||||
// Ex: to round 1.23456 to three digits, use
|
||||
// ((int) 1.23456 * (10^3)) / (10^3)
|
||||
double scale = pow(10, FORMATTER_DIGIT_COUNT);
|
||||
double rounded = static_cast<int>(ratio * static_cast<int>(scale)) / scale;
|
||||
|
||||
wstring digitSymbol = wstring{ LocalizationSettings::GetInstance().GetDigitSymbolFromEnUsDigit(L'1') };
|
||||
wstring roundedFormat = m_ratioFormatter->Format(rounded)->Data();
|
||||
|
||||
wstring ratioString = LocalizationStringUtil::GetLocalizedString(
|
||||
m_ratioFormat.c_str(),
|
||||
digitSymbol.c_str(),
|
||||
unit1.abbreviation.c_str(),
|
||||
roundedFormat.c_str(),
|
||||
unit2.abbreviation.c_str()
|
||||
);
|
||||
|
||||
wstring accessibleRatioString = LocalizationStringUtil::GetLocalizedString(
|
||||
m_ratioFormat.c_str(),
|
||||
digitSymbol.c_str(),
|
||||
unit1.accessibleName.c_str(),
|
||||
roundedFormat.c_str(),
|
||||
unit2.accessibleName.c_str()
|
||||
);
|
||||
|
||||
return make_pair(ratioString, accessibleRatioString);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
return make_pair(L"", L"");
|
||||
}
|
||||
|
||||
#pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321
|
||||
task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
ResetLoadStatus();
|
||||
|
||||
auto localSettings = ApplicationData::Current->LocalSettings;
|
||||
if (localSettings == nullptr || !localSettings->Values->HasKey(CacheTimestampKey))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
bool loadComplete = false;
|
||||
m_cacheTimestamp = static_cast<DateTime>(localSettings->Values->Lookup(CacheTimestampKey));
|
||||
if (Utils::IsDateTimeOlderThan(m_cacheTimestamp, DAY_DURATION)
|
||||
&& m_networkAccessBehavior == NetworkAccessBehavior::Normal)
|
||||
{
|
||||
loadComplete = co_await TryLoadDataFromWebAsync();
|
||||
}
|
||||
|
||||
if (!loadComplete)
|
||||
{
|
||||
loadComplete = co_await TryFinishLoadFromCacheAsync();
|
||||
}
|
||||
|
||||
co_return loadComplete;
|
||||
}
|
||||
catch (Exception^ ex)
|
||||
{
|
||||
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
|
||||
co_return false;
|
||||
}
|
||||
catch (const exception& e)
|
||||
{
|
||||
TraceLogger::GetInstance().LogStandardException(__FUNCTIONW__, e);
|
||||
co_return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
}
|
||||
|
||||
task<bool> CurrencyDataLoader::TryFinishLoadFromCacheAsync()
|
||||
{
|
||||
auto localSettings = ApplicationData::Current->LocalSettings;
|
||||
if (localSettings == nullptr)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
if (!localSettings->Values->HasKey(CacheLangcodeKey)
|
||||
|| !static_cast<String^>(localSettings->Values->Lookup(CacheLangcodeKey))->Equals(m_responseLanguage))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
StorageFolder^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
|
||||
if (localCacheFolder == nullptr)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
String^ staticDataResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, StaticDataFilename);
|
||||
String^ allRatiosResponse = co_await Utils::ReadFileFromFolder(localCacheFolder, AllRatiosDataFilename);
|
||||
|
||||
vector<UCM::CurrencyStaticData> staticData{};
|
||||
CurrencyRatioMap ratioMap{};
|
||||
|
||||
bool didParse = TryParseWebResponses(
|
||||
staticDataResponse,
|
||||
allRatiosResponse,
|
||||
staticData,
|
||||
ratioMap);
|
||||
if (!didParse)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
m_loadStatus = CurrencyLoadStatus::LoadedFromCache;
|
||||
co_await FinalizeUnits(staticData, ratioMap);
|
||||
|
||||
co_return true;
|
||||
}
|
||||
|
||||
task<bool> CurrencyDataLoader::TryLoadDataFromWebAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
ResetLoadStatus();
|
||||
|
||||
if (m_client == nullptr)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
if (m_networkAccessBehavior == NetworkAccessBehavior::Offline ||
|
||||
(m_networkAccessBehavior == NetworkAccessBehavior::OptIn && !m_meteredOverrideSet))
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
String^ staticDataResponse = co_await m_client->GetCurrencyMetadata();
|
||||
String^ allRatiosResponse = co_await m_client->GetCurrencyRatios();
|
||||
if (staticDataResponse == nullptr || allRatiosResponse == nullptr)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
vector<UCM::CurrencyStaticData> staticData{};
|
||||
CurrencyRatioMap ratioMap{};
|
||||
|
||||
bool didParse = TryParseWebResponses(
|
||||
staticDataResponse,
|
||||
allRatiosResponse,
|
||||
staticData,
|
||||
ratioMap);
|
||||
if (!didParse)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
|
||||
// Set the timestamp before saving it below.
|
||||
m_cacheTimestamp = Utils::GetUniversalSystemTime();
|
||||
|
||||
try
|
||||
{
|
||||
const vector<pair<String^, String^>> cachedFiles = {
|
||||
{ StaticDataFilename, staticDataResponse },
|
||||
{ AllRatiosDataFilename, allRatiosResponse }
|
||||
};
|
||||
|
||||
StorageFolder^ localCacheFolder = ApplicationData::Current->LocalCacheFolder;
|
||||
for (const auto& fileInfo : cachedFiles)
|
||||
{
|
||||
co_await Utils::WriteFileToFolder(
|
||||
localCacheFolder,
|
||||
fileInfo.first,
|
||||
fileInfo.second,
|
||||
CreationCollisionOption::ReplaceExisting);
|
||||
}
|
||||
|
||||
SaveLangCodeAndTimestamp();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// If we fail to save to cache it's okay, we should still continue.
|
||||
}
|
||||
|
||||
m_loadStatus = CurrencyLoadStatus::LoadedFromWeb;
|
||||
co_await FinalizeUnits(staticData, ratioMap);
|
||||
|
||||
co_return true;
|
||||
}
|
||||
catch (Exception^ ex)
|
||||
{
|
||||
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, ex);
|
||||
co_return false;
|
||||
}
|
||||
catch (const exception& e)
|
||||
{
|
||||
TraceLogger::GetInstance().LogStandardException(__FUNCTIONW__, e);
|
||||
co_return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
co_return false;
|
||||
}
|
||||
}
|
||||
|
||||
task<bool> CurrencyDataLoader::TryLoadDataFromWebOverrideAsync()
|
||||
{
|
||||
m_meteredOverrideSet = true;
|
||||
bool didLoad = co_await TryLoadDataFromWebAsync();
|
||||
if (!didLoad)
|
||||
{
|
||||
m_loadStatus = CurrencyLoadStatus::FailedToLoad;
|
||||
TraceLogger::GetInstance().LogUserRequestedRefreshFailed();
|
||||
}
|
||||
|
||||
co_return didLoad;
|
||||
};
|
||||
#pragma optimize("", on)
|
||||
|
||||
bool CurrencyDataLoader::TryParseWebResponses(
|
||||
_In_ String^ staticDataJson,
|
||||
_In_ String^ allRatiosJson,
|
||||
_Inout_ vector<UCM::CurrencyStaticData>& staticData,
|
||||
_Inout_ CurrencyRatioMap& allRatiosData)
|
||||
{
|
||||
return TryParseStaticData(staticDataJson, staticData)
|
||||
&& TryParseAllRatiosData(allRatiosJson, allRatiosData);
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::TryParseStaticData(_In_ String^ rawJson, _Inout_ vector<UCM::CurrencyStaticData>& staticData)
|
||||
{
|
||||
JsonArray^ data = nullptr;
|
||||
if (!JsonArray::TryParse(rawJson, &data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wstring countryCode{ L"" };
|
||||
wstring countryName{ L"" };
|
||||
wstring currencyCode{ L"" };
|
||||
wstring currencyName{ L"" };
|
||||
wstring currencySymbol{ L"" };
|
||||
|
||||
vector<wstring*> values = {
|
||||
&countryCode,
|
||||
&countryName,
|
||||
¤cyCode,
|
||||
¤cyName,
|
||||
¤cySymbol
|
||||
};
|
||||
|
||||
assert(values.size() == STATIC_DATA_PROPERTIES.size());
|
||||
staticData.resize(size_t{ data->Size });
|
||||
for (unsigned int i = 0; i < data->Size; i++)
|
||||
{
|
||||
JsonObject^ obj = data->GetAt(i)->GetObject();
|
||||
|
||||
for (size_t j = 0; j < values.size(); j++)
|
||||
{
|
||||
(*values[j]) = obj->GetNamedString(StringReference(STATIC_DATA_PROPERTIES[j].data()))->Data();
|
||||
}
|
||||
|
||||
staticData[i] = CurrencyStaticData{
|
||||
countryCode,
|
||||
countryName,
|
||||
currencyCode,
|
||||
currencyName,
|
||||
currencySymbol
|
||||
};
|
||||
}
|
||||
|
||||
// TODO - MSFT 8533667: this sort will be replaced by a WinRT call to sort localized strings
|
||||
sort(begin(staticData), end(staticData), [](CurrencyStaticData unit1, CurrencyStaticData unit2)
|
||||
{
|
||||
return unit1.countryName < unit2.countryName;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CurrencyDataLoader::TryParseAllRatiosData(_In_ String^ rawJson, _Inout_ CurrencyRatioMap& allRatios)
|
||||
{
|
||||
JsonArray^ data = nullptr;
|
||||
if (!JsonArray::TryParse(rawJson, &data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wstring sourceCurrencyCode{ DefaultCurrencyCode };
|
||||
|
||||
allRatios.clear();
|
||||
for (unsigned int i = 0; i < data->Size; i++)
|
||||
{
|
||||
JsonObject^ obj = data->GetAt(i)->GetObject();
|
||||
|
||||
// Rt is ratio, An is target currency ISO code.
|
||||
double relativeRatio = obj->GetNamedNumber(StringReference(RATIO_KEY));
|
||||
wstring targetCurrencyCode = obj->GetNamedString(StringReference(CURRENCY_CODE_KEY))->Data();
|
||||
|
||||
allRatios.emplace(targetCurrencyCode, CurrencyRatio{
|
||||
relativeRatio,
|
||||
sourceCurrencyCode,
|
||||
targetCurrencyCode
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FinalizeUnits
|
||||
//
|
||||
// There are a few ways we can get the data needed for Currency Converter, including from cache or from web.
|
||||
// This function accepts the data from any source, and acts as a 'last-steps' for the converter to be ready.
|
||||
// This includes identifying which units will be selected and building the map of curreny ratios.
|
||||
#pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321
|
||||
task<void> CurrencyDataLoader::FinalizeUnits(_In_ const vector<UCM::CurrencyStaticData>& staticData, _In_ const CurrencyRatioMap& ratioMap)
|
||||
{
|
||||
unordered_map<int, pair<UCM::Unit, double>> idToUnit{};
|
||||
|
||||
SelectedUnits defaultCurrencies = co_await GetDefaultFromToCurrency();
|
||||
wstring fromCurrency = defaultCurrencies.first;
|
||||
wstring toCurrency = defaultCurrencies.second;
|
||||
|
||||
{
|
||||
lock_guard<mutex> lock(m_currencyUnitsMutex);
|
||||
|
||||
int i = 1;
|
||||
m_currencyUnits.clear();
|
||||
m_currencyMetadata.clear();
|
||||
bool isConversionSourceSet = false;
|
||||
bool isConversionTargetSet = false;
|
||||
for (const UCM::CurrencyStaticData& currencyUnit : staticData)
|
||||
{
|
||||
auto itr = ratioMap.find(currencyUnit.currencyCode);
|
||||
if (itr != ratioMap.end() && (itr->second).ratio > 0)
|
||||
{
|
||||
int id = static_cast<int>(UnitConverterUnits::UnitEnd + i);
|
||||
|
||||
bool isConversionSource = (fromCurrency == currencyUnit.currencyCode);
|
||||
isConversionSourceSet = isConversionSourceSet || isConversionSource;
|
||||
|
||||
bool isConversionTarget = (toCurrency == currencyUnit.currencyCode);
|
||||
isConversionTargetSet = isConversionTargetSet || isConversionTarget;
|
||||
|
||||
UCM::Unit unit = UCM::Unit{
|
||||
id, // id
|
||||
currencyUnit.currencyName, // currencyName
|
||||
currencyUnit.countryName, // countryName
|
||||
currencyUnit.currencyCode, // abbreviation
|
||||
m_isRtlLanguage, // isRtlLanguage
|
||||
isConversionSource, // isConversionSource
|
||||
isConversionTarget // isConversionTarget
|
||||
};
|
||||
|
||||
m_currencyUnits.push_back(unit);
|
||||
m_currencyMetadata.emplace(unit, CurrencyUnitMetadata{ currencyUnit.currencySymbol });
|
||||
idToUnit.insert(pair<int, pair<UCM::Unit, double>>(unit.id, pair<UCM::Unit, double>(unit, (itr->second).ratio)));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isConversionSourceSet || !isConversionTargetSet)
|
||||
{
|
||||
GuaranteeSelectedUnits();
|
||||
defaultCurrencies = { DEFAULT_FROM_CURRENCY, DEFAULT_TO_CURRENCY };
|
||||
}
|
||||
|
||||
m_currencyRatioMap.clear();
|
||||
for (const auto& unit : m_currencyUnits)
|
||||
{
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> conversions;
|
||||
double unitFactor = idToUnit[unit.id].second;
|
||||
for (auto itr = idToUnit.begin(); itr != idToUnit.end(); itr++)
|
||||
{
|
||||
UCM::Unit targetUnit = (itr->second).first;
|
||||
double conversionRatio = (itr->second).second;
|
||||
UCM::ConversionData parsedData = { 1.0, 0.0, false };
|
||||
assert(unitFactor > 0); // divide by zero assert
|
||||
parsedData.ratio = conversionRatio / unitFactor;
|
||||
conversions.insert(make_pair(targetUnit, parsedData));
|
||||
}
|
||||
|
||||
m_currencyRatioMap.insert(make_pair(unit, conversions));
|
||||
}
|
||||
} // unlocked m_currencyUnitsMutex
|
||||
|
||||
SaveSelectedUnitsToLocalSettings(defaultCurrencies);
|
||||
};
|
||||
#pragma optimize("", on)
|
||||
|
||||
void CurrencyDataLoader::GuaranteeSelectedUnits()
|
||||
{
|
||||
bool isConversionSourceSet = false;
|
||||
bool isConversionTargetSet = false;
|
||||
for (UCM::Unit& unit : m_currencyUnits)
|
||||
{
|
||||
unit.isConversionSource = false;
|
||||
unit.isConversionTarget = false;
|
||||
|
||||
if (!isConversionSourceSet && unit.abbreviation == DEFAULT_FROM_CURRENCY)
|
||||
{
|
||||
unit.isConversionSource = true;
|
||||
isConversionSourceSet = true;
|
||||
}
|
||||
if (!isConversionTargetSet && unit.abbreviation == DEFAULT_TO_CURRENCY)
|
||||
{
|
||||
unit.isConversionTarget = true;
|
||||
isConversionTargetSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::NotifyDataLoadFinished(bool didLoad)
|
||||
{
|
||||
if (!didLoad)
|
||||
{
|
||||
m_loadStatus = CurrencyLoadStatus::FailedToLoad;
|
||||
}
|
||||
|
||||
if (m_vmCallback != nullptr)
|
||||
{
|
||||
m_vmCallback->CurrencyDataLoadFinished(didLoad);
|
||||
}
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::SaveLangCodeAndTimestamp()
|
||||
{
|
||||
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
|
||||
if (localSettings == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
localSettings->Values->Insert(CacheTimestampKey, m_cacheTimestamp);
|
||||
localSettings->Values->Insert(CacheLangcodeKey, m_responseLanguage);
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::UpdateDisplayedTimestamp()
|
||||
{
|
||||
if (m_vmCallback != nullptr)
|
||||
{
|
||||
wstring timestamp = GetCurrencyTimestamp();
|
||||
bool isWeekOld = Utils::IsDateTimeOlderThan(m_cacheTimestamp, WEEK_DURATION);
|
||||
|
||||
m_vmCallback->CurrencyTimestampCallback(timestamp, isWeekOld);
|
||||
}
|
||||
}
|
||||
wstring CurrencyDataLoader::GetCurrencyTimestamp()
|
||||
{
|
||||
wstring timestamp = L"";
|
||||
|
||||
DateTime epoch{};
|
||||
if (m_cacheTimestamp.UniversalTime != epoch.UniversalTime)
|
||||
{
|
||||
DateTimeFormatter^ dateFormatter = ref new DateTimeFormatter(L"{month.abbreviated} {day.integer}, {year.full}");
|
||||
wstring date = dateFormatter->Format(m_cacheTimestamp)->Data();
|
||||
|
||||
DateTimeFormatter^ timeFormatter = ref new DateTimeFormatter(L"shorttime");
|
||||
wstring time = timeFormatter->Format(m_cacheTimestamp)->Data();
|
||||
|
||||
timestamp = LocalizationStringUtil::GetLocalizedString(
|
||||
m_timestampFormat.c_str(),
|
||||
date.c_str(),
|
||||
time.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
#pragma optimize("", off) // Turn off optimizations to work around DevDiv 393321
|
||||
task<SelectedUnits> CurrencyDataLoader::GetDefaultFromToCurrency()
|
||||
{
|
||||
wstring fromCurrency{ DEFAULT_FROM_CURRENCY };
|
||||
wstring toCurrency{ DEFAULT_TO_CURRENCY };
|
||||
|
||||
// First, check if we previously stored the last used currencies.
|
||||
bool foundInLocalSettings = TryGetLastUsedCurrenciesFromLocalSettings(&fromCurrency, &toCurrency);
|
||||
if (!foundInLocalSettings)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Second, see if the current locale has preset defaults in DefaultFromToCurrency.json.
|
||||
Uri^ fileUri = ref new Uri(StringReference(DEFAULT_FROM_TO_CURRENCY_FILE_URI));
|
||||
StorageFile^ defaultFromToCurrencyFile = co_await StorageFile::GetFileFromApplicationUriAsync(fileUri);
|
||||
if (defaultFromToCurrencyFile != nullptr)
|
||||
{
|
||||
String^ fileContents = co_await FileIO::ReadTextAsync(defaultFromToCurrencyFile);
|
||||
JsonObject^ fromToObject = JsonObject::Parse(fileContents);
|
||||
JsonObject^ regionalDefaults = fromToObject->GetNamedObject(m_responseLanguage);
|
||||
|
||||
// Get both values before assignment in-case either fails.
|
||||
String^ selectedFrom = regionalDefaults->GetNamedString(StringReference(FROM_KEY));
|
||||
String^ selectedTo = regionalDefaults->GetNamedString(StringReference(TO_KEY));
|
||||
|
||||
fromCurrency = selectedFrom->Data();
|
||||
toCurrency = selectedTo->Data();
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
co_return make_pair(fromCurrency, toCurrency);
|
||||
};
|
||||
#pragma optimize("", on)
|
||||
|
||||
bool CurrencyDataLoader::TryGetLastUsedCurrenciesFromLocalSettings(_Out_ wstring* const fromCurrency, _Out_ wstring* const toCurrency)
|
||||
{
|
||||
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
|
||||
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
|
||||
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
|
||||
if (localSettings != nullptr && localSettings->Values != nullptr)
|
||||
{
|
||||
IPropertySet^ values = localSettings->Values;
|
||||
if (values->HasKey(fromKey) && values->HasKey(toKey))
|
||||
{
|
||||
*fromCurrency = static_cast<String^>(values->Lookup(fromKey))->Data();
|
||||
*toCurrency = static_cast<String^>(values->Lookup(toKey))->Data();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CurrencyDataLoader::SaveSelectedUnitsToLocalSettings(_In_ const SelectedUnits& selectedUnits)
|
||||
{
|
||||
String^ fromKey = UnitConverterResourceKeys::CurrencyUnitFromKey;
|
||||
String^ toKey = UnitConverterResourceKeys::CurrencyUnitToKey;
|
||||
ApplicationDataContainer^ localSettings = ApplicationData::Current->LocalSettings;
|
||||
if (localSettings != nullptr && localSettings->Values != nullptr)
|
||||
{
|
||||
IPropertySet^ values = localSettings->Values;
|
||||
values->Insert(fromKey, StringReference(selectedUnits.first.c_str()));
|
||||
values->Insert(toKey, StringReference(selectedUnits.second.c_str()));
|
||||
}
|
||||
}
|
133
src/CalcViewModel/DataLoaders/CurrencyDataLoader.h
Normal file
133
src/CalcViewModel/DataLoaders/CurrencyDataLoader.h
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Common\NetworkManager.h"
|
||||
#include "ICurrencyHttpClient.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
public enum class CurrencyLoadStatus
|
||||
{
|
||||
NotLoaded = 0,
|
||||
FailedToLoad = 1,
|
||||
LoadedFromCache = 2,
|
||||
LoadedFromWeb = 3
|
||||
};
|
||||
|
||||
namespace UnitConverterResourceKeys
|
||||
{
|
||||
extern Platform::StringReference CurrencyUnitFromKey;
|
||||
extern Platform::StringReference CurrencyUnitToKey;
|
||||
}
|
||||
|
||||
namespace CurrencyDataLoaderConstants
|
||||
{
|
||||
extern Platform::StringReference CacheTimestampKey;
|
||||
extern Platform::StringReference CacheLangcodeKey;
|
||||
extern Platform::StringReference CacheDelimiter;
|
||||
extern Platform::StringReference StaticDataFilename;
|
||||
extern Platform::StringReference AllRatiosDataFilename;
|
||||
extern long long DayDuration;
|
||||
}
|
||||
|
||||
namespace UCM = UnitConversionManager;
|
||||
|
||||
typedef std::unordered_map<std::wstring, UCM::CurrencyRatio> CurrencyRatioMap;
|
||||
typedef std::pair<std::wstring, std::wstring> SelectedUnits;
|
||||
|
||||
struct CurrencyUnitMetadata
|
||||
{
|
||||
CurrencyUnitMetadata(const std::wstring& s) : symbol(s) {}
|
||||
|
||||
const std::wstring symbol;
|
||||
};
|
||||
|
||||
class CurrencyDataLoader : public UCM::IConverterDataLoader,
|
||||
public UCM::ICurrencyConverterDataLoader
|
||||
{
|
||||
public:
|
||||
CurrencyDataLoader(_In_ std::unique_ptr<CalculatorApp::DataLoaders::ICurrencyHttpClient> client);
|
||||
~CurrencyDataLoader();
|
||||
|
||||
bool LoadFinished();
|
||||
bool LoadedFromCache();
|
||||
bool LoadedFromWeb();
|
||||
|
||||
// IConverterDataLoader
|
||||
void LoadData() override;
|
||||
std::vector<UCM::Category> LoadOrderedCategories() override;
|
||||
std::vector<UCM::Unit> LoadOrderedUnits(const UCM::Category& category) override;
|
||||
std::unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> LoadOrderedRatios(const UCM::Unit& unit) override;
|
||||
bool SupportsCategory(const UnitConversionManager::Category& target) override;
|
||||
// IConverterDataLoader
|
||||
|
||||
// ICurrencyConverterDataLoader
|
||||
void SetViewModelCallback(const std::shared_ptr<UCM::IViewModelCurrencyCallback>& callback) override;
|
||||
std::pair<std::wstring, std::wstring> GetCurrencySymbols(const UCM::Unit& unit1, const UCM::Unit& unit2) override;
|
||||
std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) override;
|
||||
std::wstring GetCurrencyTimestamp() override;
|
||||
|
||||
concurrency::task<bool> TryLoadDataFromCacheAsync() override;
|
||||
concurrency::task<bool> TryLoadDataFromWebAsync() override;
|
||||
concurrency::task<bool> TryLoadDataFromWebOverrideAsync() override;
|
||||
// ICurrencyConverterDataLoader
|
||||
|
||||
void OnNetworkBehaviorChanged(CalculatorApp::NetworkAccessBehavior newBehavior);
|
||||
|
||||
private:
|
||||
void ResetLoadStatus();
|
||||
void NotifyDataLoadFinished(bool didLoad);
|
||||
|
||||
concurrency::task<bool> TryFinishLoadFromCacheAsync();
|
||||
|
||||
bool TryParseWebResponses(
|
||||
_In_ Platform::String^ staticDataJson,
|
||||
_In_ Platform::String^ allRatiosJson,
|
||||
_Inout_ std::vector<UCM::CurrencyStaticData>& staticData,
|
||||
_Inout_ CurrencyRatioMap& allRatiosData);
|
||||
bool TryParseStaticData(_In_ Platform::String^ rawJson, _Inout_ std::vector<UCM::CurrencyStaticData>& staticData);
|
||||
bool TryParseAllRatiosData(_In_ Platform::String^ rawJson, _Inout_ CurrencyRatioMap& allRatiosData);
|
||||
concurrency::task<void> FinalizeUnits(_In_ const std::vector<UCM::CurrencyStaticData>& staticData, _In_ const CurrencyRatioMap& ratioMap);
|
||||
void GuaranteeSelectedUnits();
|
||||
|
||||
void SaveLangCodeAndTimestamp();
|
||||
void UpdateDisplayedTimestamp();
|
||||
|
||||
void RegisterForNetworkBehaviorChanges();
|
||||
void UnregisterForNetworkBehaviorChanges();
|
||||
|
||||
concurrency::task<SelectedUnits> GetDefaultFromToCurrency();
|
||||
bool TryGetLastUsedCurrenciesFromLocalSettings(_Out_ std::wstring* const fromCurrency, _Out_ std::wstring* const toCurrency);
|
||||
void SaveSelectedUnitsToLocalSettings(_In_ const SelectedUnits& selectedUnits);
|
||||
|
||||
private:
|
||||
Platform::String^ m_responseLanguage;
|
||||
std::unique_ptr<CalculatorApp::DataLoaders::ICurrencyHttpClient> m_client;
|
||||
|
||||
bool m_isRtlLanguage;
|
||||
|
||||
std::mutex m_currencyUnitsMutex;
|
||||
std::vector<UCM::Unit> m_currencyUnits;
|
||||
UCM::UnitToUnitToConversionDataMap m_currencyRatioMap;
|
||||
std::unordered_map<UCM::Unit, CurrencyUnitMetadata, UCM::UnitHash> m_currencyMetadata;
|
||||
|
||||
std::shared_ptr<UCM::IViewModelCurrencyCallback> m_vmCallback;
|
||||
|
||||
Windows::Globalization::NumberFormatting::DecimalFormatter^ m_ratioFormatter;
|
||||
std::wstring m_ratioFormat;
|
||||
Windows::Foundation::DateTime m_cacheTimestamp;
|
||||
std::wstring m_timestampFormat;
|
||||
|
||||
CurrencyLoadStatus m_loadStatus;
|
||||
|
||||
CalculatorApp::NetworkManager^ m_networkManager;
|
||||
CalculatorApp::NetworkAccessBehavior m_networkAccessBehavior;
|
||||
Windows::Foundation::EventRegistrationToken m_networkBehaviorToken;
|
||||
bool m_meteredOverrideSet;
|
||||
};
|
||||
}
|
||||
}
|
46
src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp
Normal file
46
src/CalcViewModel/DataLoaders/CurrencyHttpClient.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "CurrencyHttpClient.h"
|
||||
|
||||
using namespace CalculatorApp::DataLoaders;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Web::Http;
|
||||
|
||||
static constexpr auto sc_MetadataUriLocalizeFor = L"https://go.microsoft.com/fwlink/?linkid=2041093&localizeFor=";
|
||||
static constexpr auto sc_RatiosUriRelativeTo = L"https://go.microsoft.com/fwlink/?linkid=2041339&localCurrency=";
|
||||
|
||||
CurrencyHttpClient::CurrencyHttpClient() :
|
||||
m_client(ref new HttpClient()),
|
||||
m_responseLanguage(L"en-US")
|
||||
{
|
||||
}
|
||||
|
||||
void CurrencyHttpClient::SetSourceCurrencyCode(String^ sourceCurrencyCode)
|
||||
{
|
||||
m_sourceCurrencyCode = sourceCurrencyCode;
|
||||
}
|
||||
|
||||
void CurrencyHttpClient::SetResponseLanguage(String^ responseLanguage)
|
||||
{
|
||||
m_responseLanguage = responseLanguage;
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyMetadata()
|
||||
{
|
||||
wstring uri = wstring{ sc_MetadataUriLocalizeFor } + m_responseLanguage->Data();
|
||||
auto metadataUri = ref new Uri(StringReference(uri.c_str()));
|
||||
|
||||
return m_client->GetStringAsync(metadataUri);
|
||||
}
|
||||
|
||||
IAsyncOperationWithProgress<String^, HttpProgress>^ CurrencyHttpClient::GetCurrencyRatios()
|
||||
{
|
||||
wstring uri = wstring{ sc_RatiosUriRelativeTo } + m_sourceCurrencyCode->Data();
|
||||
auto ratiosUri = ref new Uri(StringReference(uri.c_str()));
|
||||
|
||||
return m_client->GetStringAsync(ratiosUri);
|
||||
}
|
29
src/CalcViewModel/DataLoaders/CurrencyHttpClient.h
Normal file
29
src/CalcViewModel/DataLoaders/CurrencyHttpClient.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ICurrencyHttpClient.h"
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace DataLoaders
|
||||
{
|
||||
class CurrencyHttpClient : public ICurrencyHttpClient
|
||||
{
|
||||
public:
|
||||
CurrencyHttpClient();
|
||||
|
||||
void SetSourceCurrencyCode(Platform::String^ sourceCurrencyCode) override;
|
||||
void SetResponseLanguage(Platform::String^ responseLanguage) override;
|
||||
|
||||
Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyMetadata() override;
|
||||
Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyRatios() override;
|
||||
|
||||
private:
|
||||
Windows::Web::Http::HttpClient^ m_client;
|
||||
Platform::String^ m_responseLanguage;
|
||||
Platform::String^ m_sourceCurrencyCode;
|
||||
};
|
||||
}
|
||||
}
|
134
src/CalcViewModel/DataLoaders/DefaultFromToCurrency.json
Normal file
134
src/CalcViewModel/DataLoaders/DefaultFromToCurrency.json
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"default": {
|
||||
"from": "USD",
|
||||
"to": "EUR"
|
||||
},
|
||||
"ar-AE": {
|
||||
"from": "USD",
|
||||
"to": "AED"
|
||||
},
|
||||
"ar-EG": {
|
||||
"from": "USD",
|
||||
"to": "EGP"
|
||||
},
|
||||
"ar-SA": {
|
||||
"from": "USD",
|
||||
"to": "SAR"
|
||||
},
|
||||
"da-DK": {
|
||||
"from": "DKK",
|
||||
"to": "USD"
|
||||
},
|
||||
"de-CH": {
|
||||
"from": "EUR",
|
||||
"to": "CHF"
|
||||
},
|
||||
"de-DE": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"en-AU": {
|
||||
"from": "AUD",
|
||||
"to": "USD"
|
||||
},
|
||||
"en-CA": {
|
||||
"from": "CAD",
|
||||
"to": "USD"
|
||||
},
|
||||
"en-ES": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"en-GB": {
|
||||
"from": "GBP",
|
||||
"to": "USD"
|
||||
},
|
||||
"en-IN": {
|
||||
"from": "USD",
|
||||
"to": "INR"
|
||||
},
|
||||
"en-US": {
|
||||
"from": "USD",
|
||||
"to": "EUR"
|
||||
},
|
||||
"es-AR": {
|
||||
"from": "USD",
|
||||
"to": "ARS"
|
||||
},
|
||||
"es-CL": {
|
||||
"from": "USD",
|
||||
"to": "CLP"
|
||||
},
|
||||
"es-CO": {
|
||||
"from": "USD",
|
||||
"to": "COP"
|
||||
},
|
||||
"es-ES": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"es-MX": {
|
||||
"from": "USD",
|
||||
"to": "MXN"
|
||||
},
|
||||
"es-PE": {
|
||||
"from": "USD",
|
||||
"to": "PEN"
|
||||
},
|
||||
"es-VE": {
|
||||
"from": "USD",
|
||||
"to": "VEF"
|
||||
},
|
||||
"es-XL": {
|
||||
"from": "USD",
|
||||
"to": "EUR"
|
||||
},
|
||||
"es-US": {
|
||||
"from": "USD",
|
||||
"to": "EUR"
|
||||
},
|
||||
"fr-CH": {
|
||||
"from": "EUR",
|
||||
"to": "CHF"
|
||||
},
|
||||
"fr-FR": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"it-IT": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"it-SM": {
|
||||
"from": "EUR",
|
||||
"to": "USD"
|
||||
},
|
||||
"ja-JP": {
|
||||
"from": "USD",
|
||||
"to": "JPY"
|
||||
},
|
||||
"nb-NO": {
|
||||
"from": "NOK",
|
||||
"to": "USD"
|
||||
},
|
||||
"pt-BR": {
|
||||
"from": "USD",
|
||||
"to": "BRL"
|
||||
},
|
||||
"sv-SE": {
|
||||
"from": "SEK",
|
||||
"to": "USD"
|
||||
},
|
||||
"th-TH": {
|
||||
"from": "USD",
|
||||
"to": "THB"
|
||||
},
|
||||
"zh-CN": {
|
||||
"from": "USD",
|
||||
"to": "CNY"
|
||||
},
|
||||
"zh-HK": {
|
||||
"from": "USD",
|
||||
"to": "HKD"
|
||||
}
|
||||
}
|
22
src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h
Normal file
22
src/CalcViewModel/DataLoaders/ICurrencyHttpClient.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace DataLoaders
|
||||
{
|
||||
class ICurrencyHttpClient
|
||||
{
|
||||
public:
|
||||
virtual ~ICurrencyHttpClient() {}
|
||||
|
||||
virtual void SetSourceCurrencyCode(Platform::String^ sourceCurrencyCode) = 0;
|
||||
virtual void SetResponseLanguage(Platform::String^ responseLanguage) = 0;
|
||||
|
||||
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyMetadata() = 0;
|
||||
virtual Windows::Foundation::IAsyncOperationWithProgress<Platform::String^, Windows::Web::Http::HttpProgress>^ GetCurrencyRatios() = 0;
|
||||
};
|
||||
}
|
||||
}
|
168
src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h
Normal file
168
src/CalcViewModel/DataLoaders/UnitConverterDataConstants.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
private enum UnitConverterUnits
|
||||
{
|
||||
UnitStart = 0,
|
||||
Area_Acre = UnitStart + 1,
|
||||
Area_Hectare = UnitStart + 2,
|
||||
Area_SquareCentimeter = UnitStart + 3,
|
||||
Area_SquareFoot = UnitStart + 4,
|
||||
Area_SquareInch = UnitStart + 5,
|
||||
Area_SquareKilometer = UnitStart + 6,
|
||||
Area_SquareMeter = UnitStart + 7,
|
||||
Area_SquareMile = UnitStart + 8,
|
||||
Area_SquareMillimeter = UnitStart + 9,
|
||||
Area_SquareYard = UnitStart + 10,
|
||||
Data_Bit = UnitStart + 11,
|
||||
Data_Byte = UnitStart + 12,
|
||||
Data_Gigabit = UnitStart + 13,
|
||||
Data_Gigabyte = UnitStart + 14,
|
||||
Data_Kilobit = UnitStart + 15,
|
||||
Data_Kilobyte = UnitStart + 16,
|
||||
Data_Megabit = UnitStart + 17,
|
||||
Data_Megabyte = UnitStart + 18,
|
||||
Data_Petabit = UnitStart + 19,
|
||||
Data_Petabyte = UnitStart + 20,
|
||||
Data_Terabit = UnitStart + 21,
|
||||
Data_Terabyte = UnitStart + 22,
|
||||
Energy_BritishThermalUnit = UnitStart + 23,
|
||||
Energy_Calorie = UnitStart + 24,
|
||||
Energy_ElectronVolt = UnitStart + 25,
|
||||
Energy_FootPound = UnitStart + 26,
|
||||
Energy_Joule = UnitStart + 27,
|
||||
Energy_Kilocalorie = UnitStart + 28,
|
||||
Energy_Kilojoule = UnitStart + 29,
|
||||
Length_Centimeter = UnitStart + 30,
|
||||
Length_Foot = UnitStart + 31,
|
||||
Length_Inch = UnitStart + 32,
|
||||
Length_Kilometer = UnitStart + 33,
|
||||
Length_Meter = UnitStart + 34,
|
||||
Length_Micron = UnitStart + 35,
|
||||
Length_Mile = UnitStart + 36,
|
||||
Length_Millimeter = UnitStart + 37,
|
||||
Length_Nanometer = UnitStart + 38,
|
||||
Length_NauticalMile = UnitStart + 39,
|
||||
Length_Yard = UnitStart + 40,
|
||||
Power_BritishThermalUnitPerMinute = UnitStart + 41,
|
||||
Power_FootPoundPerMinute = UnitStart + 42,
|
||||
Power_Horsepower = UnitStart + 43,
|
||||
Power_Kilowatt = UnitStart + 44,
|
||||
Power_Watt = UnitStart + 45,
|
||||
Temperature_DegreesCelsius = UnitStart + 46,
|
||||
Temperature_DegreesFahrenheit = UnitStart + 47,
|
||||
Temperature_Kelvin = UnitStart + 48,
|
||||
Time_Day = UnitStart + 49,
|
||||
Time_Hour = UnitStart + 50,
|
||||
Time_Microsecond = UnitStart + 51,
|
||||
Time_Millisecond = UnitStart + 52,
|
||||
Time_Minute = UnitStart + 53,
|
||||
Time_Second = UnitStart + 54,
|
||||
Time_Week = UnitStart + 55,
|
||||
Time_Year = UnitStart + 56,
|
||||
Speed_CentimetersPerSecond = UnitStart + 57,
|
||||
Speed_FeetPerSecond = UnitStart + 58,
|
||||
Speed_KilometersPerHour = UnitStart + 59,
|
||||
Speed_Knot = UnitStart + 60,
|
||||
Speed_Mach = UnitStart + 61,
|
||||
Speed_MetersPerSecond = UnitStart + 62,
|
||||
Speed_MilesPerHour = UnitStart + 63,
|
||||
Volume_CubicCentimeter = UnitStart + 64,
|
||||
Volume_CubicFoot = UnitStart + 65,
|
||||
Volume_CubicInch = UnitStart + 66,
|
||||
Volume_CubicMeter = UnitStart + 67,
|
||||
Volume_CubicYard = UnitStart + 68,
|
||||
Volume_CupUS = UnitStart + 69,
|
||||
Volume_FluidOunceUK = UnitStart + 70,
|
||||
Volume_FluidOunceUS = UnitStart + 71,
|
||||
Volume_GallonUK = UnitStart + 72,
|
||||
Volume_GallonUS = UnitStart + 73,
|
||||
Volume_Liter = UnitStart + 74,
|
||||
Volume_Milliliter = UnitStart + 75,
|
||||
Volume_PintUK = UnitStart + 76,
|
||||
Volume_PintUS = UnitStart + 77,
|
||||
Volume_TablespoonUS = UnitStart + 78,
|
||||
Volume_TeaspoonUS = UnitStart + 79,
|
||||
Volume_QuartUK = UnitStart + 80,
|
||||
Volume_QuartUS = UnitStart + 81,
|
||||
Weight_Carat = UnitStart + 82,
|
||||
Weight_Centigram = UnitStart + 83,
|
||||
Weight_Decigram = UnitStart + 84,
|
||||
Weight_Decagram = UnitStart + 85,
|
||||
Weight_Gram = UnitStart + 86,
|
||||
Weight_Hectogram = UnitStart + 87,
|
||||
Weight_Kilogram = UnitStart + 88,
|
||||
Weight_LongTon = UnitStart + 89,
|
||||
Weight_Milligram = UnitStart + 90,
|
||||
Weight_Ounce = UnitStart + 91,
|
||||
Weight_Pound = UnitStart + 92,
|
||||
Weight_ShortTon = UnitStart + 93,
|
||||
Weight_Stone = UnitStart + 94,
|
||||
Weight_Tonne = UnitStart + 95,
|
||||
Area_SoccerField = UnitStart + 99,
|
||||
Data_FloppyDisk = UnitStart + 100,
|
||||
Data_CD = UnitStart + 101,
|
||||
Data_DVD = UnitStart + 102,
|
||||
Energy_Battery = UnitStart + 103,
|
||||
Length_Paperclip = UnitStart + 105,
|
||||
Length_JumboJet = UnitStart + 107,
|
||||
Power_LightBulb = UnitStart + 108,
|
||||
Power_Horse = UnitStart + 109,
|
||||
Volume_Bathtub = UnitStart + 111,
|
||||
Weight_Snowflake = UnitStart + 113,
|
||||
Weight_Elephant = UnitStart + 114,
|
||||
Volume_TeaspoonUK = UnitStart + 115,
|
||||
Volume_TablespoonUK = UnitStart + 116,
|
||||
Area_Hand = UnitStart + 118,
|
||||
Speed_Turtle = UnitStart + 121,
|
||||
Speed_Jet = UnitStart + 122,
|
||||
Volume_CoffeeCup = UnitStart + 124,
|
||||
Weight_Whale = UnitStart + 123,
|
||||
Volume_SwimmingPool = UnitStart + 125,
|
||||
Speed_Horse = UnitStart + 126,
|
||||
Area_Paper = UnitStart + 127,
|
||||
Area_Castle = UnitStart + 128,
|
||||
Energy_Banana = UnitStart + 129,
|
||||
Energy_SliceOfCake = UnitStart + 130,
|
||||
Length_Hand = UnitStart + 131,
|
||||
Power_TrainEngine = UnitStart + 132,
|
||||
Weight_SoccerBall = UnitStart + 133,
|
||||
Angle_Degree = UnitStart + 134,
|
||||
Angle_Radian = UnitStart + 135,
|
||||
Angle_Gradian = UnitStart + 136,
|
||||
Pressure_Atmosphere = UnitStart + 137,
|
||||
Pressure_Bar = UnitStart + 138,
|
||||
Pressure_KiloPascal = UnitStart + 139,
|
||||
Pressure_MillimeterOfMercury = UnitStart + 140,
|
||||
Pressure_Pascal = UnitStart + 141,
|
||||
Pressure_PSI = UnitStart + 142,
|
||||
Data_Exabits = UnitStart + 143,
|
||||
Data_Exabytes = UnitStart + 144,
|
||||
Data_Exbibits = UnitStart + 145,
|
||||
Data_Exbibytes = UnitStart + 146,
|
||||
Data_Gibibits = UnitStart + 147,
|
||||
Data_Gibibytes = UnitStart + 148,
|
||||
Data_Kibibits = UnitStart + 149,
|
||||
Data_Kibibytes = UnitStart + 150,
|
||||
Data_Mebibits = UnitStart + 151,
|
||||
Data_Mebibytes = UnitStart + 152,
|
||||
Data_Pebibits = UnitStart + 153,
|
||||
Data_Pebibytes = UnitStart + 154,
|
||||
Data_Tebibits = UnitStart + 155,
|
||||
Data_Tebibytes = UnitStart + 156,
|
||||
Data_Yobibits = UnitStart + 157,
|
||||
Data_Yobibytes = UnitStart + 158,
|
||||
Data_Yottabit = UnitStart + 159,
|
||||
Data_Yottabyte = UnitStart + 160,
|
||||
Data_Zebibits = UnitStart + 161,
|
||||
Data_Zebibytes = UnitStart + 162,
|
||||
Data_Zetabits = UnitStart + 163,
|
||||
Data_Zetabytes = UnitStart + 164,
|
||||
UnitEnd = Data_Zetabytes
|
||||
};
|
||||
}
|
||||
}
|
598
src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp
Normal file
598
src/CalcViewModel/DataLoaders/UnitConverterDataLoader.cpp
Normal file
@@ -0,0 +1,598 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Common\AppResourceProvider.h"
|
||||
#include "UnitConverterDataLoader.h"
|
||||
#include "UnitConverterDataConstants.h"
|
||||
#include "CurrencyDataLoader.h"
|
||||
|
||||
using namespace CalculatorApp::Common;
|
||||
using namespace CalculatorApp::DataLoaders;
|
||||
using namespace CalculatorApp::ViewModel;
|
||||
using namespace Platform;
|
||||
using namespace std;
|
||||
using namespace Windows::ApplicationModel::Resources;
|
||||
using namespace Windows::ApplicationModel::Resources::Core;
|
||||
using namespace Windows::Globalization;
|
||||
|
||||
static constexpr bool CONVERT_WITH_OFFSET_FIRST = true;
|
||||
|
||||
UnitConverterDataLoader::UnitConverterDataLoader(GeographicRegion^ region) :
|
||||
m_currentRegionCode(region->CodeTwoLetter)
|
||||
{
|
||||
m_categoryList = make_shared<vector<UCM::Category>>();
|
||||
m_categoryToUnits = make_shared<UCM::CategoryToUnitVectorMap>();
|
||||
m_ratioMap = make_shared<UCM::UnitToUnitToConversionDataMap>();
|
||||
}
|
||||
|
||||
vector<UCM::Category> UnitConverterDataLoader::LoadOrderedCategories()
|
||||
{
|
||||
return *m_categoryList;
|
||||
}
|
||||
|
||||
vector<UCM::Unit> UnitConverterDataLoader::LoadOrderedUnits(const UCM::Category& category)
|
||||
{
|
||||
return m_categoryToUnits->at(category);
|
||||
}
|
||||
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> UnitConverterDataLoader::LoadOrderedRatios(const UCM::Unit& unit)
|
||||
{
|
||||
return m_ratioMap->at(unit);
|
||||
}
|
||||
|
||||
bool UnitConverterDataLoader::SupportsCategory(const UCM::Category& target)
|
||||
{
|
||||
shared_ptr<vector<UCM::Category>> supportedCategories = nullptr;
|
||||
if (!m_categoryList->empty())
|
||||
{
|
||||
supportedCategories = m_categoryList;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCategories(supportedCategories);
|
||||
}
|
||||
|
||||
static int currencyId = NavCategory::Serialize(ViewMode::Currency);
|
||||
auto itr = find_if(supportedCategories->begin(), supportedCategories->end(),
|
||||
[&](const UCM::Category& category)
|
||||
{
|
||||
return currencyId != category.id && target.id == category.id;
|
||||
});
|
||||
|
||||
return itr != supportedCategories->end();
|
||||
}
|
||||
|
||||
void UnitConverterDataLoader::LoadData()
|
||||
{
|
||||
unordered_map<int, OrderedUnit> idToUnit;
|
||||
|
||||
unordered_map<ViewMode, vector<OrderedUnit>> orderedUnitMap{};
|
||||
unordered_map<ViewMode, unordered_map<int, double>> categoryToUnitConversionDataMap{};
|
||||
unordered_map<int, unordered_map<int, UCM::ConversionData>> explicitConversionData{};
|
||||
|
||||
// Load categories, units and conversion data into data structures. This will be then used to populate hashmaps used by CalcEngine and UI layer
|
||||
GetCategories(m_categoryList);
|
||||
GetUnits(orderedUnitMap);
|
||||
GetConversionData(categoryToUnitConversionDataMap);
|
||||
GetExplicitConversionData(explicitConversionData); // This is needed for temperature conversions
|
||||
|
||||
m_categoryToUnits->clear();
|
||||
m_ratioMap->clear();
|
||||
for (UCM::Category objectCategory : *m_categoryList)
|
||||
{
|
||||
ViewMode categoryViewMode = NavCategory::Deserialize(objectCategory.id);
|
||||
assert(NavCategory::IsConverterViewMode(categoryViewMode));
|
||||
if (categoryViewMode == ViewMode::Currency)
|
||||
{
|
||||
// Currency is an ordered category but we do not want to process it here
|
||||
// because this function is not thread-safe and currency data is asynchronously
|
||||
// loaded.
|
||||
m_categoryToUnits->insert(pair<UCM::Category, std::vector<UCM::Unit>>(objectCategory, {}));
|
||||
continue;
|
||||
}
|
||||
|
||||
vector<OrderedUnit> orderedUnits = orderedUnitMap[categoryViewMode];
|
||||
vector<UCM::Unit> unitList;
|
||||
|
||||
// Sort the units by order
|
||||
sort(orderedUnits.begin(), orderedUnits.end(), [](const OrderedUnit& first, const OrderedUnit& second){ return first.order < second.order; });
|
||||
|
||||
for (OrderedUnit u : orderedUnits)
|
||||
{
|
||||
unitList.push_back(static_cast<UCM::Unit>(u));
|
||||
idToUnit.insert(pair<int, OrderedUnit>(u.id, u));
|
||||
}
|
||||
|
||||
// Save units per category
|
||||
m_categoryToUnits->insert(pair<UCM::Category, std::vector<UCM::Unit>>(objectCategory, unitList));
|
||||
|
||||
// For each unit, populate the conversion data
|
||||
for (UCM::Unit unit : unitList)
|
||||
{
|
||||
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> conversions;
|
||||
|
||||
if (explicitConversionData.find(unit.id) == explicitConversionData.end())
|
||||
{
|
||||
// Get the associated units for a category id
|
||||
unordered_map<int, double> unitConversions = categoryToUnitConversionDataMap.at(categoryViewMode);
|
||||
double unitFactor = unitConversions[unit.id];
|
||||
|
||||
for (auto itr = unitConversions.begin(); itr != unitConversions.end(); ++itr)
|
||||
{
|
||||
UCM::ConversionData parsedData = { 1.0, 0.0, false };
|
||||
assert(itr->second > 0); // divide by zero assert
|
||||
parsedData.ratio = unitFactor / itr->second;
|
||||
conversions.insert(pair<UCM::Unit, UCM::ConversionData>(idToUnit.at(itr->first), parsedData));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unordered_map<int, UCM::ConversionData> unitConversions = explicitConversionData.at(unit.id);
|
||||
for (auto itr = unitConversions.begin(); itr != unitConversions.end(); ++itr)
|
||||
{
|
||||
conversions.insert(pair<UCM::Unit, UCM::ConversionData>(idToUnit.at(itr->first), itr->second));
|
||||
}
|
||||
}
|
||||
|
||||
m_ratioMap->insert(pair<UCM::Unit, unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash>>(unit, conversions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitConverterDataLoader::GetCategories(_In_ shared_ptr<vector<UCM::Category>> categoriesList)
|
||||
{
|
||||
categoriesList->clear();
|
||||
auto converterCategory = NavCategoryGroup::CreateConverterCategory();
|
||||
for (auto const& category : converterCategory->Categories)
|
||||
{
|
||||
/* Id, CategoryName, SupportsNegative */
|
||||
categoriesList->emplace_back(
|
||||
NavCategory::Serialize(category->Mode),
|
||||
category->Name->Data(),
|
||||
category->SupportsNegative);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitConverterDataLoader::GetUnits(_In_ unordered_map<ViewMode, vector<OrderedUnit>>& unitMap)
|
||||
{
|
||||
bool USSource, USTarget;
|
||||
bool UKSource, UKTarget;
|
||||
bool Source, Target;
|
||||
|
||||
USSource = (GetRegion() == L"US") ? true : false;
|
||||
USTarget = USSource;
|
||||
|
||||
UKSource = (GetRegion() == L"UK") ? true : false;
|
||||
UKTarget = UKSource;
|
||||
|
||||
Source = (GetRegion() == L"Others") ? true : false;
|
||||
Target = Source;
|
||||
|
||||
vector<OrderedUnit> areaUnits;
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_Acre, GetLocalizedStringName(L"UnitName_Acre"), GetLocalizedStringName(L"UnitAbbreviation_Acre"), 9 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_Hectare, GetLocalizedStringName(L"UnitName_Hectare"), GetLocalizedStringName(L"UnitAbbreviation_Hectare"), 4 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareCentimeter, GetLocalizedStringName(L"UnitName_SquareCentimeter"), GetLocalizedStringName(L"UnitAbbreviation_SquareCentimeter"), 2 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareFoot, GetLocalizedStringName(L"UnitName_SquareFoot"), GetLocalizedStringName(L"UnitAbbreviation_SquareFoot"), 7, (UKSource || Source), USTarget, false });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareInch, GetLocalizedStringName(L"UnitName_SquareInch"), GetLocalizedStringName(L"UnitAbbreviation_SquareInch"), 6 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareKilometer, GetLocalizedStringName(L"UnitName_SquareKilometer"), GetLocalizedStringName(L"UnitAbbreviation_SquareKilometer"), 5 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareMeter, GetLocalizedStringName(L"UnitName_SquareMeter"), GetLocalizedStringName(L"UnitAbbreviation_SquareMeter"), 3, USSource, (UKTarget || Target), false});
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareMile, GetLocalizedStringName(L"UnitName_SquareMile"), GetLocalizedStringName(L"UnitAbbreviation_SquareMile"), 10 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareMillimeter, GetLocalizedStringName(L"UnitName_SquareMillimeter"), GetLocalizedStringName(L"UnitAbbreviation_SquareMillimeter"), 1 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SquareYard, GetLocalizedStringName(L"UnitName_SquareYard"), GetLocalizedStringName(L"UnitAbbreviation_SquareYard"), 8 });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_Hand, GetLocalizedStringName(L"UnitName_Hand"), GetLocalizedStringName(L"UnitAbbreviation_Hand"), 11, false, false, true});
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_Paper, GetLocalizedStringName(L"UnitName_Paper"), GetLocalizedStringName(L"UnitAbbreviation_Paper"), 12, false, false, true });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_SoccerField, GetLocalizedStringName(L"UnitName_SoccerField"), GetLocalizedStringName(L"UnitAbbreviation_SoccerField"),13, false, false, true });
|
||||
areaUnits.push_back(OrderedUnit{ UnitConverterUnits::Area_Castle, GetLocalizedStringName(L"UnitName_Castle"), GetLocalizedStringName(L"UnitAbbreviation_Castle"), 14, false, false, true });
|
||||
unitMap.emplace(ViewMode::Area, areaUnits);
|
||||
|
||||
vector<OrderedUnit> dataUnits;
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Bit, GetLocalizedStringName(L"UnitName_Bit"), GetLocalizedStringName(L"UnitAbbreviation_Bit"), 1 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Byte, GetLocalizedStringName(L"UnitName_Byte"), GetLocalizedStringName(L"UnitAbbreviation_Byte"), 2 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exabits, GetLocalizedStringName(L"UnitName_Exabits"), GetLocalizedStringName(L"UnitAbbreviation_Exabits"), 23 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exabytes, GetLocalizedStringName(L"UnitName_Exabytes"), GetLocalizedStringName(L"UnitAbbreviation_Exabytes"), 25 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exbibits, GetLocalizedStringName(L"UnitName_Exbibits"), GetLocalizedStringName(L"UnitAbbreviation_Exbibits"), 24 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exbibytes, GetLocalizedStringName(L"UnitName_Exbibytes"), GetLocalizedStringName(L"UnitAbbreviation_Exbibytes"), 26 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gibibits, GetLocalizedStringName(L"UnitName_Gibibits"), GetLocalizedStringName(L"UnitAbbreviation_Gibibits"), 12 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gibibytes, GetLocalizedStringName(L"UnitName_Gibibytes"), GetLocalizedStringName(L"UnitAbbreviation_Gibibytes"), 14 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gigabit, GetLocalizedStringName(L"UnitName_Gigabit"), GetLocalizedStringName(L"UnitAbbreviation_Gigabit"), 11 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gigabyte, GetLocalizedStringName(L"UnitName_Gigabyte"), GetLocalizedStringName(L"UnitAbbreviation_Gigabyte"),13, true, false, false});
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Kibibits, GetLocalizedStringName(L"UnitName_Kibibits"), GetLocalizedStringName(L"UnitAbbreviation_Kibibits"), 4 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Kibibytes, GetLocalizedStringName(L"UnitName_Kibibytes"), GetLocalizedStringName(L"UnitAbbreviation_Kibibytes"),6 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Kilobit, GetLocalizedStringName(L"UnitName_Kilobit"), GetLocalizedStringName(L"UnitAbbreviation_Kilobit"), 3 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Kilobyte, GetLocalizedStringName(L"UnitName_Kilobyte"), GetLocalizedStringName(L"UnitAbbreviation_Kilobyte"), 5 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Mebibits, GetLocalizedStringName(L"UnitName_Mebibits"), GetLocalizedStringName(L"UnitAbbreviation_Mebibits"), 8 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Mebibytes, GetLocalizedStringName(L"UnitName_Mebibytes"), GetLocalizedStringName(L"UnitAbbreviation_Mebibytes"), 10 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Megabit, GetLocalizedStringName(L"UnitName_Megabit"), GetLocalizedStringName(L"UnitAbbreviation_Megabit"), 7 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Megabyte, GetLocalizedStringName(L"UnitName_Megabyte"), GetLocalizedStringName(L"UnitAbbreviation_Megabyte"), 9, false, true, false});
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Pebibits, GetLocalizedStringName(L"UnitName_Pebibits"), GetLocalizedStringName(L"UnitAbbreviation_Pebibits"), 20 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Pebibytes, GetLocalizedStringName(L"UnitName_Pebibytes"), GetLocalizedStringName(L"UnitAbbreviation_Pebibytes"), 22 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Petabit, GetLocalizedStringName(L"UnitName_Petabit"), GetLocalizedStringName(L"UnitAbbreviation_Petabit"), 19 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Petabyte, GetLocalizedStringName(L"UnitName_Petabyte"), GetLocalizedStringName(L"UnitAbbreviation_Petabyte"), 21 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Tebibits, GetLocalizedStringName(L"UnitName_Tebibits"), GetLocalizedStringName(L"UnitAbbreviation_Tebibits"), 16 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Tebibytes, GetLocalizedStringName(L"UnitName_Tebibytes"), GetLocalizedStringName(L"UnitAbbreviation_Tebibytes"), 18 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Terabit, GetLocalizedStringName(L"UnitName_Terabit"), GetLocalizedStringName(L"UnitAbbreviation_Terabit"), 15 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Terabyte, GetLocalizedStringName(L"UnitName_Terabyte"), GetLocalizedStringName(L"UnitAbbreviation_Terabyte"), 17 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Yobibits, GetLocalizedStringName(L"UnitName_Yobibits"), GetLocalizedStringName(L"UnitAbbreviation_Yobibits"), 32 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Yobibytes, GetLocalizedStringName(L"UnitName_Yobibytes"), GetLocalizedStringName(L"UnitAbbreviation_Yobibytes"), 34 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Yottabit, GetLocalizedStringName(L"UnitName_Yottabit"), GetLocalizedStringName(L"UnitAbbreviation_Yottabit"), 31 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Yottabyte, GetLocalizedStringName(L"UnitName_Yottabyte"), GetLocalizedStringName(L"UnitAbbreviation_Yottabyte"), 33 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Zebibits, GetLocalizedStringName(L"UnitName_Zebibits"), GetLocalizedStringName(L"UnitAbbreviation_Zebibits"), 28 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Zebibytes, GetLocalizedStringName(L"UnitName_Zebibytes"), GetLocalizedStringName(L"UnitAbbreviation_Zebibytes"), 30 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Zetabits, GetLocalizedStringName(L"UnitName_Zetabits"), GetLocalizedStringName(L"UnitAbbreviation_Zetabits"), 27 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Zetabytes, GetLocalizedStringName(L"UnitName_Zetabytes"), GetLocalizedStringName(L"UnitAbbreviation_Zetabytes"),29 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_FloppyDisk, GetLocalizedStringName(L"UnitName_FloppyDisk"), GetLocalizedStringName(L"UnitAbbreviation_FloppyDisk"), 13, false, false, true });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_CD, GetLocalizedStringName(L"UnitName_CD"), GetLocalizedStringName(L"UnitAbbreviation_CD"), 14, false, false, true });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_DVD, GetLocalizedStringName(L"UnitName_DVD"), GetLocalizedStringName(L"UnitAbbreviation_DVD"), 15, false, false, true });
|
||||
unitMap.emplace(ViewMode::Data, dataUnits);
|
||||
|
||||
vector<OrderedUnit> energyUnits;
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_BritishThermalUnit, GetLocalizedStringName(L"UnitName_BritishThermalUnit"), GetLocalizedStringName(L"UnitAbbreviation_BritishThermalUnit"), 7 });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Calorie, GetLocalizedStringName(L"UnitName_Calorie"), GetLocalizedStringName(L"UnitAbbreviation_Calorie"), 4 });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_ElectronVolt, GetLocalizedStringName(L"UnitName_Electron-Volt"), GetLocalizedStringName(L"UnitAbbreviation_Electron-Volt"), 1 });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_FootPound, GetLocalizedStringName(L"UnitName_Foot-Pound"), GetLocalizedStringName(L"UnitAbbreviation_Foot-Pound"), 6 });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Joule, GetLocalizedStringName(L"UnitName_Joule"), GetLocalizedStringName(L"UnitAbbreviation_Joule"), 2, true, false, false});
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Kilocalorie, GetLocalizedStringName(L"UnitName_Kilocalorie"), GetLocalizedStringName(L"UnitAbbreviation_Kilocalorie"), 5, false, true, false });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Kilojoule, GetLocalizedStringName(L"UnitName_Kilojoule"), GetLocalizedStringName(L"UnitAbbreviation_Kilojoule"), 3 });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Battery, GetLocalizedStringName(L"UnitName_Battery"), GetLocalizedStringName(L"UnitAbbreviation_Battery"), 8, false, false, true });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_Banana, GetLocalizedStringName(L"UnitName_Banana"), GetLocalizedStringName(L"UnitAbbreviation_Banana"), 9, false, false, true });
|
||||
energyUnits.push_back(OrderedUnit{ UnitConverterUnits::Energy_SliceOfCake, GetLocalizedStringName(L"UnitName_SliceOfCake"), GetLocalizedStringName(L"UnitAbbreviation_SliceOfCake"),10, false, false, true });
|
||||
unitMap.emplace(ViewMode::Energy, energyUnits);
|
||||
|
||||
vector<OrderedUnit> lengthUnits;
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Centimeter, GetLocalizedStringName(L"UnitName_Centimeter"), GetLocalizedStringName(L"UnitAbbreviation_Centimeter"), 4 , USSource, (Target || UKTarget), false});
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Foot, GetLocalizedStringName(L"UnitName_Foot"), GetLocalizedStringName(L"UnitAbbreviation_Foot"), 8 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Inch, GetLocalizedStringName(L"UnitName_Inch"), GetLocalizedStringName(L"UnitAbbreviation_Inch"), 7 , (Source|| UKSource), USTarget, false });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Kilometer, GetLocalizedStringName(L"UnitName_Kilometer"), GetLocalizedStringName(L"UnitAbbreviation_Kilometer"), 6 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Meter, GetLocalizedStringName(L"UnitName_Meter"), GetLocalizedStringName(L"UnitAbbreviation_Meter"), 5 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Micron, GetLocalizedStringName(L"UnitName_Micron"), GetLocalizedStringName(L"UnitAbbreviation_Micron"), 2 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Mile, GetLocalizedStringName(L"UnitName_Mile"), GetLocalizedStringName(L"UnitAbbreviation_Mile"), 10 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Millimeter, GetLocalizedStringName(L"UnitName_Millimeter"), GetLocalizedStringName(L"UnitAbbreviation_Millimeter"), 3 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Nanometer, GetLocalizedStringName(L"UnitName_Nanometer"), GetLocalizedStringName(L"UnitAbbreviation_Nanometer"), 1 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_NauticalMile, GetLocalizedStringName(L"UnitName_NauticalMile"), GetLocalizedStringName(L"UnitAbbreviation_NauticalMile"), 11 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Yard, GetLocalizedStringName(L"UnitName_Yard"), GetLocalizedStringName(L"UnitAbbreviation_Yard"), 9 });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Paperclip, GetLocalizedStringName(L"UnitName_Paperclip"), GetLocalizedStringName(L"UnitAbbreviation_Paperclip"), 12 ,false, false, true });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_Hand, GetLocalizedStringName(L"UnitName_Hand"), GetLocalizedStringName(L"UnitAbbreviation_Hand"), 13 ,false, false, true });
|
||||
lengthUnits.push_back(OrderedUnit{ UnitConverterUnits::Length_JumboJet, GetLocalizedStringName(L"UnitName_JumboJet"), GetLocalizedStringName(L"UnitAbbreviation_JumboJet"), 14 , false, false, true });
|
||||
unitMap.emplace(ViewMode::Length, lengthUnits);
|
||||
|
||||
vector<OrderedUnit> powerUnits;
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_BritishThermalUnitPerMinute, GetLocalizedStringName(L"UnitName_BTUPerMinute"), GetLocalizedStringName(L"UnitAbbreviation_BTUPerMinute"), 5 });
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_FootPoundPerMinute, GetLocalizedStringName(L"UnitName_Foot-PoundPerMinute"), GetLocalizedStringName(L"UnitAbbreviation_Foot-PoundPerMinute"), 4 });
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_Horsepower, GetLocalizedStringName(L"UnitName_Horsepower"), GetLocalizedStringName(L"UnitAbbreviation_Horsepower") , 3 , false, true, false });
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_Kilowatt, GetLocalizedStringName(L"UnitName_Kilowatt"), GetLocalizedStringName(L"UnitAbbreviation_Kilowatt"), 2 , (Source|| USSource), false, false});
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_Watt, GetLocalizedStringName(L"UnitName_Watt"), GetLocalizedStringName(L"UnitAbbreviation_Watt"), 1, UKSource });
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_LightBulb, GetLocalizedStringName(L"UnitName_LightBulb"), GetLocalizedStringName(L"UnitAbbreviation_LightBulb"), 6 ,false, false, true});
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_Horse, GetLocalizedStringName(L"UnitName_Horse"), GetLocalizedStringName(L"UnitAbbreviation_Horse"), 7 ,false, false, true});
|
||||
powerUnits.push_back(OrderedUnit{ UnitConverterUnits::Power_TrainEngine, GetLocalizedStringName(L"UnitName_TrainEngine"), GetLocalizedStringName(L"UnitAbbreviation_TrainEngine"), 8 ,false, false, true });
|
||||
unitMap.emplace(ViewMode::Power, powerUnits);
|
||||
|
||||
vector<OrderedUnit> tempUnits;
|
||||
tempUnits.push_back(OrderedUnit{ UnitConverterUnits::Temperature_DegreesCelsius, GetLocalizedStringName(L"UnitName_DegreesCelsius"), GetLocalizedStringName(L"UnitAbbreviation_DegreesCelsius"), 1, USSource, (Target || UKTarget), false });
|
||||
tempUnits.push_back(OrderedUnit{ UnitConverterUnits::Temperature_DegreesFahrenheit, GetLocalizedStringName(L"UnitName_DegreesFahrenheit"), GetLocalizedStringName(L"UnitAbbreviation_DegreesFahrenheit"), 2 , (Source || UKSource), USTarget, false });
|
||||
tempUnits.push_back(OrderedUnit{ UnitConverterUnits::Temperature_Kelvin, GetLocalizedStringName(L"UnitName_Kelvin"), GetLocalizedStringName(L"UnitAbbreviation_Kelvin"), 3 });
|
||||
unitMap.emplace(ViewMode::Temperature, tempUnits);
|
||||
|
||||
vector<OrderedUnit> timeUnits;
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Day, GetLocalizedStringName(L"UnitName_Day"), GetLocalizedStringName(L"UnitAbbreviation_Day"), 6 });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Hour, GetLocalizedStringName(L"UnitName_Hour"), GetLocalizedStringName(L"UnitAbbreviation_Hour"), 5 ,true, false, false });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Microsecond, GetLocalizedStringName(L"UnitName_Microsecond"), GetLocalizedStringName(L"UnitAbbreviation_Microsecond"), 1 });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Millisecond, GetLocalizedStringName(L"UnitName_Millisecond"), GetLocalizedStringName(L"UnitAbbreviation_Millisecond"), 2 });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Minute, GetLocalizedStringName(L"UnitName_Minute"), GetLocalizedStringName(L"UnitAbbreviation_Minute"), 4 ,false, true, false });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Second, GetLocalizedStringName(L"UnitName_Second"), GetLocalizedStringName(L"UnitAbbreviation_Second"), 3 });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Week, GetLocalizedStringName(L"UnitName_Week"), GetLocalizedStringName(L"UnitAbbreviation_Week"), 7 });
|
||||
timeUnits.push_back(OrderedUnit{ UnitConverterUnits::Time_Year, GetLocalizedStringName(L"UnitName_Year"), GetLocalizedStringName(L"UnitAbbreviation_Year"), 8 });
|
||||
unitMap.emplace(ViewMode::Time, timeUnits);
|
||||
|
||||
vector<OrderedUnit> speedUnits;
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_CentimetersPerSecond, GetLocalizedStringName(L"UnitName_CentimetersPerSecond"), GetLocalizedStringName(L"UnitAbbreviation_CentimetersPerSecond"), 1 });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_FeetPerSecond, GetLocalizedStringName(L"UnitName_FeetPerSecond"), GetLocalizedStringName(L"UnitAbbreviation_FeetPerSecond"), 4 });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_KilometersPerHour, GetLocalizedStringName(L"UnitName_KilometersPerHour"), GetLocalizedStringName(L"UnitAbbreviation_KilometersPerHour"), 3 ,(USSource || UKSource), Target, false });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_Knot, GetLocalizedStringName(L"UnitName_Knot"), GetLocalizedStringName(L"UnitAbbreviation_Knot"), 6 });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_Mach, GetLocalizedStringName(L"UnitName_Mach"), GetLocalizedStringName(L"UnitAbbreviation_Mach"), 7 });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_MetersPerSecond, GetLocalizedStringName(L"UnitName_MetersPerSecond"), GetLocalizedStringName(L"UnitAbbreviation_MetersPerSecond"), 2 });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_MilesPerHour, GetLocalizedStringName(L"UnitName_MilesPerHour"), GetLocalizedStringName(L"UnitAbbreviation_MilesPerHour"), 5, Source, (UKTarget || USTarget), false });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_Turtle, GetLocalizedStringName(L"UnitName_Turtle"), GetLocalizedStringName(L"UnitAbbreviation_Turtle"), 8 ,false, false, true });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_Horse, GetLocalizedStringName(L"UnitName_Horse"), GetLocalizedStringName(L"UnitAbbreviation_Horse"),9 , false, false, true });
|
||||
speedUnits.push_back(OrderedUnit{ UnitConverterUnits::Speed_Jet, GetLocalizedStringName(L"UnitName_Jet"), GetLocalizedStringName(L"UnitAbbreviation_Jet"), 10, false, false, true });
|
||||
unitMap.emplace(ViewMode::Speed, speedUnits);
|
||||
|
||||
vector<OrderedUnit> volumeUnits;
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CubicCentimeter, GetLocalizedStringName(L"UnitName_CubicCentimeter"), GetLocalizedStringName(L"UnitAbbreviation_CubicCentimeter"), 2 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CubicFoot, GetLocalizedStringName(L"UnitName_CubicFoot"), GetLocalizedStringName(L"UnitAbbreviation_CubicFoot"), 13 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CubicInch, GetLocalizedStringName(L"UnitName_CubicInch"), GetLocalizedStringName(L"UnitAbbreviation_CubicInch"), 12 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CubicMeter, GetLocalizedStringName(L"UnitName_CubicMeter"), GetLocalizedStringName(L"UnitAbbreviation_CubicMeter"), 4 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CubicYard, GetLocalizedStringName(L"UnitName_CubicYard"), GetLocalizedStringName(L"UnitAbbreviation_CubicYard"), 14 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CupUS, GetLocalizedStringName(L"UnitName_CupUS"), GetLocalizedStringName(L"UnitAbbreviation_CupUS"), 8 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_FluidOunceUK, GetLocalizedStringName(L"UnitName_FluidOunceUK"), GetLocalizedStringName(L"UnitAbbreviation_FluidOunceUK"), 17 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_FluidOunceUS, GetLocalizedStringName(L"UnitName_FluidOunceUS"), GetLocalizedStringName(L"UnitAbbreviation_FluidOunceUS"), 7 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_GallonUK, GetLocalizedStringName(L"UnitName_GallonUK"), GetLocalizedStringName(L"UnitAbbreviation_GallonUK"), 20 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_GallonUS, GetLocalizedStringName(L"UnitName_GallonUS"), GetLocalizedStringName(L"UnitAbbreviation_GallonUS"), 11 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_Liter, GetLocalizedStringName(L"UnitName_Liter"), GetLocalizedStringName(L"UnitAbbreviation_Liter"), 3 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_Milliliter, GetLocalizedStringName(L"UnitName_Milliliter"), GetLocalizedStringName(L"UnitAbbreviation_Milliliter"), 1 , USSource, (Target || UKTarget), false});
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_PintUK, GetLocalizedStringName(L"UnitName_PintUK"), GetLocalizedStringName(L"UnitAbbreviation_PintUK"), 18 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_PintUS, GetLocalizedStringName(L"UnitName_PintUS"), GetLocalizedStringName(L"UnitAbbreviation_PintUS"), 9 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_TablespoonUS, GetLocalizedStringName(L"UnitName_TablespoonUS"), GetLocalizedStringName(L"UnitAbbreviation_TablespoonUS"), 6 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_TeaspoonUS, GetLocalizedStringName(L"UnitName_TeaspoonUS"), GetLocalizedStringName(L"UnitAbbreviation_TeaspoonUS"), 5 ,Source, USTarget, false });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_QuartUK, GetLocalizedStringName(L"UnitName_QuartUK"), GetLocalizedStringName(L"UnitAbbreviation_QuartUK"), 19 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_QuartUS, GetLocalizedStringName(L"UnitName_QuartUS"), GetLocalizedStringName(L"UnitAbbreviation_QuartUS"), 10 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_TeaspoonUK, GetLocalizedStringName(L"UnitName_TeaspoonUK"), GetLocalizedStringName(L"UnitAbbreviation_TeaspoonUK"), 15, UKSource });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_TablespoonUK, GetLocalizedStringName(L"UnitName_TablespoonUK"), GetLocalizedStringName(L"UnitAbbreviation_TablespoonUK"), 16 });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_CoffeeCup, GetLocalizedStringName(L"UnitName_CoffeeCup"), GetLocalizedStringName(L"UnitAbbreviation_CoffeeCup"), 22 ,false, false, true });
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_Bathtub, GetLocalizedStringName(L"UnitName_Bathtub"), GetLocalizedStringName(L"UnitAbbreviation_Bathtub"), 23 ,false, false, true});
|
||||
volumeUnits.push_back(OrderedUnit{ UnitConverterUnits::Volume_SwimmingPool, GetLocalizedStringName(L"UnitName_SwimmingPool"), GetLocalizedStringName(L"UnitAbbreviation_SwimmingPool"), 24 ,false, false, true });
|
||||
unitMap.emplace(ViewMode::Volume, volumeUnits);
|
||||
|
||||
vector<OrderedUnit> weightUnits;
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Carat, GetLocalizedStringName(L"UnitName_Carat"), GetLocalizedStringName(L"UnitAbbreviation_Carat"), 1 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Centigram, GetLocalizedStringName(L"UnitName_Centigram"), GetLocalizedStringName(L"UnitAbbreviation_Centigram"), 3 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Decigram, GetLocalizedStringName(L"UnitName_Decigram"), GetLocalizedStringName(L"UnitAbbreviation_Decigram"), 4 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Decagram, GetLocalizedStringName(L"UnitName_Decagram"), GetLocalizedStringName(L"UnitAbbreviation_Decagram"), 6 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Gram, GetLocalizedStringName(L"UnitName_Gram"), GetLocalizedStringName(L"UnitAbbreviation_Gram"), 5 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Hectogram, GetLocalizedStringName(L"UnitName_Hectogram"), GetLocalizedStringName(L"UnitAbbreviation_Hectogram"), 7 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Kilogram, GetLocalizedStringName(L"UnitName_Kilogram"), GetLocalizedStringName(L"UnitAbbreviation_Kilogram"), 8 ,(USSource || UKSource), Target, false});
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_LongTon, GetLocalizedStringName(L"UnitName_LongTon"), GetLocalizedStringName(L"UnitAbbreviation_LongTon"), 14 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Milligram, GetLocalizedStringName(L"UnitName_Milligram"), GetLocalizedStringName(L"UnitAbbreviation_Milligram"), 2 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Ounce, GetLocalizedStringName(L"UnitName_Ounce"), GetLocalizedStringName(L"UnitAbbreviation_Ounce"), 10 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Pound, GetLocalizedStringName(L"UnitName_Pound"), GetLocalizedStringName(L"UnitAbbreviation_Pound"), 11 , Source, (USTarget ||UKTarget), false });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_ShortTon, GetLocalizedStringName(L"UnitName_ShortTon"), GetLocalizedStringName(L"UnitAbbreviation_ShortTon"), 13 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Stone, GetLocalizedStringName(L"UnitName_Stone"), GetLocalizedStringName(L"UnitAbbreviation_Stone"), 12 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Tonne, GetLocalizedStringName(L"UnitName_Tonne"), GetLocalizedStringName(L"UnitAbbreviation_Tonne"), 9 });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Snowflake, GetLocalizedStringName(L"UnitName_Snowflake"), GetLocalizedStringName(L"UnitAbbreviation_Snowflake"), 15 ,false, false, true });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_SoccerBall, GetLocalizedStringName(L"UnitName_SoccerBall"), GetLocalizedStringName(L"UnitAbbreviation_SoccerBall"), 16 , false, false, true });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Elephant, GetLocalizedStringName(L"UnitName_Elephant"), GetLocalizedStringName(L"UnitAbbreviation_Elephant"), 17 ,false, false, true });
|
||||
weightUnits.push_back(OrderedUnit{ UnitConverterUnits::Weight_Whale, GetLocalizedStringName(L"UnitName_Whale"), GetLocalizedStringName(L"UnitAbbreviation_Whale"), 18 ,false, false, true });
|
||||
unitMap.emplace(ViewMode::Weight, weightUnits);
|
||||
|
||||
vector<OrderedUnit> pressureUnits;
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_Atmosphere, GetLocalizedStringName(L"UnitName_Atmosphere"), GetLocalizedStringName(L"UnitAbbreviation_Atmosphere"), 1 , true, false, false });
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_Bar, GetLocalizedStringName(L"UnitName_Bar"), GetLocalizedStringName(L"UnitAbbreviation_Bar"), 2, false, true, false});
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_KiloPascal, GetLocalizedStringName(L"UnitName_KiloPascal"), GetLocalizedStringName(L"UnitAbbreviation_KiloPascal"), 3 });
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_MillimeterOfMercury, GetLocalizedStringName(L"UnitName_MillimeterOfMercury "), GetLocalizedStringName(L"UnitAbbreviation_MillimeterOfMercury "), 4 });
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_Pascal, GetLocalizedStringName(L"UnitName_Pascal"), GetLocalizedStringName(L"UnitAbbreviation_Pascal"), 5 });
|
||||
pressureUnits.push_back(OrderedUnit{ UnitConverterUnits::Pressure_PSI, GetLocalizedStringName(L"UnitName_PSI"), GetLocalizedStringName(L"UnitAbbreviation_PSI"), 6, false, false, false });
|
||||
unitMap.emplace(ViewMode::Pressure, pressureUnits);
|
||||
|
||||
vector<OrderedUnit> angleUnits;
|
||||
angleUnits.push_back(OrderedUnit{ UnitConverterUnits::Angle_Degree, GetLocalizedStringName(L"UnitName_Degree"), GetLocalizedStringName(L"UnitAbbreviation_Degree"), 1, true, false, false });
|
||||
angleUnits.push_back(OrderedUnit{ UnitConverterUnits::Angle_Radian, GetLocalizedStringName(L"UnitName_Radian"), GetLocalizedStringName(L"UnitAbbreviation_Radian"), 2, false, true, false });
|
||||
angleUnits.push_back(OrderedUnit{ UnitConverterUnits::Angle_Gradian, GetLocalizedStringName(L"UnitName_Gradian"), GetLocalizedStringName(L"UnitAbbreviation_Gradian"), 3});
|
||||
unitMap.emplace(ViewMode::Angle, angleUnits);
|
||||
}
|
||||
|
||||
void UnitConverterDataLoader::GetConversionData(_In_ unordered_map<ViewMode, unordered_map<int, double>>& categoryToUnitConversionMap)
|
||||
{
|
||||
/*categoryId, UnitId, factor*/
|
||||
static const vector<UnitData> unitDataList = {
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_Acre, 4046.8564224 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareMeter, 1 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareFoot, 0.09290304 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareYard, 0.83612736 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareMillimeter, 0.000001 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareCentimeter, 0.0001 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareInch, 0.00064516 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareMile, 2589988.110336 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SquareKilometer, 1000000 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_Hectare, 10000 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_Hand, 0.012516104 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_Paper, 0.06032246 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_SoccerField, 10869.66 },
|
||||
{ ViewMode::Area, UnitConverterUnits::Area_Castle, 100000 },
|
||||
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Bit, 0.000000125 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Byte, 0.000001 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Kilobyte, 0.001 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Megabyte, 1 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Gigabyte, 1000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Terabyte, 1000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Petabyte, 1000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Exabytes, 1000000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Zetabytes, 1000000000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Yottabyte, 1000000000000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Kilobit, 0.000125 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Megabit, 0.125 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Gigabit, 125 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Terabit, 125000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Petabit, 125000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Exabits, 125000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Zetabits, 125000000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Yottabit, 125000000000000000 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Gibibits, 134.217728 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Gibibytes, 1073.741824 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Kibibits, 0.000128 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Kibibytes, 0.001024 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Mebibits, 0.131072 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Mebibytes, 1.048576 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Pebibits, 140737488.355328 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Pebibytes, 1125899906.842624 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Tebibits, 137438.953472 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Tebibytes, 1099511.627776 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Exbibits, 144115188075.855872 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Exbibytes, 1152921504606.846976 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Zebibits, 147573952589676.412928 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Zebibytes, 1180591620717411.303424 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Yobibits, 151115727451828646.838272 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_Yobibytes, 1208925819614629174.706176 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_FloppyDisk, 1.509949 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_CD, 734.003200 },
|
||||
{ ViewMode::Data, UnitConverterUnits::Data_DVD, 5046.586573 },
|
||||
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Calorie, 4.184 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Kilocalorie, 4184},
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_BritishThermalUnit, 1055.056 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Kilojoule, 1000 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_ElectronVolt, 0.0000000000000000001602176565 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Joule, 1 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_FootPound, 1.3558179483314 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Battery, 9000 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_Banana, 439614 },
|
||||
{ ViewMode::Energy, UnitConverterUnits::Energy_SliceOfCake, 1046700 },
|
||||
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Inch, 0.0254 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Foot, 0.3048 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Yard, 0.9144 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Mile, 1609.344 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Micron, 0.000001 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Millimeter, 0.001 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Nanometer, 0.000000001 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Centimeter, 0.01 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Meter, 1 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Kilometer, 1000 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_NauticalMile, 1852 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Paperclip, 0.035052 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_Hand, 0.18669 },
|
||||
{ ViewMode::Length, UnitConverterUnits::Length_JumboJet, 76 },
|
||||
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_BritishThermalUnitPerMinute, 17.58426666666667 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_FootPoundPerMinute, 0.0225969658055233 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_Watt, 1 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_Kilowatt, 1000 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_Horsepower, 745.69987158227022 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_LightBulb, 60 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_Horse, 745.7 },
|
||||
{ ViewMode::Power, UnitConverterUnits::Power_TrainEngine, 2982799.486329081 },
|
||||
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Day, 86400 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Second, 1 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Week, 604800 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Year, 31557600 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Millisecond, 0.001 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Microsecond, 0.000001 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Minute, 60 },
|
||||
{ ViewMode::Time, UnitConverterUnits::Time_Hour, 3600 },
|
||||
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CupUS, 236.588237 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_PintUS, 473.176473 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_PintUK, 568.26125 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_QuartUS, 946.352946 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_QuartUK, 1136.5225 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_GallonUS, 3785.411784 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_GallonUK, 4546.09 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_Liter, 1000 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_TeaspoonUS, 4.928922 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_TablespoonUS, 14.786765 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CubicCentimeter, 1 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CubicYard, 764554.857984 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CubicMeter, 1000000 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_Milliliter, 1 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CubicInch, 16.387064 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CubicFoot, 28316.846592 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_FluidOunceUS, 29.5735295625 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_FluidOunceUK, 28.4130625 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_TeaspoonUK, 5.91938802083333333333 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_TablespoonUK, 17.7581640625 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_CoffeeCup, 236.5882 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_Bathtub, 378541.2 },
|
||||
{ ViewMode::Volume, UnitConverterUnits::Volume_SwimmingPool, 3750000000 },
|
||||
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Kilogram, 1 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Hectogram, 0.1 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Decagram, 0.01 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Gram, 0.001 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Pound, 0.45359237 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Ounce, 0.028349523125 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Milligram, 0.000001 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Centigram, 0.00001 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Decigram, 0.0001 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_LongTon, 1016.0469088 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Tonne, 1000 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Stone, 6.35029318 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Carat, 0.0002 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_ShortTon, 907.18474 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Snowflake, 0.000002 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_SoccerBall, 0.4325 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Elephant, 4000 },
|
||||
{ ViewMode::Weight, UnitConverterUnits::Weight_Whale, 90000 },
|
||||
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_CentimetersPerSecond, 1 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_FeetPerSecond, 30.48 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_KilometersPerHour, 27.777777777777777777778 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_Knot, 51.44 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_Mach, 34030 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_MetersPerSecond, 100 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_MilesPerHour, 44.7 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_Turtle, 8.94 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_Horse, 2011.5 },
|
||||
{ ViewMode::Speed, UnitConverterUnits::Speed_Jet, 24585 },
|
||||
|
||||
{ ViewMode::Angle, UnitConverterUnits::Angle_Degree, 1 },
|
||||
{ ViewMode::Angle, UnitConverterUnits::Angle_Radian, 57.29577951308233 },
|
||||
{ ViewMode::Angle, UnitConverterUnits::Angle_Gradian, 0.9 },
|
||||
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_Atmosphere, 1 },
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_Bar, 0.9869232667160128 },
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_KiloPascal, 0.0098692326671601 },
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_MillimeterOfMercury, 0.0013155687145324 },
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_Pascal, 9.869232667160128e-6 },
|
||||
{ ViewMode::Pressure, UnitConverterUnits::Pressure_PSI, 0.068045961016531 }
|
||||
};
|
||||
|
||||
// Populate the hash map and return;
|
||||
for (UnitData unitdata : unitDataList)
|
||||
{
|
||||
if (categoryToUnitConversionMap.find(unitdata.categoryId) == categoryToUnitConversionMap.end())
|
||||
{
|
||||
unordered_map<int, double> conversionData;
|
||||
conversionData.insert(pair<int, double>(unitdata.unitId, unitdata.factor));
|
||||
categoryToUnitConversionMap.insert(pair<ViewMode, unordered_map<int, double>>(unitdata.categoryId, conversionData));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryToUnitConversionMap.at(unitdata.categoryId).insert(pair<int, double>(unitdata.unitId, unitdata.factor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wstring UnitConverterDataLoader::GetLocalizedStringName(String^ stringId)
|
||||
{
|
||||
return AppResourceProvider::GetInstance().GetResourceString(stringId)->Data();
|
||||
}
|
||||
|
||||
wstring UnitConverterDataLoader::GetRegion()
|
||||
{
|
||||
if ((m_currentRegionCode == L"US") ||
|
||||
(m_currentRegionCode == L"LR") ||
|
||||
(m_currentRegionCode == L"MM"))
|
||||
{
|
||||
return L"US";
|
||||
}
|
||||
else if (m_currentRegionCode == L"GB")
|
||||
{
|
||||
return L"UK";
|
||||
}
|
||||
else
|
||||
{
|
||||
return L"Others";
|
||||
}
|
||||
}
|
||||
|
||||
void UnitConverterDataLoader::GetExplicitConversionData(_In_ unordered_map<int, unordered_map<int, UCM::ConversionData>>& unitToUnitConversionList)
|
||||
{
|
||||
/* categoryId, ParentUnitId, UnitId, ratio, offset, offsetfirst*/
|
||||
ExplicitUnitConversionData conversionDataList[] = {
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesCelsius, UnitConverterUnits::Temperature_DegreesCelsius , 1, 0 },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesCelsius, UnitConverterUnits::Temperature_DegreesFahrenheit, 1.8, 32 },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesCelsius, UnitConverterUnits::Temperature_Kelvin, 1, 273.15 },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesFahrenheit, UnitConverterUnits::Temperature_DegreesCelsius, 0.55555555555555555555555555555556, -32, CONVERT_WITH_OFFSET_FIRST },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesFahrenheit, UnitConverterUnits::Temperature_DegreesFahrenheit, 1, 0 },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_DegreesFahrenheit, UnitConverterUnits::Temperature_Kelvin, 0.55555555555555555555555555555556, 459.67, CONVERT_WITH_OFFSET_FIRST },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_Kelvin, UnitConverterUnits::Temperature_DegreesCelsius, 1, -273.15, CONVERT_WITH_OFFSET_FIRST },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_Kelvin, UnitConverterUnits::Temperature_DegreesFahrenheit, 1.8, -459.67 },
|
||||
{ ViewMode::Temperature, UnitConverterUnits::Temperature_Kelvin, UnitConverterUnits::Temperature_Kelvin, 1, 0 }
|
||||
};
|
||||
|
||||
// Populate the hash map and return;
|
||||
for (ExplicitUnitConversionData data : conversionDataList)
|
||||
{
|
||||
if (unitToUnitConversionList.find(data.parentUnitId) == unitToUnitConversionList.end())
|
||||
{
|
||||
unordered_map<int, UCM::ConversionData> conversionData;
|
||||
conversionData.insert(pair<int, UCM::ConversionData>(data.unitId, static_cast<UCM::ConversionData>(data)));
|
||||
unitToUnitConversionList.insert(pair<int, unordered_map<int, UCM::ConversionData>>(data.parentUnitId, conversionData));
|
||||
}
|
||||
else
|
||||
{
|
||||
unitToUnitConversionList.at(data.parentUnitId).insert(pair<int, UCM::ConversionData>(data.unitId, static_cast<UCM::ConversionData>(data)));
|
||||
}
|
||||
}
|
||||
}
|
72
src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h
Normal file
72
src/CalcViewModel/DataLoaders/UnitConverterDataLoader.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
struct OrderedUnit : UnitConversionManager::Unit
|
||||
{
|
||||
OrderedUnit(){}
|
||||
|
||||
OrderedUnit(int id, std::wstring name, std::wstring abbreviation, int order, bool isConversionSource = false, bool isConversionTarget = false, bool isWhimsical = false)
|
||||
: UnitConversionManager::Unit(id, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical), order(order)
|
||||
{
|
||||
}
|
||||
|
||||
int order;
|
||||
};
|
||||
|
||||
struct UnitData
|
||||
{
|
||||
CalculatorApp::Common::ViewMode categoryId;
|
||||
int unitId;
|
||||
double factor;
|
||||
};
|
||||
|
||||
struct ExplicitUnitConversionData : UnitConversionManager::ConversionData
|
||||
{
|
||||
ExplicitUnitConversionData(){}
|
||||
ExplicitUnitConversionData(CalculatorApp::Common::ViewMode categoryId, int parentUnitId, int unitId, double ratio, double offset, bool offsetFirst = false) :
|
||||
categoryId(categoryId), parentUnitId(parentUnitId), unitId(unitId), UnitConversionManager::ConversionData(ratio, offset, offsetFirst)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CalculatorApp::Common::ViewMode categoryId;
|
||||
int parentUnitId;
|
||||
int unitId;
|
||||
};
|
||||
|
||||
class UnitConverterDataLoader : public UnitConversionManager::IConverterDataLoader,
|
||||
public std::enable_shared_from_this<UnitConverterDataLoader>
|
||||
{
|
||||
public:
|
||||
UnitConverterDataLoader(Windows::Globalization::GeographicRegion^ region);
|
||||
|
||||
private:
|
||||
// IConverterDataLoader
|
||||
void LoadData() override;
|
||||
std::vector<UnitConversionManager::Category> LoadOrderedCategories() override;
|
||||
std::vector<UnitConversionManager::Unit> LoadOrderedUnits(const UnitConversionManager::Category& c) override;
|
||||
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash> LoadOrderedRatios(const UnitConversionManager::Unit& unit) override;
|
||||
bool SupportsCategory(const UnitConversionManager::Category& target) override;
|
||||
// IConverterDataLoader
|
||||
|
||||
void GetCategories(_In_ std::shared_ptr<std::vector<UnitConversionManager::Category>> categoriesList);
|
||||
void GetUnits(_In_ std::unordered_map<CalculatorApp::Common::ViewMode, std::vector<CalculatorApp::ViewModel::OrderedUnit>>& unitMap);
|
||||
void GetConversionData(_In_ std::unordered_map<CalculatorApp::Common::ViewMode, std::unordered_map<int, double>>& categoryToUnitConversionMap);
|
||||
void GetExplicitConversionData(_In_ std::unordered_map<int, std::unordered_map<int, UnitConversionManager::ConversionData>>& unitToUnitConversionList);
|
||||
|
||||
std::wstring GetLocalizedStringName(_In_ Platform::String^ stringId);
|
||||
std::wstring GetRegion();
|
||||
|
||||
std::shared_ptr<std::vector<UnitConversionManager::Category>> m_categoryList;
|
||||
std::shared_ptr<UnitConversionManager::CategoryToUnitVectorMap> m_categoryToUnits;
|
||||
std::shared_ptr<UnitConversionManager::UnitToUnitToConversionDataMap> m_ratioMap;
|
||||
Platform::String^ m_currentRegionCode;
|
||||
};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user