diff --git a/apps/probability/Makefile b/apps/probability/Makefile index c66d45e14..dd36d2129 100644 --- a/apps/probability/Makefile +++ b/apps/probability/Makefile @@ -1,6 +1,10 @@ app_objs += $(addprefix apps/probability/,\ app.o\ calculation.o\ + left_integral_calculation.o\ + right_integral_calculation.o\ + finite_integral_calculation.o\ + calculation.o\ calculation_controller.o\ cell.o\ image_table_view.o\ diff --git a/apps/probability/calculation.cpp b/apps/probability/calculation.cpp index fb74a8e88..791f7a501 100644 --- a/apps/probability/calculation.cpp +++ b/apps/probability/calculation.cpp @@ -5,88 +5,13 @@ namespace Probability { Calculation::Calculation(): - m_type(LeftIntegral), - m_parameter1(0.0f), - m_parameter2(0.0f), - m_parameter3(0.0f), m_law(nullptr) { } void Calculation::setLaw(Law * law) { m_law = law; - computeCalculation(0); -} - -void Calculation::setType(Type type) { - m_type = type; - initParameters(); -} - -Calculation::Type Calculation::type() const { - return m_type; -} - -float Calculation::parameterAtIndex(int index) { - if (index == 0) { - return m_parameter1; - } - if (index == 1) { - return m_parameter2; - } - return m_parameter3; -} - -void Calculation::setParameterAtIndex(float f, int index) { - if (index == 0) { - m_parameter1 = f; - } - if (index == 1) { - m_parameter2 = f; - } - if (index == 2) { - m_parameter3 = f; - } - computeCalculation(index); -} - -void Calculation::computeCalculation(int indexKnownElement) { - if (m_law == nullptr) { - return; - } - if (m_type == LeftIntegral) { - if (indexKnownElement == 0) { - m_parameter2 = m_law->cumulativeDistributiveFunctionAtAbscissa(m_parameter1); - } else { - m_parameter1 = m_law->cumulativeDistributiveInverseForProbability(&m_parameter2); - } - } - if (m_type == FiniteIntegral) { - m_parameter3 = m_law->finiteIntegralBetweenAbscissas(m_parameter1, m_parameter2); - } - if (m_type == RightIntegral) { - if (indexKnownElement == 0) { - m_parameter2 = m_law->rightIntegralFromAbscissa(m_parameter1); - } else { - m_parameter1 = m_law->rightIntegralInverseForProbability(&m_parameter2); - } - } -} - -void Calculation::initParameters() { - if (m_type == LeftIntegral) { - m_parameter1 = 0.0f; - computeCalculation(0); - } - if (m_type == FiniteIntegral) { - m_parameter1 = -1.0f; - m_parameter2 = 1.0f; - computeCalculation(0); - } - if (m_type == RightIntegral) { - m_parameter1 = 0.0f; - computeCalculation(0); - } + compute(0); } } diff --git a/apps/probability/calculation.h b/apps/probability/calculation.h index 0fa606cb7..e76ced3e3 100644 --- a/apps/probability/calculation.h +++ b/apps/probability/calculation.h @@ -7,24 +7,21 @@ namespace Probability { class Calculation { public: - enum Type : uint8_t { + enum class Type : uint8_t{ LeftIntegral = 0, FiniteIntegral = 1, - RightIntegral = 2, + RightIntegral = 2 }; Calculation(); + virtual ~Calculation() {}; void setLaw(Law * law); - void setType(Type type); - Type type() const; - float parameterAtIndex(int index); - void setParameterAtIndex(float f, int index); -private: - void computeCalculation(int indexKnownElement); - void initParameters(); - Type m_type; - float m_parameter1; - float m_parameter2; - float m_parameter3; + virtual Type type() const = 0; + virtual int numberOfParameters() = 0; + virtual const char * legendForParameterAtIndex(int index) = 0; + virtual void setParameterAtIndex(float f, int index) = 0; + virtual float parameterAtIndex(int index) = 0; +protected: + virtual void compute(int indexKnownElement) = 0; Law * m_law; }; diff --git a/apps/probability/calculation_controller.cpp b/apps/probability/calculation_controller.cpp index 82e244418..4f9a6cb9e 100644 --- a/apps/probability/calculation_controller.cpp +++ b/apps/probability/calculation_controller.cpp @@ -7,7 +7,7 @@ namespace Probability { CalculationController::ContentView::ContentView(Responder * parentResponder, CalculationController * calculationController, Calculation * calculation) : m_lawCurveView(LawCurveView()), - m_imageTableView(ImageTableView(parentResponder, calculation)), + m_imageTableView(ImageTableView(parentResponder, calculation, calculationController)), m_calculationCell{EditableTextCell(parentResponder, calculationController, m_draftTextBuffer), EditableTextCell(parentResponder, calculationController, m_draftTextBuffer), EditableTextCell(parentResponder, calculationController, m_draftTextBuffer)}, @@ -19,11 +19,13 @@ void CalculationController::ContentView::setLaw(Law * law) { m_lawCurveView.setLaw(law); } +void CalculationController::ContentView::setCalculation(Calculation * calculation) { + m_calculation = calculation; + m_imageTableView.setCalculation(calculation); +} + int CalculationController::ContentView::numberOfSubviews() const { - if ((int)m_calculation->type() == 1) { - return 8; - } - return 6; + return 2*m_calculation->numberOfParameters() + 2; } View * CalculationController::ContentView::subviewAtIndex(int index) { @@ -35,29 +37,17 @@ View * CalculationController::ContentView::subviewAtIndex(int index) { return &m_imageTableView; } if (index == 2) { - if ((int)m_calculation->type() == 0) { - m_text[0].setText("P(X <= "); - } else { - m_text[0].setText("P( "); - } + m_text[0].setText(m_calculation->legendForParameterAtIndex(0)); m_text[0].setAlignment(0.5f, 0.5f); return &m_text[0]; } if (index == 4) { - if (m_calculation->type() == Calculation::Type::LeftIntegral) { - m_text[1].setText(") = "); - } - if (m_calculation->type() == Calculation::Type::FiniteIntegral) { - m_text[1].setText(" <= X <= "); - } - if (m_calculation->type() == Calculation::Type::RightIntegral) { - m_text[1].setText(" <= X ) = "); - } + m_text[1].setText(m_calculation->legendForParameterAtIndex(1)); m_text[1].setAlignment(0.5f, 0.5f); return &m_text[1]; } if (index == 6) { - m_text[2].setText(" )= "); + m_text[2].setText(m_calculation->legendForParameterAtIndex(2)); m_text[2].setAlignment(0.5f, 0.5f); return &m_text[2]; } @@ -79,38 +69,27 @@ void CalculationController::ContentView::layoutSubviews() { m_lawCurveView.setFrame(KDRect(0, ImageTableView::k_imageHeight, bounds().width(), bounds().height() - ImageTableView::k_imageHeight)); m_imageTableView.setFrame(KDRect(xCoordinate, 0, ImageTableView::k_imageWidth, 3*ImageTableView::k_imageHeight)); xCoordinate += ImageTableView::k_imageWidth + k_textMargin; - KDCoordinate numberOfCharacters = 7; - if ((int)m_calculation->type() > 0) { - numberOfCharacters = 3; - } + KDCoordinate numberOfCharacters = strlen(m_calculation->legendForParameterAtIndex(0)); m_text[0].setFrame(KDRect(xCoordinate, 0, numberOfCharacters*k_charWidth, ImageTableView::k_imageHeight)); xCoordinate += numberOfCharacters*k_charWidth + k_textMargin; m_calculationCell[0].setFrame(KDRect(xCoordinate, 0, k_textFieldWidth, ImageTableView::k_imageHeight)); xCoordinate += k_textFieldWidth + k_textMargin; - if (m_calculation->type() == Calculation::Type::LeftIntegral) { - numberOfCharacters = 4; - } - if (m_calculation->type() == Calculation::Type::FiniteIntegral) { - numberOfCharacters = 9; - } - if (m_calculation->type() == Calculation::Type::RightIntegral) { - numberOfCharacters = 10; - } + numberOfCharacters = strlen(m_calculation->legendForParameterAtIndex(1)); m_text[1].setFrame(KDRect(xCoordinate, 0, numberOfCharacters*k_charWidth, ImageTableView::k_imageHeight)); xCoordinate += numberOfCharacters*k_charWidth + k_textMargin; m_calculationCell[1].setFrame(KDRect(xCoordinate, 0, k_textFieldWidth, ImageTableView::k_imageHeight)); xCoordinate += k_textFieldWidth + k_textMargin; - numberOfCharacters = 4; - m_text[2].setFrame(KDRect(xCoordinate, 0, numberOfCharacters*k_charWidth, ImageTableView::k_imageHeight)); - xCoordinate += numberOfCharacters*k_charWidth + k_textMargin; - m_calculationCell[2].setFrame(KDRect(xCoordinate, 0, k_textFieldWidth, ImageTableView::k_imageHeight)); - - for (int k = 0; k < k_maxNumberOfEditableFields; k++) { + if (m_calculation->numberOfParameters() > 2) { + numberOfCharacters = strlen(m_calculation->legendForParameterAtIndex(2));; + m_text[2].setFrame(KDRect(xCoordinate, 0, numberOfCharacters*k_charWidth, ImageTableView::k_imageHeight)); + xCoordinate += numberOfCharacters*k_charWidth + k_textMargin; + m_calculationCell[2].setFrame(KDRect(xCoordinate, 0, k_textFieldWidth, ImageTableView::k_imageHeight)); + } + for (int k = 0; k < m_calculation->numberOfParameters(); k++) { willDisplayEditableCellAtIndex(k); } } - void CalculationController::ContentView::drawRect(KDContext * ctx, KDRect rect) const { ctx->fillRect(bounds(), KDColorWhite); } @@ -129,9 +108,10 @@ EditableTextCell * CalculationController::ContentView::calculationCellAtIndex(in CalculationController::CalculationController(Responder * parentResponder) : ViewController(parentResponder), - m_contentView(ContentView(this, this, &m_calculation)), - m_highlightedSubviewIndex(1), - m_calculation(Calculation()) + m_calculation(new LeftIntegralCalculation()), + m_contentView(ContentView(this, this, m_calculation)), + m_law(nullptr), + m_highlightedSubviewIndex(1) { } @@ -144,12 +124,31 @@ const char * CalculationController::title() const { } void CalculationController::setLaw(Law * law) { + m_law = law; m_contentView.setLaw(law); - m_calculation.setLaw(law); + m_calculation->setLaw(law); } -Calculation * CalculationController::calculation() { - return &m_calculation; +void CalculationController::setCalculationAccordingToIndex(int index) { + if (m_calculation != nullptr) { + delete m_calculation; + m_calculation = nullptr; + } + switch (index) { + case 0: + m_calculation = new LeftIntegralCalculation(); + break; + case 1: + m_calculation = new FiniteIntegralCalculation(); + break; + case 2: + m_calculation = new RightIntegralCalculation(); + break; + default: + return; + } + m_calculation->setLaw(m_law); + m_contentView.setCalculation(m_calculation); } bool CalculationController::handleEvent(Ion::Events::Event event) { @@ -192,8 +191,8 @@ bool CalculationController::textFieldDidFinishEditing(TextField * textField, con AppsContainer * appsContainer = (AppsContainer *)app()->container(); Context * globalContext = appsContainer->globalContext(); float floatBody = Expression::parse(text)->approximate(*globalContext); - m_calculation.setParameterAtIndex(floatBody, m_highlightedSubviewIndex-1); - for (int k = 0; k < ContentView::k_maxNumberOfEditableFields; k++) { + m_calculation->setParameterAtIndex(floatBody, m_highlightedSubviewIndex-1); + for (int k = 0; k < m_calculation->numberOfParameters(); k++) { m_contentView.willDisplayEditableCellAtIndex(k); } return true; diff --git a/apps/probability/calculation_controller.h b/apps/probability/calculation_controller.h index 8ac351514..9715c3a3e 100644 --- a/apps/probability/calculation_controller.h +++ b/apps/probability/calculation_controller.h @@ -14,17 +14,19 @@ public: View * view() override; const char * title() const override; void setLaw(Law * law); - Calculation * calculation(); + void setCalculationAccordingToIndex(int index); bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; void selectSubview(int subviewIndex); bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override; bool textFieldDidFinishEditing(TextField * textField, const char * text) override; private: + Calculation * m_calculation; class ContentView : public View { public: ContentView(Responder * parentResponder, CalculationController * calculationController, Calculation * Calculation); void setLaw(Law * law); + void setCalculation(Calculation * calculation); void layoutSubviews() override; void drawRect(KDContext * ctx, KDRect rect) const override; LawCurveView * lawCurveView(); @@ -46,8 +48,8 @@ private: Calculation * m_calculation; }; ContentView m_contentView; + Law * m_law; int m_highlightedSubviewIndex; - Calculation m_calculation; }; } diff --git a/apps/probability/finite_integral_calculation.cpp b/apps/probability/finite_integral_calculation.cpp new file mode 100644 index 000000000..d1d1e9fb2 --- /dev/null +++ b/apps/probability/finite_integral_calculation.cpp @@ -0,0 +1,68 @@ +#include "finite_integral_calculation.h" +#include +#include + +namespace Probability { + +FiniteIntegralCalculation::FiniteIntegralCalculation() : + Calculation(), + m_lowerBound(-1.0f), + m_upperBound(1.0f), + m_result(0.0f) +{ + compute(0); +} + +Calculation::Type FiniteIntegralCalculation::type() const { + return Type::FiniteIntegral; +} + +int FiniteIntegralCalculation::numberOfParameters() { + return 3; +} + +const char * FiniteIntegralCalculation::legendForParameterAtIndex(int index) { + assert(index >= 0 && index < 3); + if (index == 0) { + return "P( "; + } + if (index == 1) { + return " <= X <= "; + } + return " )= "; +} + +void FiniteIntegralCalculation::setParameterAtIndex(float f, int index) { + assert(index >= 0 && index < 3); + if (index == 0) { + m_lowerBound = f; + } + if (index == 1) { + m_upperBound = f; + } + if (index == 2) { + m_result = f; + } + compute(index); +} + + +float FiniteIntegralCalculation::parameterAtIndex(int index) { + assert(index >= 0 && index < 3); + if (index == 0) { + return m_lowerBound; + } + if (index == 1) { + return m_upperBound; + } + return m_result; +} + +void FiniteIntegralCalculation::compute(int indexKnownElement) { + if (m_law == nullptr) { + return; + } + m_result = m_law->finiteIntegralBetweenAbscissas(m_lowerBound, m_upperBound); +} + +} diff --git a/apps/probability/finite_integral_calculation.h b/apps/probability/finite_integral_calculation.h new file mode 100644 index 000000000..2f33ce1cc --- /dev/null +++ b/apps/probability/finite_integral_calculation.h @@ -0,0 +1,26 @@ +#ifndef PROBABILITE_FINITE_INTEGRAL_CALCULATION_H +#define PROBABILITE_FINITE_INTEGRAL_CALCULATION_H + +#include "calculation.h" + +namespace Probability { + +class FiniteIntegralCalculation : public Calculation { +public: + FiniteIntegralCalculation(); + ~FiniteIntegralCalculation() override {}; + Type type() const override; + int numberOfParameters() override; + const char * legendForParameterAtIndex(int index) override; + void setParameterAtIndex(float f, int index) override; + float parameterAtIndex(int index) override; +private: + void compute(int indexKnownElement) override; + float m_lowerBound; + float m_upperBound; + float m_result; +}; + +} + +#endif diff --git a/apps/probability/image_table_view.cpp b/apps/probability/image_table_view.cpp index 0d5d11550..20aa3637f 100644 --- a/apps/probability/image_table_view.cpp +++ b/apps/probability/image_table_view.cpp @@ -42,15 +42,20 @@ void ImageTableView::ImageCell::setImage(const Image * image, const Image * focu m_focusedIcon = focusedImage; } -ImageTableView::ImageTableView(Responder * parentResponder, Calculation * calculation) : +ImageTableView::ImageTableView(Responder * parentResponder, Calculation * calculation, CalculationController * calculationController) : View(), Responder(parentResponder), m_selectableTableView(SelectableTableView(this, this, 0, 0, 0, 0, nullptr, false, false)), m_isSelected(false), - m_calculation(calculation) + m_calculation(calculation), + m_calculationController(calculationController) { } +void ImageTableView::setCalculation(Calculation * calculation) { + m_calculation = calculation; +} + void ImageTableView::didBecomeFirstResponder() { m_isSelected = true; if (m_selectableTableView.selectedRow() == -1) { @@ -63,7 +68,7 @@ void ImageTableView::didBecomeFirstResponder() { bool ImageTableView::handleEvent(Ion::Events::Event event) { if (event == Ion::Events::OK) { - m_calculation->setType((Calculation::Type)m_selectableTableView.selectedRow()); + m_calculationController->setCalculationAccordingToIndex(m_selectableTableView.selectedRow()); select(false); setHighlight(true); m_selectableTableView.reloadData(); @@ -79,7 +84,7 @@ void ImageTableView::select(bool select) { m_isSelected = select; } else { m_isSelected = select; - m_selectableTableView.selectCellAtLocation(0, m_calculation->type()); + m_selectableTableView.selectCellAtLocation(0, (int)m_calculation->type()); } } @@ -113,7 +118,7 @@ void ImageTableView::willDisplayCellForIndex(TableViewCell * cell, int index) { const Image * images[3] = {ImageStore::Calcul1Icon, ImageStore::Calcul2Icon, ImageStore::Calcul3Icon}; const Image * focusedImages[3] = {ImageStore::FocusedCalcul1Icon, ImageStore::FocusedCalcul2Icon, ImageStore::FocusedCalcul3Icon}; if (!m_isSelected) { - myCell->setImage(images[m_calculation->type()], focusedImages[m_calculation->type()]); + myCell->setImage(images[(int)m_calculation->type()], focusedImages[(int)m_calculation->type()]); } else { myCell->setImage(images[index], focusedImages[index]); } diff --git a/apps/probability/image_table_view.h b/apps/probability/image_table_view.h index b180c5ab8..f36fdc837 100644 --- a/apps/probability/image_table_view.h +++ b/apps/probability/image_table_view.h @@ -2,13 +2,18 @@ #define PROBABILITY_IMAGE_TABLE_VIEW_H #include -#include "calculation.h" +#include "left_integral_calculation.h" +#include "right_integral_calculation.h" +#include "finite_integral_calculation.h" namespace Probability { +class CalculationController; + class ImageTableView : public View, public Responder, public SimpleListViewDataSource { public: - ImageTableView(Responder * parentResponder, Calculation * calculation); + ImageTableView(Responder * parentResponder, Calculation * calculation, CalculationController * calculationController); + void setCalculation(Calculation * calculation); bool handleEvent(Ion::Events::Event event) override; void didBecomeFirstResponder() override; void select(bool select); @@ -24,6 +29,7 @@ private: int numberOfSubviews() const override; View * subviewAtIndex(int index) override; void layoutSubviews() override; + void setCalculationAccordingToIndex(int index); class ImageCell : public TableViewCell { public: ImageCell(); @@ -42,6 +48,7 @@ private: SelectableTableView m_selectableTableView; bool m_isSelected; Calculation * m_calculation; + CalculationController * m_calculationController; }; } diff --git a/apps/probability/left_integral_calculation.cpp b/apps/probability/left_integral_calculation.cpp new file mode 100644 index 000000000..ab8f7c8c4 --- /dev/null +++ b/apps/probability/left_integral_calculation.cpp @@ -0,0 +1,62 @@ +#include "left_integral_calculation.h" +#include +#include + +namespace Probability { + +LeftIntegralCalculation::LeftIntegralCalculation() : + Calculation(), + m_lowerBound(0.0f), + m_result(0.0f) +{ + compute(0); +} + +Calculation::Type LeftIntegralCalculation::type() const { + return Type::LeftIntegral; +} + +int LeftIntegralCalculation::numberOfParameters() { + return 2; +} + +const char * LeftIntegralCalculation::legendForParameterAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return "P(X <= "; + } + return ") = "; +} + +void LeftIntegralCalculation::setParameterAtIndex(float f, int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + m_lowerBound = f; + } + if (index == 1) { + m_result = f; + } + compute(index); +} + + +float LeftIntegralCalculation::parameterAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return m_lowerBound; + } + return m_result; +} + +void LeftIntegralCalculation::compute(int indexKnownElement) { + if (m_law == nullptr) { + return; + } + if (indexKnownElement == 0) { + m_result = m_law->cumulativeDistributiveFunctionAtAbscissa(m_lowerBound); + } else { + m_lowerBound = m_law->cumulativeDistributiveInverseForProbability(&m_result); + } +} + +} diff --git a/apps/probability/left_integral_calculation.h b/apps/probability/left_integral_calculation.h new file mode 100644 index 000000000..805fda6dc --- /dev/null +++ b/apps/probability/left_integral_calculation.h @@ -0,0 +1,25 @@ +#ifndef PROBABILITE_LEFT_INTEGRAL_CALCULATION_H +#define PROBABILITE_LEFT_INTEGRAL_CALCULATION_H + +#include "calculation.h" + +namespace Probability { + +class LeftIntegralCalculation : public Calculation { +public: + LeftIntegralCalculation(); + ~LeftIntegralCalculation() override {}; + Type type() const override; + int numberOfParameters() override; + const char * legendForParameterAtIndex(int index) override; + void setParameterAtIndex(float f, int index) override; + float parameterAtIndex(int index) override; +private: + void compute(int indexKnownElement) override; + float m_lowerBound; + float m_result; +}; + +} + +#endif diff --git a/apps/probability/parameters_controller.cpp b/apps/probability/parameters_controller.cpp index c1d14226a..98aa1d09b 100644 --- a/apps/probability/parameters_controller.cpp +++ b/apps/probability/parameters_controller.cpp @@ -11,8 +11,7 @@ ParametersController::ContentView::ContentView(Responder * parentResponder, Sele ParametersController * parameterController = (ParametersController *) context; CalculationController * calculationController = parameterController->calculationController(); calculationController->selectSubview(1); - Calculation * calculation = calculationController->calculation(); - calculation->setType(Calculation::Type::LeftIntegral); + calculationController->setCalculationAccordingToIndex(0); StackViewController * stack = parameterController->stackController(); stack->updateTitle(); stack->push(calculationController); diff --git a/apps/probability/right_integral_calculation.cpp b/apps/probability/right_integral_calculation.cpp new file mode 100644 index 000000000..53a14134e --- /dev/null +++ b/apps/probability/right_integral_calculation.cpp @@ -0,0 +1,62 @@ +#include "right_integral_calculation.h" +#include +#include + +namespace Probability { + +RightIntegralCalculation::RightIntegralCalculation() : + Calculation(), + m_upperBound(0.0f), + m_result(0.0f) +{ + compute(0); +} + +Calculation::Type RightIntegralCalculation::type() const { + return Type::RightIntegral; +} + +int RightIntegralCalculation::numberOfParameters() { + return 2; +} + +const char * RightIntegralCalculation::legendForParameterAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return "P( "; + } + return " <= X ) = "; +} + +void RightIntegralCalculation::setParameterAtIndex(float f, int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + m_upperBound = f; + } + if (index == 1) { + m_result = f; + } + compute(index); +} + + +float RightIntegralCalculation::parameterAtIndex(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return m_upperBound; + } + return m_result; +} + +void RightIntegralCalculation::compute(int indexKnownElement) { + if (m_law == nullptr) { + return; + } + if (indexKnownElement == 0) { + m_result = m_law->rightIntegralFromAbscissa(m_upperBound); + } else { + m_upperBound = m_law->rightIntegralInverseForProbability(&m_result); + } +} + +} diff --git a/apps/probability/right_integral_calculation.h b/apps/probability/right_integral_calculation.h new file mode 100644 index 000000000..1a8237f4d --- /dev/null +++ b/apps/probability/right_integral_calculation.h @@ -0,0 +1,25 @@ +#ifndef PROBABILITE_RIGHT_INTEGRAL_CALCULATION_H +#define PROBABILITE_RIGHT_INTEGRAL_CALCULATION_H + +#include "calculation.h" + +namespace Probability { + +class RightIntegralCalculation : public Calculation { +public: + RightIntegralCalculation(); + ~RightIntegralCalculation() override {}; + Type type() const override; + int numberOfParameters() override; + const char * legendForParameterAtIndex(int index) override; + void setParameterAtIndex(float f, int index) override; + float parameterAtIndex(int index) override; +private: + void compute(int indexKnownElement) override; + float m_upperBound; + float m_result; +}; + +} + +#endif