From 5da90b51601e2fbf776cdbbf447e3363723c8a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Fri, 1 Jun 2018 10:30:54 +0200 Subject: [PATCH] [apps/stats] Fill with formula in statistics --- apps/regression/store_controller.h | 1 + apps/shared/store_controller.cpp | 7 +++++ apps/shared/store_controller.h | 1 + apps/statistics/series_context.cpp | 40 ++++++++++++++++------------ apps/statistics/series_context.h | 10 ++++--- apps/statistics/store_controller.cpp | 22 ++++++++++++++- apps/statistics/store_controller.h | 2 ++ 7 files changed, 61 insertions(+), 22 deletions(-) diff --git a/apps/regression/store_controller.h b/apps/regression/store_controller.h index f8720c4a2..3de9511d9 100644 --- a/apps/regression/store_controller.h +++ b/apps/regression/store_controller.h @@ -11,6 +11,7 @@ namespace Regression { class StoreController : public Shared::StoreController { public: StoreController(Responder * parentResponder, Store * store, ButtonRowController * header); + void fillColumnWithFormula(Poincare::Expression * formula) {} void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; private: HighlightCell * titleCells(int index) override; diff --git a/apps/shared/store_controller.cpp b/apps/shared/store_controller.cpp index 54bc7138a..54752db42 100644 --- a/apps/shared/store_controller.cpp +++ b/apps/shared/store_controller.cpp @@ -64,7 +64,14 @@ void StoreController::displayFormulaInput() { bool StoreController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { if (textField == contentView()->formulaInputView()->textField()) { // Handle formula input + Expression * expression = Expression::parse(textField->text()); + if (expression == nullptr) { + app()->displayWarning(I18n::Message::SyntaxError); + return false; + } contentView()->displayFormulaInput(false); + fillColumnWithFormula(expression); + delete expression; app()->setFirstResponder(contentView()); return true; } diff --git a/apps/shared/store_controller.h b/apps/shared/store_controller.h index aa6b6e5e1..2e2b1b5b0 100644 --- a/apps/shared/store_controller.h +++ b/apps/shared/store_controller.h @@ -16,6 +16,7 @@ public: StoreController(Responder * parentResponder, FloatPairStore * store, ButtonRowController * header); void displayFormulaInput(); + virtual void fillColumnWithFormula(Poincare::Expression * formula) = 0; // TextFieldDelegate bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override; diff --git a/apps/statistics/series_context.cpp b/apps/statistics/series_context.cpp index a63f254ea..d02587d02 100644 --- a/apps/statistics/series_context.cpp +++ b/apps/statistics/series_context.cpp @@ -1,31 +1,37 @@ #include "series_context.h" #include #include +#include using namespace Poincare; using namespace Shared; namespace Statistics { +void SeriesContext::setExpressionForSymbolName(const Expression * expression, const Symbol * symbol, Context & context) { + m_parentContext->setExpressionForSymbolName(expression, symbol, context); +} + const Expression * SeriesContext::expressionForSymbol(const Symbol * symbol) { - assert(m_seriesPairIndex >= 0); - if (!symbol->isSeriesSymbol()) { - return nullptr; + if (symbol->isSeriesSymbol()) { + const char * seriesName = Symbol::textForSpecialSymbols(symbol->name()); + assert(strlen(seriesName) == 2); + + int series = (int)(seriesName[1] - '0') - 1; + assert(series >= 0 && series < FloatPairStore::k_numberOfSeries); + + assert((seriesName[0] == 'V') || (seriesName[0] == 'N')); + int storeI = seriesName[0] == 'V' ? 0 : 1; + + assert(m_seriesPairIndex >= 0); + assert(m_seriesPairIndex < m_store->numberOfPairsOfSeries(series)); + + Expression * result = new Decimal(m_store->get(series, storeI, m_seriesPairIndex)); + assert(result != nullptr); + return result; + } else { + return m_parentContext->expressionForSymbol(symbol); } - const char * seriesName = Symbol::textForSpecialSymbols(symbol->name()); - assert(strlen(seriesName) == 2); - - int series = seriesName[1] - '0'; - assert(series >= 0 && series < Store::k_numberOfSeries); - - assert((seriesName[0] == 'V') || (seriesName[0] == 'N')); - int storeI = seriesName[0] == 'V' ? 0 : 1; - - assert(m_seriesPairIndex < store->numberOfPairsOfSeries(series)); - - Expression * result = new Decimal(m_store->get(series, storeI, m_seriesPairIndex)); - assert(result != nullptr); - return result; } } diff --git a/apps/statistics/series_context.h b/apps/statistics/series_context.h index 1ffe4986a..fac98891f 100644 --- a/apps/statistics/series_context.h +++ b/apps/statistics/series_context.h @@ -8,17 +8,19 @@ namespace Statistics { class SeriesContext : public Poincare::Context { public: - SeriesContext(Shared::FloatPairStore * store) : + SeriesContext(Shared::FloatPairStore * store, Poincare::Context * parentContext = nullptr) : Poincare::Context(), m_store(store), - m_seriesPairIndex(-1) + m_seriesPairIndex(-1), + m_parentContext(parentContext) {} - void setStorePosition(int series, int i, int j); - void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol, Poincare::Context & context) override {} + void setSeriesPairIndex(int j) { m_seriesPairIndex = j; } + void setExpressionForSymbolName(const Poincare::Expression * expression, const Poincare::Symbol * symbol, Poincare::Context & context) override; const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; private: Shared::FloatPairStore * m_store; int m_seriesPairIndex; + Poincare::Context * m_parentContext; }; } diff --git a/apps/statistics/store_controller.cpp b/apps/statistics/store_controller.cpp index 7ec96e246..3ea77f6ed 100644 --- a/apps/statistics/store_controller.cpp +++ b/apps/statistics/store_controller.cpp @@ -1,4 +1,5 @@ #include "store_controller.h" +#include "series_context.h" #include "app.h" #include "../apps_container.h" #include "../constant.h" @@ -6,16 +7,35 @@ #include #include +using namespace Poincare; using namespace Shared; namespace Statistics { StoreController::StoreController(Responder * parentResponder, Store * store, ButtonRowController * header) : Shared::StoreController(parentResponder, store, header), - m_titleCells{} + m_titleCells{}, + m_store(store) { } +void StoreController::fillColumnWithFormula(Expression * formula) { + int currentColumn = selectedColumn(); + // Fetch the series used in the formula to: + // - Make sure the current filled column is not inside + // - Compute the size of the filled in series + + SeriesContext seriesContext(m_store, const_cast(static_cast(app()->container()))->globalContext()); + for (int j = 0; j < 2; j++) { + // Set the context + seriesContext.setSeriesPairIndex(j); + // Compute the new value using the formula + double evaluation = formula->approximateToScalar(seriesContext); + setDataAtLocation(evaluation, currentColumn, j + 1); + } + selectableTableView()->reloadData(); +} + void StoreController::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) { Shared::StoreController::willDisplayCellAtLocation(cell, i, j); if (cellAtLocationIsEditable(i, j)) { diff --git a/apps/statistics/store_controller.h b/apps/statistics/store_controller.h index 8427ab5af..6a7d20143 100644 --- a/apps/statistics/store_controller.h +++ b/apps/statistics/store_controller.h @@ -11,6 +11,7 @@ namespace Statistics { class StoreController : public Shared::StoreController { public: StoreController(Responder * parentResponder, Store * store, ButtonRowController * header); + void fillColumnWithFormula(Poincare::Expression * formula) override; void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override; private: bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override; @@ -18,6 +19,7 @@ private: View * loadView() override; void unloadView(View * view) override; Shared::StoreTitleCell * m_titleCells[k_numberOfTitleCells]; + Store * m_store; }; }