Refactor Equation to be treated as a model and update Key Graph Features (#791)

* refactor code

* update KGF

* Rename some functions

* Undo comment out of proj file

* Pr feedback
This commit is contained in:
Pepe Rivera
2019-11-20 14:28:32 -08:00
committed by GitHub
parent 9ee2f8a293
commit 288a90e0fe
16 changed files with 215 additions and 764 deletions

View File

@@ -413,6 +413,9 @@
<ProjectReference Include="..\CalcManager\CalcManager.vcxproj">
<Project>{311e866d-8b93-4609-a691-265941fee101}</Project>
</ProjectReference>
<ProjectReference Include="..\GraphControl\GraphControl.vcxproj">
<Project>{e727a92b-f149-492c-8117-c039a298719b}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup Condition="!Exists('DataLoaders\DataLoaderConstants.h')">
<ClCompile>

View File

@@ -14,6 +14,7 @@ using namespace std;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::Foundation::Collections;
using namespace GraphControl;
namespace CalculatorApp::ViewModel
{
@@ -31,83 +32,62 @@ namespace CalculatorApp::ViewModel
{
}
EquationViewModel::EquationViewModel()
: m_LineColor{ nullptr }
, m_Expression{ "" }
, m_IsAnalysisUpdated{ false }
, m_Domain{ "" }
, m_Range{ "" }
, m_XIntercept{ "" }
, m_YIntercept{ "" }
, m_Parity{ -1 }
, m_PeriodicityDirection{ -1 }
, m_PeriodicityExpression{ "" }
, m_Minima{ ref new Vector<String ^>() }
, m_Maxima{ ref new Vector<String ^>() }
, m_InflectionPoints{ ref new Vector<String ^>() }
, m_Monotonicity{ ref new Map<String ^, String ^>() }
, m_VerticalAsymptotes{ ref new Vector<String ^>() }
, m_HorizontalAsymptotes{ ref new Vector<String ^>() }
, m_ObliqueAsymptotes{ ref new Vector<String ^>() }
, m_TooComplexFeatures{ -1 }
, m_AnalysisError{ 0 }
, m_AnalysisErrorVisible{ false }
EquationViewModel::EquationViewModel(GraphControl::Equation ^ equation)
: m_AnalysisErrorVisible{ false }
, m_KeyGraphFeaturesItems{ ref new Vector<KeyGraphFeaturesItem ^>() }
, m_resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() }
{
}
void EquationViewModel::OnPropertyChanged(String ^ propertyName)
{
if (propertyName == L"IsAnalysisUpdated")
if (equation == nullptr)
{
OnIsAnalysisUpdatedChanged();
throw ref new InvalidArgumentException(L"Equation cannot be null");
}
GraphEquation = equation;
}
void EquationViewModel::OnIsAnalysisUpdatedChanged()
void EquationViewModel::PopulateKeyGraphFeatures()
{
if (IsAnalysisUpdated)
if (GraphEquation->AnalysisError != 0)
{
if (AnalysisError != 0)
AnalysisErrorVisible = true;
if (GraphEquation->AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisCouldNotBePerformed))
{
AnalysisErrorVisible = true;
if (AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisCouldNotBePerformed))
{
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisCouldNotBePerformed");
}
else if (AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisNotSupported))
{
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisNotSupported");
}
return;
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisCouldNotBePerformed");
}
KeyGraphFeaturesItems->Clear();
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Domain"), Domain, m_resourceLoader->GetString(L"KGFDomainNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Range"), Range, m_resourceLoader->GetString(L"KGFRangeNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"XIntercept"), XIntercept, m_resourceLoader->GetString(L"KGFXInterceptNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"YIntercept"), YIntercept, m_resourceLoader->GetString(L"KGFYInterceptNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Minima"), Minima, m_resourceLoader->GetString(L"KGFMinimaNone"));
SetKeyGraphFeaturesItems(m_resourceLoader->GetString(L"Maxima"), Maxima, m_resourceLoader->GetString(L"KGFMaximaNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"InflectionPoints"), InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"VerticalAsymptotes"), VerticalAsymptotes, m_resourceLoader->GetString(L"KGFVerticalAsymptotesNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"HorizontalAsymptotes"), HorizontalAsymptotes, m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
SetKeyGraphFeaturesItems(
m_resourceLoader->GetString(L"ObliqueAsymptotes"), ObliqueAsymptotes, m_resourceLoader->GetString(L"KGFObliqueAsymptotesNone"));
SetParityStringProperty();
SetPeriodicityStringProperty();
SetMonotoncityStringProperty();
SetTooComplexFeaturesErrorProperty();
AnalysisErrorVisible = false;
IsAnalysisUpdated = false;
else if (GraphEquation->AnalysisError == static_cast<int>(AnalysisErrorType::AnalysisNotSupported))
{
AnalysisErrorString = m_resourceLoader->GetString(L"KGFAnalysisNotSupported");
}
return;
}
KeyGraphFeaturesItems->Clear();
AddKeyGraphFeature(m_resourceLoader->GetString(L"Domain"), GraphEquation->Domain, m_resourceLoader->GetString(L"KGFDomainNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"Range"), GraphEquation->Range, m_resourceLoader->GetString(L"KGFRangeNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"XIntercept"), GraphEquation->XIntercept, m_resourceLoader->GetString(L"KGFXInterceptNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"YIntercept"), GraphEquation->YIntercept, m_resourceLoader->GetString(L"KGFYInterceptNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"Minima"), GraphEquation->Minima, m_resourceLoader->GetString(L"KGFMinimaNone"));
AddKeyGraphFeature(m_resourceLoader->GetString(L"Maxima"), GraphEquation->Maxima, m_resourceLoader->GetString(L"KGFMaximaNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"InflectionPoints"), GraphEquation->InflectionPoints, m_resourceLoader->GetString(L"KGFInflectionPointsNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"VerticalAsymptotes"), GraphEquation->VerticalAsymptotes, m_resourceLoader->GetString(L"KGFVerticalAsymptotesNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"HorizontalAsymptotes"),
GraphEquation->HorizontalAsymptotes,
m_resourceLoader->GetString(L"KGFHorizontalAsymptotesNone"));
AddKeyGraphFeature(
m_resourceLoader->GetString(L"ObliqueAsymptotes"), GraphEquation->ObliqueAsymptotes, m_resourceLoader->GetString(L"KGFObliqueAsymptotesNone"));
AddParityKeyGraphFeature();
AddPeriodicityKeyGraphFeature();
AddMonotoncityKeyGraphFeature();
AddTooComplexKeyGraphFeature();
AnalysisErrorVisible = false;
}
void EquationViewModel::SetKeyGraphFeaturesItems(String ^ title, String ^ expression, String ^ errorString)
void EquationViewModel::AddKeyGraphFeature(String ^ title, String ^ expression, String ^ errorString)
{
KeyGraphFeaturesItem ^ item = ref new KeyGraphFeaturesItem();
item->Title = title;
@@ -124,7 +104,7 @@ namespace CalculatorApp::ViewModel
KeyGraphFeaturesItems->Append(item);
}
void EquationViewModel::SetKeyGraphFeaturesItems(String ^ title, IObservableVector<String ^> ^ expressionVector, String ^ errorString)
void EquationViewModel::AddKeyGraphFeature(String ^ title, IVector<String ^> ^ expressionVector, String ^ errorString)
{
KeyGraphFeaturesItem ^ item = ref new KeyGraphFeaturesItem();
item->Title = title;
@@ -144,11 +124,11 @@ namespace CalculatorApp::ViewModel
KeyGraphFeaturesItems->Append(item);
}
void EquationViewModel::SetParityStringProperty()
void EquationViewModel::AddParityKeyGraphFeature()
{
KeyGraphFeaturesItem ^ parityItem = ref new KeyGraphFeaturesItem();
parityItem->Title = m_resourceLoader->GetString(L"Parity");
switch (Parity)
switch (GraphEquation->Parity)
{
case 0:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityUnknown"));
@@ -164,18 +144,17 @@ namespace CalculatorApp::ViewModel
break;
default:
parityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFParityUnknown"));
}
parityItem->IsText = true;
KeyGraphFeaturesItems->Append(parityItem);
}
void EquationViewModel::SetPeriodicityStringProperty()
void EquationViewModel::AddPeriodicityKeyGraphFeature()
{
KeyGraphFeaturesItem ^ periodicityItem = ref new KeyGraphFeaturesItem();
periodicityItem->Title = m_resourceLoader->GetString(L"Periodicity");
switch (PeriodicityDirection)
switch (GraphEquation->PeriodicityDirection)
{
case 0:
// Periodicity is not supported or is too complex to calculate.
@@ -183,14 +162,14 @@ namespace CalculatorApp::ViewModel
// SetTooComplexFeaturesErrorProperty will set the too complex error when periodicity is supported and unknown
return;
case 1:
if (PeriodicityExpression == L"")
if (GraphEquation->PeriodicityExpression == L"")
{
periodicityItem->DisplayItems->Append(m_resourceLoader->GetString(L"KGFPeriodicityUnknown"));
periodicityItem->IsText = true;
}
else
{
periodicityItem->DisplayItems->Append(PeriodicityExpression);
periodicityItem->DisplayItems->Append(GraphEquation->PeriodicityExpression);
periodicityItem->IsText = false;
}
break;
@@ -206,13 +185,13 @@ namespace CalculatorApp::ViewModel
KeyGraphFeaturesItems->Append(periodicityItem);
}
void EquationViewModel::SetMonotoncityStringProperty()
void EquationViewModel::AddMonotoncityKeyGraphFeature()
{
KeyGraphFeaturesItem ^ monotonicityItem = ref new KeyGraphFeaturesItem();
monotonicityItem->Title = m_resourceLoader->GetString(L"Monotonicity");
if (Monotonicity->Size != 0)
if (GraphEquation->Monotonicity->Size != 0)
{
for (auto item : Monotonicity)
for (auto item : GraphEquation->Monotonicity)
{
GridDisplayItems ^ gridItem = ref new GridDisplayItems();
gridItem->Expression = item->Key;
@@ -250,9 +229,9 @@ namespace CalculatorApp::ViewModel
KeyGraphFeaturesItems->Append(monotonicityItem);
}
void EquationViewModel::SetTooComplexFeaturesErrorProperty()
void EquationViewModel::AddTooComplexKeyGraphFeature()
{
if (TooComplexFeatures <= 0)
if (GraphEquation->TooComplexFeatures <= 0)
{
return;
}
@@ -260,55 +239,55 @@ namespace CalculatorApp::ViewModel
Platform::String ^ separator = ref new String(LocalizationSettings::GetInstance().GetListSeparator().c_str());
wstring error;
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Domain) == KeyGraphFeaturesFlag::Domain)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Domain) == KeyGraphFeaturesFlag::Domain)
{
error.append((m_resourceLoader->GetString(L"Domain") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Range) == KeyGraphFeaturesFlag::Range)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Range) == KeyGraphFeaturesFlag::Range)
{
error.append((m_resourceLoader->GetString(L"Range") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Zeros) == KeyGraphFeaturesFlag::Zeros)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Zeros) == KeyGraphFeaturesFlag::Zeros)
{
error.append((m_resourceLoader->GetString(L"XIntercept") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::YIntercept) == KeyGraphFeaturesFlag::YIntercept)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::YIntercept) == KeyGraphFeaturesFlag::YIntercept)
{
error.append((m_resourceLoader->GetString(L"YIntercept") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Parity) == KeyGraphFeaturesFlag::Parity)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Parity) == KeyGraphFeaturesFlag::Parity)
{
error.append((m_resourceLoader->GetString(L"Parity") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Periodicity) == KeyGraphFeaturesFlag::Periodicity)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Periodicity) == KeyGraphFeaturesFlag::Periodicity)
{
error.append((m_resourceLoader->GetString(L"Periodicity") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Minima) == KeyGraphFeaturesFlag::Minima)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Minima) == KeyGraphFeaturesFlag::Minima)
{
error.append((m_resourceLoader->GetString(L"Minima") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::Maxima) == KeyGraphFeaturesFlag::Maxima)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::Maxima) == KeyGraphFeaturesFlag::Maxima)
{
error.append((m_resourceLoader->GetString(L"Maxima") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::InflectionPoints) == KeyGraphFeaturesFlag::InflectionPoints)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::InflectionPoints) == KeyGraphFeaturesFlag::InflectionPoints)
{
error.append((m_resourceLoader->GetString(L"InflectionPoints") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::VerticalAsymptotes) == KeyGraphFeaturesFlag::VerticalAsymptotes)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::VerticalAsymptotes) == KeyGraphFeaturesFlag::VerticalAsymptotes)
{
error.append((m_resourceLoader->GetString(L"VerticalAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::HorizontalAsymptotes) == KeyGraphFeaturesFlag::HorizontalAsymptotes)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::HorizontalAsymptotes) == KeyGraphFeaturesFlag::HorizontalAsymptotes)
{
error.append((m_resourceLoader->GetString(L"HorizontalAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::ObliqueAsymptotes) == KeyGraphFeaturesFlag::ObliqueAsymptotes)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::ObliqueAsymptotes) == KeyGraphFeaturesFlag::ObliqueAsymptotes)
{
error.append((m_resourceLoader->GetString(L"ObliqueAsymptotes") + separator + L" ")->Data());
}
if ((TooComplexFeatures & KeyGraphFeaturesFlag::MonotoneIntervals) == KeyGraphFeaturesFlag::MonotoneIntervals)
if ((GraphEquation->TooComplexFeatures & KeyGraphFeaturesFlag::MonotoneIntervals) == KeyGraphFeaturesFlag::MonotoneIntervals)
{
error.append((m_resourceLoader->GetString(L"Monotonicity") + separator + L" ")->Data());
}

View File

@@ -36,58 +36,60 @@ public
ref class EquationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{
public:
EquationViewModel();
EquationViewModel(GraphControl::Equation ^ equation);
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Expression);
OBSERVABLE_PROPERTY_RW(Windows::UI::Xaml::Media::SolidColorBrush ^, LineColor);
OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(GraphControl::Equation ^, GraphEquation);
// Key Graph Features
OBSERVABLE_PROPERTY_RW_ALWAYS_NOTIFY(bool, IsAnalysisUpdated);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Domain);
OBSERVABLE_PROPERTY_RW(Platform::String ^, Range);
OBSERVABLE_PROPERTY_RW(Platform::String ^, XIntercept);
OBSERVABLE_PROPERTY_RW(Platform::String ^, YIntercept);
OBSERVABLE_PROPERTY_RW(int, Parity);
OBSERVABLE_PROPERTY_RW(int, PeriodicityDirection);
OBSERVABLE_PROPERTY_RW(Platform::String ^, PeriodicityExpression);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, Minima);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, Maxima);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, InflectionPoints);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, VerticalAsymptotes);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, HorizontalAsymptotes);
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^, ObliqueAsymptotes);
OBSERVABLE_PROPERTY_RW(int, TooComplexFeatures);
OBSERVABLE_PROPERTY_RW(int, AnalysisError);
OBSERVABLE_PROPERTY_R(Platform::String ^, AnalysisErrorString);
OBSERVABLE_PROPERTY_R(bool, AnalysisErrorVisible);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<CalculatorApp::ViewModel::KeyGraphFeaturesItem ^> ^, KeyGraphFeaturesItems)
property Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ Monotonicity
property Platform::String ^ Expression
{
Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ get()
Platform::String ^ get()
{
return m_Monotonicity;
return GraphEquation->Expression;
}
void set(Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String^> ^ value)
void set(Platform::String ^ value)
{
if (m_Monotonicity != value)
if (GraphEquation->Expression != value)
{
m_Monotonicity = value;
GraphEquation->Expression = value;
RaisePropertyChanged("Expression");
}
}
}
property Windows::UI::Xaml::Media::SolidColorBrush ^ LineColor
{
Windows::UI::Xaml::Media::SolidColorBrush ^ get()
{
return GraphEquation->LineColor;
}
void set(Windows::UI::Xaml::Media::SolidColorBrush ^ value)
{
if (GraphEquation->LineColor != value)
{
GraphEquation->LineColor = value;
RaisePropertyChanged("LineColor");
}
}
}
// Key Graph Features
OBSERVABLE_PROPERTY_R(Platform::String ^, AnalysisErrorString);
OBSERVABLE_PROPERTY_R(bool, AnalysisErrorVisible);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<CalculatorApp::ViewModel::KeyGraphFeaturesItem ^> ^, KeyGraphFeaturesItems)
void PopulateKeyGraphFeatures();
private:
void OnPropertyChanged(Platform::String ^ propertyName);
void SetParityStringProperty();
void SetPeriodicityStringProperty();
void SetKeyGraphFeaturesItems(Platform::String ^ title, Platform::String ^ expression, Platform::String ^ errorString);
void SetKeyGraphFeaturesItems(Platform::String ^ title, Windows::Foundation::Collections::IObservableVector<Platform::String ^> ^ expressionVector,
void AddKeyGraphFeature(Platform::String ^ title, Platform::String ^ expression, Platform::String ^ errorString);
void AddKeyGraphFeature(
Platform::String ^ title,
Windows::Foundation::Collections::IVector<Platform::String ^> ^ expressionVector,
Platform::String ^ errorString);
void SetMonotoncityStringProperty();
void SetTooComplexFeaturesErrorProperty();
void OnIsAnalysisUpdatedChanged();
void AddParityKeyGraphFeature();
void AddPeriodicityKeyGraphFeature();
void AddMonotoncityKeyGraphFeature();
void AddTooComplexKeyGraphFeature();
Windows::Foundation::Collections::IObservableMap<Platform::String ^, Platform::String ^> ^ m_Monotonicity;
Windows::ApplicationModel::Resources::ResourceLoader ^ m_resourceLoader;