class VectorMetricsViewModel:
    calculator = VectorMetrics()
    METRICS = {
        'L1': calculator.l1,
        'L2': calculator.l2,
        'L3': calculator.l3,
        'L4': calculator.l4,
        'Linf': calculator.linf
    }

    def __init__(self, logger=RealLogger()):
        self.logger = logger
        self.logger.log('Welcome to The Float Vector Metrics Calculator!')
        self.x = [0, 0, 0]
        self.y = [0, 0, 0]
        self.x_in = str(self.x)
        self.y_in = str(self.y)
        self.button_state = "disabled"
        self.result = 0
        self.error_msg = ''
        self.metric = None

    def validate(self, value):
        try:
            value = eval(value)
            if isinstance(value, list):
                self.button_state = "active"
                self.error_msg = ''
                return True
            else:
                self.error_msg = "Error: Only list notations supported"
                self.logger.log('%s' % self.error_msg)
                self.button_state = "disabled"
                return False
        except Exception as exp:
            self.error_msg = "Error: Incorrect expression, only list of float or int values supported"
            self.logger.log('%s' % self.error_msg)
            self.button_state = "disabled"
            return False

    def get_button_state(self):
        return self.button_state

    def set_button_state(self, state):
        self.button_state = state

    def set_x(self, value):
        self.x_in = value
        is_valid = self.validate(value)
        if is_valid:
            self.x = eval(value)
            self.logger.log('Setting x vector to %s' % self.x_in)
        return is_valid

    def get_x(self):
        return self.x_in

    def set_y(self, value):
        self.y_in = value
        is_valid = self.validate(value)
        if is_valid:
            self.y = eval(value)
            self.logger.log('Setting y vector to %s' % self.y_in)
        return is_valid

    def get_y(self):
        return self.y_in

    def get_error_message(self):
        return self.error_msg

    def set_metric(self, value):
        self.metric = self.METRICS.get(value, None)
        self.logger.log('Setting metric to %s' % value)
        if self.metric is not None and self.error_msg == '':
            self.button_state = 'active'

    def compute(self):
        self.logger.log('Button clicked')
        try:
            self.result = self.metric(self.x, self.y)
            self.logger.log('Result: %s' % self.result)
        except Exception as exp:
            self.error_msg = "Error: {}".format(exp)
            self.logger.log('%s' % self.error_msg)

    def get_result(self):
        return "Result: {}".format(self.result)
 def test_can_raise_error_when_p_is_not_int(self):
     a = [1.2]
     b = [5]
     metrics_calculator = VectorMetrics()
     with self.assertRaises(TypeError):
         metrics_calculator._VectorMetrics__lp(a, b, 0.4)
 def test_can_raise_error_when_element_vector_invalid_type(self):
     a = ['1.2']
     b = [5]
     metrics_calculator = VectorMetrics()
     with self.assertRaises(TypeError):
         metrics_calculator.l1(a, b)
 def test_can_raise_error_when_p_negative(self):
     a = [1.2]
     b = [5]
     metrics_calculator = VectorMetrics()
     with self.assertRaises(ValueError):
         metrics_calculator._VectorMetrics__lp(a, b, -1)
 def test_can_create_class(self):
     metrics_calc = VectorMetrics()
     self.assertTrue(isinstance(metrics_calc, VectorMetrics))
 def test_can_raise_error_when_vector_not_list(self):
     a = [1.2, 1.5, 1.8]
     b = 5
     metrics_calculator = VectorMetrics()
     with self.assertRaises(TypeError):
         metrics_calculator.l4(a, b)
 def test_can_raise_error_when_vector_of_unequal_length(self):
     a = [1.2, 1.5, 1.8]
     b = [5]
     metrics_calculator = VectorMetrics()
     with self.assertRaises(ValueError):
         metrics_calculator.l3(a, b)
 def test_can_calculate_linf_metric(self):
     a = [1.2, 1.5, 1.8]
     b = [3.3, 8.7, 1.7]
     metrics_calculator = VectorMetrics()
     calc_value = metrics_calculator.linf(a, b)
     self.assertAlmostEqual(calc_value, 7.19999999)
 def test_can_calculate_l4_metric(self):
     a = [1.2, 1.8, 1.4]
     b = [1.2, 1.4, 1.8]
     metrics_calculator = VectorMetrics()
     calc_value = metrics_calculator.l4(a, b)
     self.assertAlmostEqual(calc_value, 0.4756828)
 def test_can_calculate_l3_metric(self):
     a = [1.2, 1.5, 1.8]
     b = [5.2, 7.5, 1.7]
     metrics_calculator = VectorMetrics()
     calc_value = metrics_calculator.l3(a, b)
     self.assertAlmostEqual(calc_value, 6.5421404)
 def test_can_calculate_l2_metric(self):
     a = [1.2, 1.5, 1.8]
     b = [1.3, 1.4, 1.7]
     metrics_calculator = VectorMetrics()
     calc_value = metrics_calculator.l2(a, b)
     self.assertAlmostEqual(calc_value, 0.17320508)
 def test_can_calculate_l1_metric(self):
     a = [1.2, 1.5, 1.8]
     b = [2.2, 2.5, 2.8]
     metrics_calculator = VectorMetrics()
     calc_value = metrics_calculator.l1(a, b)
     self.assertEqual(calc_value, 3)