"""
Tests for the `.app` attribute belonging to an instance of `porter.ModelService`.
"""

import json
import re
import warnings

import unittest
from unittest import mock

import flask
from werkzeug import exceptions as exc
from porter import __version__
from porter import constants as cn
from porter.datascience import BaseModel, BasePostProcessor, BasePreProcessor
from porter.services import ModelApp, BaseService, PredictionService
import porter.schemas as sc

@mock.patch('porter.responses.api.request_id', lambda: '123')
class TestAppPredictions(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # define objects for model 1
        class Preprocessor1(BasePreProcessor):
            def process(self, X):
                X = X.copy() # silence SettingWithCopyWarning
                X['feature2'] = X.feature2.astype(str)
                return X
        class Model1(BaseModel):
            feature2_map = {str(x+1): x for x in range(5)}
            def predict(self, X):
                return X['feature1'] * X.feature2.map(self.feature2_map)
        class Postprocessor1(BasePostProcessor):
            def process(self, X_input, X_preprocessed, predictions):
                return predictions * -1
        feature_schema1 = sc.Object(
            properties={
                'feature1': sc.Number(),
                'feature2': sc.Number(),
            }
        )

        # define objects for model 2
        class Preprocessor2(BasePreProcessor):
            def process(self, X):
                X['feature3'] = range(len(X))
                return X
        class Model2(BaseModel):
            def predict(self, X):
                return X['feature1'] + X['feature3']
        feature_schema2 = sc.Object(properties={'feature1': sc.Number()})
        def user_check(X):
            if (X.feature1 == 0).any():
                raise exc.UnprocessableEntity

        # define objects for model 3
        class Model3(BaseModel):
            def predict(self, X):
                return X['feature1'] * -1
        feature_schema3 = sc.Object(properties={'feature1': sc.Number()})
        wrong_prediction_schema3 = sc.Number(additional_params=dict(minimum=0))

        cls.prediction_service_error = E = Exception('this mock service failed during prediction')
        class ModelFailing(BaseModel):
            def predict(self, X):
                raise E

        # define configs and add services to app
        prediction_service1 = PredictionService(
            model=Model1(),
            name='a-model',
            api_version='v0',
            action='predict',
            preprocessor=Preprocessor1(),
            postprocessor=Postprocessor1(),
            feature_schema=feature_schema1,
            validate_request_data=True,
            batch_prediction=True
        )
        prediction_service2 = PredictionService(
            model=Model2(),
            name='anotherModel',
            api_version='v1',
            namespace='n/s/',
            preprocessor=Preprocessor2(),
            postprocessor=None,
            feature_schema=feature_schema2,
            validate_request_data=True,
            batch_prediction=True,
            additional_checks=user_check
        )
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')
            prediction_service3 = PredictionService(
                model=Model3(),
                name='model-3',
                api_version='v0.0-alpha',
                preprocessor=None,
                postprocessor=None,
                feature_schema=feature_schema3,
                validate_request_data=True,
                validate_response_data=True,
                batch_prediction=False,
                meta={'algorithm': 'randomforest', 'lasttrained': 1}
            )
            prediction_service4 = PredictionService(
                model=Model3(),
                name='model-4',
                api_version='v0.0-alpha',
                preprocessor=None,
                postprocessor=None,
                feature_schema=feature_schema3,
                validate_request_data=True,
                validate_response_data=True,
                batch_prediction=False,
                meta={'algorithm': 'randomforest', 'lasttrained': 1}
            )
            prediction_service5 = PredictionService(
                model=Model3(),
                name='model-5',
                api_version='v0.0-alpha',
                preprocessor=None,
                postprocessor=None,
                feature_schema=feature_schema3,
                prediction_schema=wrong_prediction_schema3,
                validate_request_data=True,
                validate_response_data=True,
                batch_prediction=False,
                meta={'algorithm': 'randomforest', 'lasttrained': 1}
            )
        prediction_service_failing = PredictionService(
            model=ModelFailing(),
            name='failing-model',
            api_version='v1',
            action='fail',
        )
        cls.model_app = ModelApp([
            prediction_service1,
            prediction_service2,
            prediction_service3,
            prediction_service4,
            prediction_service5,
            prediction_service_failing,
        ])
        cls.app = cls.model_app.app.test_client()

    def test_prediction_success(self):
        post_data1 = [
            {'id': 1, 'feature1': 2, 'feature2': 1},
            {'id': 2, 'feature1': 2, 'feature2': 2},
            {'id': 3, 'feature1': 2, 'feature2': 3},
            {'id': 4, 'feature1': 2, 'feature2': 4},
            {'id': 5, 'feature1': 2, 'feature2': 5},
        ]
        post_data2 = [
            {'id': 1, 'feature1': 10},
            {'id': 2, 'feature1': 10},
            {'id': 3, 'feature1':  1},
            {'id': 4, 'feature1':  3},
            {'id': 5, 'feature1':  3},
        ]
        post_data3 = {'id': 1, 'feature1': 5}
        actual1 = self.app.post('/a-model/v0/predict', data=json.dumps(post_data1))
        actual1 = json.loads(actual1.data)
        actual2 = self.app.post('/n/s/anotherModel/v1/prediction', data=json.dumps(post_data2))
        actual2 = json.loads(actual2.data)
        actual3 = self.app.post('/model-3/v0.0-alpha/prediction', data=json.dumps(post_data3))
        actual3 = json.loads(actual3.data)
        expected1 = {
            'request_id': 0,
            'model_context': {
                'model_name': 'a-model',
                'api_version': 'v0',
                'model_meta': {}
            },
            'predictions': [
                {'id': 1, 'prediction': 0},
                {'id': 2, 'prediction': -2},
                {'id': 3, 'prediction': -4},
                {'id': 4, 'prediction': -6},
                {'id': 5, 'prediction': -8},
            ]
        }
        expected2 = {
            'request_id': 1,
            'model_context': {
                'model_name': 'anotherModel',
                'api_version': 'v1',
                'model_meta': {}
            },
            'predictions': [
                {'id': 1, 'prediction': 10},
                {'id': 2, 'prediction': 11},
                {'id': 3, 'prediction': 3},
                {'id': 4, 'prediction': 6},
                {'id': 5, 'prediction': 7},
            ]
        }
        expected3 = {
            'request_id': 123,
            'model_context': {
                'model_name': 'model-3',
                'api_version': 'v0.0-alpha',
                'model_meta': {
                    'algorithm': 'randomforest',
                    'lasttrained': 1
                }
            },
            'predictions': {'id': 1, 'prediction': -5}
        }
        for key in ['model_context', 'predictions']:
            self.assertCountEqual(actual1[key], expected1[key])
            self.assertCountEqual(actual2[key], expected2[key])
            self.assertCountEqual(actual3[key], expected3[key])

    def test_prediction_bad_requests_400(self):
        actual = self.app.post('/a-model/v0/predict', data='cannot be parsed')
        self.assertTrue(actual.status_code, 400)
        expected_data = {
            'request_id': 123,
            'error': {
                'name': 'BadRequest',
                'messages': ['The browser (or proxy) sent a request that this server could not understand.'],
            }
        }
        actual_data = json.loads(actual.data)
        self.assertIn('request_id', actual_data)
        self.assertEqual(expected_data['error'], actual_data['error'])

    def test_asdkfj(self):
        # TODO: rename
        post_data2 = [{'id': 1, 'feature1': 2}, {'id': 2, 'feature1': 2}]
        resp = self.app.post('/model-3/v0.0-alpha/prediction', data=json.dumps(post_data2))
        print(resp.json)
        self.assertEqual(resp.status_code, 422)

    def test_prediction_bad_requests_422(self):
        # should be array when sent to model1
        post_data1 = {'id': 1, 'feature1': 2, 'feature2': 1}
        # should be single object when sent to model3
        post_data2 = [{'id': 1, 'feature1': 2}, {'id': 2, 'feature1': 2}]
        # missing model2 features
        post_data3 = [{'id': 1, 'feature2': 1},
                      {'id': 2, 'feature2': 2},
                      {'id': 3, 'feature2': 3}]
        # contains nulls
        post_data4 = {'id': 1, 'feature1': None}
        # contains nulls
        post_data5 = [{'id': 1, 'feature1': 1, 'feature2': 1},
                      {'id': 1, 'feature1': 1}]
        # contains 0 values that don't pass user check
        post_data6 = [{'id': 1, 'feature1': 1, 'feature2': 1},
                      {'id': 1, 'feature1': 0, 'feature2': 1}]
        actuals = [
            self.app.post('/a-model/v0/predict', data=json.dumps(post_data1)),
            self.app.post('/model-3/v0.0-alpha/prediction', data=json.dumps(post_data2)),
            self.app.post('/n/s/anotherModel/v1/prediction', data=json.dumps(post_data3)),
            self.app.post('/model-3/v0.0-alpha/prediction', data=json.dumps(post_data4)),
            self.app.post('/a-model/v0/predict', data=json.dumps(post_data5)),
            self.app.post('/n/s/anotherModel/v1/prediction', data=json.dumps(post_data6)),
        ]
        # check status codes
        self.assertTrue(all(actual.status_code == 422 for actual in actuals))
        # check that all objects have error key
        self.assertTrue(all('error' in json.loads(actual.data) for actual in actuals))
        # check response values
        expected_error_values = [
            {'name': 'UnprocessableEntity'},
            {'name': 'UnprocessableEntity'},
            {'name': 'UnprocessableEntity'},
            {'name': 'UnprocessableEntity'},
            {'name': 'UnprocessableEntity'},
            {'name': 'UnprocessableEntity'},
            {'name': 'BadRequest'},
        ]
        for actual, expectations in zip(actuals, expected_error_values):
            actual_error_obj = json.loads(actual.data)['error']
            for key, value in expectations.items():
                self.assertEqual(actual_error_obj[key], value)
        # check that model context data is passed into responses
        expected_model_context_values = [
            {'model_name': 'a-model', 'api_version': 'v0'},
            {'model_name': 'model-3', 'api_version': 'v0.0-alpha',
             'model_meta': {'algorithm': 'randomforest', 'lasttrained': 1}},
            {'model_name': 'anotherModel', 'api_version': 'v1'},
            {'model_name': 'model-3', 'api_version': 'v0.0-alpha',
             'model_meta': {'algorithm': 'randomforest', 'lasttrained': 1}},
            {'model_name': 'a-model', 'api_version': 'v0'},
            {'model_name': 'anotherModel', 'api_version': 'v1'},
        ]
        for actual, expectations in zip(actuals, expected_model_context_values):
            actual_error_obj = json.loads(actual.data)
            for key, value in expectations.items():
                self.assertEqual(actual_error_obj['model_context'][key], value)

    def test_prediction_response_valid_schema(self):
        # test that validation passes for valid response
        post_data4 = {'id': 1, 'feature1': 5}
        actual4 = self.app.post('/model-4/v0.0-alpha/prediction', data=json.dumps(post_data4))
        actual4 = json.loads(actual4.data)
        expected4 = {
            'request_id': '123',
            'model_context': {
                'model_name': 'model-4',
                'api_version': 'v0.0-alpha',
                'model_meta': {
                    'algorithm': 'randomforest',
                    'lasttrained': 1
                }
            },
            'predictions': {'id': 1, 'prediction': -5}
        }
        self.assertEqual(actual4, expected4)

    def test_prediction_response_invalid_schema(self):
        # test that validation fails for invalid response
        post_data5 = {'id': 1, 'feature1': 5}
        actual5 = self.app.post('/model-5/v0.0-alpha/prediction', data=json.dumps(post_data5))
        actual5 = json.loads(actual5.data)
        self.assertRegex(
            actual5['error']['messages'][0],
            'Schema validation failed: data.predictions.prediction must be bigger')

    def test_get_prediction_endpoints(self):
        resp1 = self.app.get('/a-model/v0/predict')
        resp2 = self.app.get('/model-3/v0.0-alpha/prediction')
        resp3 = self.app.get('/n/s/anotherModel/v1/prediction')
        self.assertEqual(resp1.status_code, 200)
        self.assertEqual(resp2.status_code, 200)
        self.assertEqual(resp3.status_code, 200)

    @mock.patch('porter.services.BaseService._log_error')
    def test_prediction_service_that_fails(self, mock__log_error):
        # test how unhandled exceptions are treated
        resp = self.app.post('/failing-model/v1/fail', data='{}')
        self.assertEqual(resp.status_code, 500)
        self.assertEqual(resp.json['error']['messages'], ['Could not serve model results successfully.'])
        # make sure the original exception was logged
        mock__log_error.assert_called_with(self.prediction_service_error)

class TestOpenAPIDocumentationDefaults(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        service1 = PredictionService(
            name='service1',
            api_version='2',
            model=None,  # we're not going to make calls for predictions here
            feature_schema=sc.Object(properties={'a': sc.Integer(), 'b': sc.Integer(), 'c': sc.Number()})
        )
        service1 = PredictionService(
            namespace='ns',
            name='service2',
            api_version='1',
            model=None,  # we're not going to make calls for predictions here
            feature_schema=sc.Object(properties={'a': sc.Integer(), 'b': sc.Integer()})
        )

    def test_docs_url(self):
        model_app = ModelApp([], expose_docs=True)
        app = model_app.app.test_client()
        resp = app.get('/docs/')
        self.assertEqual(resp.status_code, 200)

    def test_can_serve_swagger_files(self):
        model_app = ModelApp([], expose_docs=True)
        app = model_app.app.test_client()
        files = [
            'favicon-16x16.png',
            'favicon-32x32.png',
            'index.html',
            'oauth2-redirect.html',
            'swagger-ui-bundle.js',
            'swagger-ui-bundle.js.map',
            'swagger-ui-standalone-preset.js',
            'swagger-ui-standalone-preset.js.map',
            'swagger-ui.css',
            'swagger-ui.css.map',
            'swagger-ui.js',
            'swagger-ui.js.map',
            'swagger_template.html',
        ]
        for filename in files:
            resp = app.get(f'/assets/swagger-ui/{filename}')
            self.assertEqual(resp.status_code, 200)

    def test_docs_prefix(self):
        model_app = ModelApp([], docs_prefix='/my/docs/ns', expose_docs=True)
        app = model_app.app.test_client()
        resp = app.get('/my/docs/ns/docs/')
        self.assertEqual(resp.status_code, 200)

        files = [
            'favicon-16x16.png',
            'favicon-32x32.png',
            'index.html',
            'oauth2-redirect.html',
            'swagger-ui-bundle.js',
            'swagger-ui-bundle.js.map',
            'swagger-ui-standalone-preset.js',
            'swagger-ui-standalone-preset.js.map',
            'swagger-ui.css',
            'swagger-ui.css.map',
            'swagger-ui.js',
            'swagger-ui.js.map',
            'swagger_template.html',
        ]
        for filename in files:
            resp = app.get(f'/my/docs/ns/assets/swagger-ui/{filename}')
            self.assertEqual(resp.status_code, 200)

    def test_docs_paths(self):
        class SC(BaseService):
            def serve(self): pass
            def status(self): pass
            action = 'endpoint'

        service = SC(name='the', api_version='v1')
        model_app = ModelApp([service], expose_docs=True)
        docs_json = model_app.docs_json
        expected_keys = ['openapi', 'info', 'paths', 'components']
        self.assertEqual(set(docs_json.keys()), set(expected_keys))
        expected_paths = ['/the/v1/endpoint', '/-/alive', '/-/ready']
        self.assertEqual(set(docs_json['paths'].keys()), set(expected_paths))

@mock.patch('porter.responses.api.request_id', lambda: '123')
class TestAppHealthChecks(unittest.TestCase):
    def test_liveness_live(self):
        model_app = ModelApp([])
        app = model_app.app.test_client()
        resp = app.get('/-/alive')
        self.assertEqual(resp.status_code, 200)

    def test_readiness_not_ready1(self):
        model_app = ModelApp([])
        app = model_app.app.test_client()
        resp_alive = app.get('/-/alive')
        resp_ready = app.get('/-/ready')
        expected_data = {
            'request_id': '123',
            'porter_version': __version__,
            'deployed_on': cn.HEALTH_CHECK_VALUES.DEPLOYED_ON,
            'services': {},
            'app_meta': {
                'description': '

(porter v0.15.4)

',
                'expose_docs': False,
                'name': None,
                'version': None},
        }
        self.assertEqual(resp_alive.status_code, 200)
        self.assertEqual(resp_ready.status_code, 503)
        alive_response = json.loads(resp_alive.data)
        ready_respnose = json.loads(resp_ready.data)
        self.assertEqual(alive_response, expected_data)
        self.assertEqual(ready_respnose, expected_data)
        # make sure the defined schema matches reality
        sc.health_check.validate(alive_response)  # should not raise exception
        sc.health_check.validate(ready_respnose)  # should not raise exception

    @mock.patch('porter.services.PredictionService.__init__')
    def test_readiness_not_ready2(self, mock_init):
        mock_init.return_value = None
        class C(PredictionService):
            status = 'NOTREADY'
            request_schemas = {}
            response_schemas = {}
        svc = C()
        svc.name  = 'foo'
        svc.api_version = 'bar'
        svc.meta = {'k': 1}
        svc.id = 'foo:bar'
        svc.endpoint = '/foo/bar/'
        svc.route_kwargs = {}

        model_app = ModelApp([svc])
        app = model_app.app.test_client()

        resp_alive = app.get('/-/alive')
        resp_ready = app.get('/-/ready')
        expected_data = {
            'request_id': '123',
            'porter_version': __version__,
            'deployed_on': cn.HEALTH_CHECK_VALUES.DEPLOYED_ON,
            'services': {
                'foo:bar': {
                    'status': 'NOTREADY',
                    'endpoint': '/foo/bar/',
                    'model_context': {
                        'model_name': 'foo',
                        'api_version': 'bar',
                        'model_meta': {'k': 1}
                    }
                }
            },
            'app_meta': {
                'description': '

(porter v0.15.4)

',
                'expose_docs': False,
                'name': None,
                'version': None},
        }
        self.assertEqual(resp_alive.status_code, 200)
        self.assertEqual(resp_ready.status_code, 503)
        alive_response = json.loads(resp_alive.data)
        ready_respnose = json.loads(resp_ready.data)
        self.assertEqual(alive_response, expected_data)
        self.assertEqual(ready_respnose, expected_data)
        # make sure the defined schema matches reality
        sc.health_check.validate(alive_response)  # should not raise exception
        sc.health_check.validate(ready_respnose)  # should not raise exception

    @mock.patch('porter.services.PredictionService.__init__')
    def test_readiness_ready_ready1(self, mock_init):
        mock_init.return_value = None
        svc = PredictionService()
        svc.name = 'model1'
        svc.api_version = '1.0.0'
        svc.id = 'model1'
        svc.endpoint = '/model1/1.0.0/prediction'
        svc.meta = {'foo': 1, 'bar': 2}
        svc.response_schemas = {}
        svc.request_schemas = {}

        model_app = ModelApp([svc])
        app = model_app.app.test_client()

        resp_alive = app.get('/-/alive')
        resp_ready = app.get('/-/ready')
        expected_data = {
            'request_id': '123',
            'porter_version': __version__,
            'deployed_on': cn.HEALTH_CHECK_VALUES.DEPLOYED_ON,
            'app_meta': {
                'description': '

(porter v0.15.4)

',
                'expose_docs': False,
                'name': None,
                'version': None},
            'services': {
                'model1': {
                    'status': 'READY',
                    'endpoint': '/model1/1.0.0/prediction',
                    'model_context': {
                        'model_name': 'model1',
                        'api_version': '1.0.0',
                        'model_meta': {'foo': 1, 'bar': 2}
                    }
                }
            }
        }
        self.assertEqual(resp_alive.status_code, 200)
        self.assertEqual(resp_ready.status_code, 200)
        alive_response = json.loads(resp_alive.data)
        ready_respnose = json.loads(resp_ready.data)
        self.assertEqual(alive_response, expected_data)
        self.assertEqual(ready_respnose, expected_data)
        # make sure the defined schema matches reality
        sc.health_check.validate(alive_response)  # should not raise exception
        sc.health_check.validate(ready_respnose)  # should not raise exception

    @mock.patch('porter.services.PredictionService.__init__')
    def test_readiness_ready_ready2(self, mock_init):
        mock_init.return_value = None
        svc1 = PredictionService()
        svc1.name = 'model1'
        svc1.api_version = '1.0.0'
        svc1.id = 'model1:1.0.0'
        svc1.endpoint = '/model1/1.0.0/prediction'
        svc1.meta = {'foo': 1, 'bar': 2}
        svc1.response_schemas = {}
        svc1.request_schemas = {}
        svc2 = PredictionService()
        svc2.name = 'model2'
        svc2.api_version = 'v0'
        svc2.id = 'model2:v0'
        svc2.endpoint = '/model2/v0/prediction'
        svc2.meta = {'foo': 1}
        svc2.response_schemas = {}
        svc2.request_schemas = {}

        model_app = ModelApp([svc1, svc2])
        app = model_app.app.test_client()

        resp_alive = app.get('/-/alive')
        resp_ready = app.get('/-/ready')
        expected_data = {
            'request_id': '123',
            'porter_version': __version__,
            'deployed_on': cn.HEALTH_CHECK_VALUES.DEPLOYED_ON,
            'app_meta': {
                'description': '

(porter v0.15.4)

',
                'expose_docs': False,
                'name': None,
                'version': None},
            'services': {
                'model1:1.0.0': {
                    'status': 'READY',
                    'endpoint': '/model1/1.0.0/prediction',
                    'model_context': {
                        'model_name': 'model1',
                        'api_version': '1.0.0',
                        'model_meta': {'foo': 1, 'bar': 2},
                    }
                },
                'model2:v0': {
                    'status': 'READY',
                    'endpoint': '/model2/v0/prediction',
                    'model_context': {
                        'model_name': 'model2',
                        'api_version': 'v0',
                        'model_meta': {'foo': 1},
                    }
                }
            }
        }
        self.assertEqual(resp_alive.status_code, 200)
        self.assertEqual(resp_ready.status_code, 200)
        alive_response = json.loads(resp_alive.data)
        ready_respnose = json.loads(resp_ready.data)
        self.assertEqual(alive_response, expected_data)
        self.assertEqual(ready_respnose, expected_data)
        # make sure the defined schema matches reality
        sc.health_check.validate(alive_response)  # should not raise exception
        sc.health_check.validate(ready_respnose)  # should not raise exception

    def test_root(self):
        model_app = ModelApp([])
        app = model_app.app.test_client()
        resp = app.get('/')
        self.assertEqual(resp.status_code, 200)

        model_app = ModelApp([], expose_docs=True)
        app = model_app.app.test_client()
        resp = app.get('/')
        self.assertEqual(resp.status_code, 302)

@mock.patch('porter.services.porter_responses.api.request_id', lambda: 123)
@mock.patch('porter.services.cf.return_message_on_error', True)
@mock.patch('porter.services.cf.return_traceback_on_error', True)
@mock.patch('porter.services.cf.return_user_data_on_error', True)
class TestAppErrorHandling(unittest.TestCase):
    @classmethod
    @mock.patch('porter.services.BaseService._ids', set())
    def setUpClass(cls):
        # DO NOT set app.testing = True here
        # doing so *disables* error handling in the application and instead
        # passes errors on to the test client (in our case, instances of
        # unittest.TestCase).
        # In this class we actually want to test the applications error handling
        # and thus do not set this attribute.
        # See, http://flask.pocoo.org/docs/0.12/api/#flask.Flask.test_client

        prediction_service = PredictionService(name='failing-model',
            api_version='B', model=None, meta={'1': 'one', 'two': 2})

        cls.model_app = ModelApp([prediction_service])
        flask_app = cls.model_app.app
        @flask_app.route('/test-error-handling/', methods=['POST'])
        def test_error():
            flask.request.get_json(force=True)
            raise Exception('exceptional testing of exceptions')
        cls.app_test_client = flask_app.test_client()

    def test_bad_request(self):
        # note data is unreadable JSON, thus a BadRequest
        resp = self.app_test_client.post('/test-error-handling/', data='bad data')
        actual = json.loads(resp.data)
        expected = {
            'request_id': 123,
            'error': {
                'name': 'BadRequest',
                'messages': ['The browser (or proxy) sent a request that this server could not understand.'],
                # user_data is None when not passed or unreadable
                'user_data': None,
                'traceback': re.compile(r'.*raise\sBadRequest.*')
            }
        }
        self.assertEqual(resp.status_code, 400)
        self.assertEqual(actual['error']['name'], expected['error']['name'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error']['messages'], expected['error']['messages'])
        self.assertEqual(actual['error']['user_data'], expected['error']['user_data'])
        self.assertTrue(expected['error']['traceback'].search(actual['error']['traceback']))

    def test_not_found(self):
        resp = self.app_test_client.get('/not-found/')
        actual = json.loads(resp.data)
        expected = {
            'request_id': 123,
            'error': {
                'name': 'NotFound',
                'messages': ['The requested URL was not found on the server. '
                             'If you entered the URL manually please check your spelling and '
                             'try again.'],
                'user_data': None,
                'traceback': re.compile(r'.*raise\sNotFound.*')
            }
        }
        self.assertEqual(resp.status_code, 404)
        self.assertEqual(actual['error']['name'], expected['error']['name'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error']['messages'], expected['error']['messages'])
        self.assertEqual(actual['error']['user_data'], expected['error']['user_data'])
        self.assertTrue(expected['error']['traceback'].search(actual['error']['traceback']))

    def test_method_not_allowed(self):
        resp = self.app_test_client.get('/test-error-handling/')
        actual = json.loads(resp.data)
        expected = {
            'request_id': 123,
            'error': {
                'name': 'MethodNotAllowed',
                'messages': ['The method is not allowed for the requested URL.'],
                'user_data': None,
                'traceback': re.compile(r'.*raise\sMethodNotAllowed.*')
            }
        }
        self.assertEqual(resp.status_code, 405)
        self.assertEqual(actual['error']['name'], expected['error']['name'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error']['messages'], expected['error']['messages'])
        self.assertEqual(actual['error']['user_data'], expected['error']['user_data'])
        self.assertTrue(expected['error']['traceback'].search(actual['error']['traceback']))

    def test_internal_server_error(self):
        user_data = {"valid": "json"}
        resp = self.app_test_client.post('/test-error-handling/', data=json.dumps(user_data))
        actual = json.loads(resp.data)
        expected = {
            'request_id': 123,
            'error': {
                'name': 'Exception',
                'messages': ['exceptional testing of exceptions'],
                'user_data': user_data,
                'traceback': re.compile(r'.*raise\sException')
            }
        }
        self.assertEqual(resp.status_code, 500)
        self.assertEqual(actual['error']['name'], expected['error']['name'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error']['messages'], expected['error']['messages'])
        self.assertEqual(actual['error']['user_data'], expected['error']['user_data'])
        self.assertTrue(expected['error']['traceback'].search(actual['error']['traceback']))

    @mock.patch('porter.services.PredictionService._predict')
    def test_prediction_fails(self, mock__predict):
        mock__predict.side_effect = Exception('testing a failing model')
        user_data = {'some test': 'data'}
        resp = self.app_test_client.post('/failing-model/B/prediction', data=json.dumps(user_data))
        actual = json.loads(resp.data)
        expected = {
            'model_context': {
                'model_name': 'failing-model',
                'api_version': 'B',
                'model_meta': {
                    '1': 'one',
                    'two': 2
                },
            },
            'request_id': 123,
            'error': {
                'name': 'InternalServerError',
                'messages': ['Could not serve model results successfully.'],
                'user_data': user_data,
                'traceback': re.compile(r".*testing\sa\sfailing\smodel.*"),
            }
        }
        self.assertEqual(resp.status_code, 500)
        self.assertEqual(actual['model_context']['model_name'], expected['model_context']['model_name'])
        self.assertEqual(actual['model_context']['api_version'], expected['model_context']['api_version'])
        self.assertEqual(actual['model_context']['model_meta']['1'], expected['model_context']['model_meta']['1'])
        self.assertEqual(actual['model_context']['model_meta']['two'], expected['model_context']['model_meta']['two'])
        self.assertEqual(actual['error']['name'], expected['error']['name'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error']['messages'], expected['error']['messages'])
        self.assertEqual(actual['error']['user_data'], expected['error']['user_data'])
        self.assertTrue(expected['error']['traceback'].search(actual['error']['traceback']))

@mock.patch('porter.services.porter_responses.api.request_id', lambda: 123)
@mock.patch('porter.services.cf.return_message_on_error', True)
@mock.patch('porter.services.cf.return_traceback_on_error', False)
@mock.patch('porter.services.cf.return_user_data_on_error', False)
class TestAppErrorHandlingCustomKeys(unittest.TestCase):
    @classmethod
    @mock.patch('porter.services.BaseService._ids', set())
    def setUpClass(cls):
        # DO NOT set app.testing = True here
        # doing so *disables* error handling in the application and instead
        # passes errors on to the test client (in our case, instances of
        # unittest.TestCase).
        # In this class we actually want to test the applications error handling
        # and thus do not set this attribute.
        # See, http://flask.pocoo.org/docs/0.12/api/#flask.Flask.test_client

        prediction_service = PredictionService(name='failing-model',
            api_version='B', model=None, meta={'1': 'one', 'two': 2})

        cls.model_app = ModelApp([prediction_service])

        flask_app = cls.model_app.app
        @flask_app.route('/test-error-handling/', methods=['POST'])
        def test_error():
            flask.request.get_json(force=True)
            raise Exception('exceptional testing of exceptions')
        cls.app_test_client = flask_app.test_client()

    @mock.patch('porter.services.PredictionService._predict')
    def test(self, mock__predict):
        mock__predict.side_effect = Exception('testing a failing model')
        user_data = {'some test': 'data'}
        resp = self.app_test_client.post('/failing-model/B/prediction', data=json.dumps(user_data))
        actual = json.loads(resp.data)
        expected = {
            'model_context': {
                'model_name': 'failing-model',
                'api_version': 'B',
                'model_meta': {
                    '1': 'one',
                    'two': 2
                }
            },
            'request_id': 123,
            'error': {
                'name': 'InternalServerError',
                'messages': ['Could not serve model results successfully.'],
            }
        }
        self.assertEqual(resp.status_code, 500)
        self.assertEqual(actual['model_context'], expected['model_context'])
        self.assertEqual(actual['model_context']['model_meta'], expected['model_context']['model_meta'])
        self.assertEqual(actual['error'], expected['error'])
        self.assertEqual(actual['request_id'], expected['request_id'])
        self.assertEqual(actual['error'], expected['error'])

if __name__ == '__main__':
    unittest.main()


import numpy as np
import dict_helpers
from sklearn.preprocessing import normalize
import efficient_sparse_coding

dict_size   = 512;          # dictionary size
lambda_     = 0.15;         # sparsity regularization
patch_size  = 3;            # image patch size
num_patch   = 10000;       # number of patches to sample,say 100,000 from 30 images
upscale     = 2;            # upscaling factor
iteration_num = 10;          # number of alternating iterations, say 40
img_path = 'ECE551/551_Data/Training/t'
img_type = 'bmp'
dic_path = 'ECE551/551_Data/Dictionary'

def train_coupled_dict(Xh,Xl,dict_size,lambda_,iteration_num):
    hdim,ldim = Xh.shape[1], Xl.shape[1]
    Xh = normalize(Xh,norm='l2',axis=1) # normalize so that each patch (row) have unit norm
    Xl = normalize(Xl,norm='l2',axis=1)
    X = np.hstack((np.sqrt(hdim)*Xh, np.sqrt(ldim)*Xl))
    X = normalize(X,norm='l2',axis=1) # dim here is: num_patch * (hdim+ldim)
    X = X.T # dim here is: (hdim+ldim) * num_patch
    # now min
    D = efficient_sparse_coding.dict_training(X,dict_size,lambda_,iteration_num)
    Dh = D[0:hdim,:]
    Dl = D[hdim:,:]
    # returned dict is not normalized
    # and of size hdim* num_patch and ldim* num_patch
    return Dh,Dl

Xh,Xl = dict_helpers.rnd_sample_patch(img_path, img_type, patch_size, num_patch, upscale)
Xh,Xl = dict_helpers.patch_pruning(Xh,Xl)
Dh,Dl = train_coupled_dict(Xh,Xl,dict_size,lambda_,iteration_num)

dict_path = dic_path+'/D_'+str(dict_size)+'_'+str(lambda_)+'_'+str(patch_size)+'_'+str(upscale)+'_Dh.out'
np.savetxt(dict_path, Dh)
dict_path = dic_path+'/D_'+str(dict_size)+'_'+str(lambda_)+'_'+str(patch_size)+'_'+str(upscale)+'_Dl.out'
np.savetxt(dict_path, Dl)


import os
import cv2
import numpy as np

class Frame:
    def __init__(self):
        pass

    @staticmethod
    def create_dir(input_path, output_path):
        name = input_path.split("/")[-1].split(".")[0]
        save_path = os.path.join(output_path, name)
        try:
            if not os.path.exists(save_path):
                os.makedirs(save_path)
        except OSError:
            print(f"ERROR: creating directory with name {save_path}")
        return save_path, name

    @staticmethod
    def save_frame(save_path, name, gap, frame, idx):
        if idx == 0:
            cv2.imwrite(f"{save_path}/{name}_{idx}_.jpg", frame)
        else:
            if idx % gap == 0:
                cv2.imwrite(f"{save_path}/{name}_{idx}_.jpg", frame)

    @staticmethod
    def video_frame(video_path, save_dir, gap):
        cap = cv2.VideoCapture(video_path)
        idx = 0
        save_path, name = Frame.create_dir(video_path, save_dir)
        while True:
            ret, frame = cap.read()
            if ret:
                Frame.save_frame(save_path, name, gap, frame, idx)
            else:
                cap.release()
                break
            idx += 1

    @staticmethod
    def rescaleFrame(frame, scale=0.75):
        # images, video and live videos
        height = int(frame.shape[0] * scale)
        width = int(frame.shape[1] * scale)
        dimensions = (width, height)

        return cv2.resize(frame, dimensions, interpolation=cv2.INTER_AREA)

    @staticmethod
    def image_center(height, width):
        return [int(width / 2), int(height / 2)]

    @staticmethod
    def draw_image_center(image, height, width):
        start_point_horizontal = (0, int(height / 2))
        end_point_horizontal = (width, int(height / 2))

        cv2.line(image, start_point_horizontal, end_point_horizontal, (255, 0, 0), 1)

        start_point_vertical = (int(width / 2), 0)
        end_point_vertical = (int(width / 2), height)

        cv2.line(image, start_point_vertical, end_point_vertical, (255, 0, 0), 1)
        return image

    @staticmethod
    def draw_dist(frame, bbox_x_y_center, img_x_y_center, distance):
        i = 0
        for bb_center in bbox_x_y_center:
            cv2.line(frame, (img_x_y_center[0], img_x_y_center[1]), (bb_center[0], bb_center[1]), (255, 0, 0), 2)
            cv2.putText(frame, f'{distance[i]} m', (bb_center[0] + 10, bb_center[1]), cv2.FONT_HERSHEY_PLAIN, 1,
                        (255, 255, 255), 2)
            i += 1
        return frame

    @staticmethod
    def distance(bbox_x_y_center, img_x_y_center, GSD):
        distances = []
        img_x_y_center = np.array(img_x_y_center)

        for bb_center in bbox_x_y_center:
            bb_center = np.array((bb_center[0], bb_center[1]))
            dist_pix = np.linalg.norm(bb_center - img_x_y_center)  # valor em Pixel
            dist = round(dist_pix * GSD, 2)
            distances.append(dist)
        return distances

    @staticmethod
    def click_event(event, x, y, flags, params):
        # function to display the pixel coordinates
        # of the points clicked on the image  # ix, iy = [], []

        global ix, iy
        # checking for left mouse clicks
        if event == cv2.EVENT_LBUTTONDOWN:
            # displaying the coordinates
            # on the Shell
            print(x, ' ', y)
            ix.append(x), iy.append(y)
            print('dentro da funcao', ix, iy)

            # displaying the coordinates
            # on the image window
            font = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(frame, str(x) + ',' +
                        str(y), (x, y), font,
                        1, (255, 0, 0), 2)
            cv2.imshow('image', frame)


# Data Structure: Stack Implementation (Using Doubly-Linked List)

class Node:

    def __init__(self, value, previous_=None, next_=None):
        """
        Initializes a Node, with a value, previous reference and next reference.

        :param value (any): Any value.
        :param previous_ (Node): Reference to the previous Node.
        :param next_ (Node): Reference to the next Node.
        """
        self.value = value
        self.previous = previous_
        self.next = next_

class Stack:
    """
    A class to represent a Stack.

    ...
    Attributes
    ----------
    head: Node
        hold the last element pushed onto the stack.
    tail: Node
        hold the first element pushed onto the stack.
    traverse: Node
        hold the current element traversed.

    Methods
    -------
    push(value: Node)
        Adds an element to the start of the Stack. (O(1))
    pop()
        Removes an element from the start of the Stack. (O(1))
    peek(last: Boolean)
        Look at the top / last element of the Stack. (O(1))
    traversal(back: Boolean)
        Traverse the stack, like a browsing session. (O(1))
    print_links()
        :returns a string showing a Node's value, it's previous value (if any), it's next value (if any).
    __print_helper_links(head: Node)
        A helper function for print_links()
    """

    def __init__(self, head=None, tail=None):
        self.head = head
        self.tail = tail
        self.traverse = self.head

    def push(self, value):
        node = Node(value)

        # Case 1: First Element in Stack
        if not self.head:
            self.head = node
            self.tail = node

        # Case 2: More than 1 Element in Stack
        elif self.head:
            self.head.previous = node
            node.next, self.head = self.head, node
            self.traverse = node

    def pop(self):

        # Case 1: No Elements
        if not self.head:
            raise IndexError("Stack is empty.")

        # Case 2: Only 1 Element in the Stack
        elif not self.head.next:
            self.head, self.tail, self.traverse = None, None, None

        # Case 3: More than 1 Element in Stack
        else:
            self.head, self.head.previous = self.head.next, None
            self.traverse = self.head

    def peek(self, last=False):

        # If Stack has at-least 1 element.
        if self.head:

            # Peek: Oldest Element
            if last:
                return self.tail.value

            # Peek: Latest Element
            elif not last:
                return self.head.value

        # If Stack is Empty.
        raise IndexError("Stack is empty.")

    def traversal(self, back=True):

        # If Stack has at-least 1 element.
        if self.head:

            # To traverse backwards / downwards (next)
            if back:
                if self.traverse.next:
                    self.traverse = self.traverse.next
                    return self.traverse.value

                return "No backwards traversals possible."

            # To traverse forwards / upwards (previous)
            if not back:
                if self.traverse.previous:
                    self.traverse = self.traverse.previous
                    return self.traverse.value

                return "No forward traversals possible."

        # If Stack is Empty.
        raise IndexError("Stack is empty.")

    def print_links(self):
        if not self.head:
            raise IndexError("Stack is empty.")

        else:
            return self.__print_helper_links(self.head)

    def __print_helper_links(self, head):

        # Base Case:
        if not head.next:
            return F"Value:({str(head.value)})" \
                   + F" Previous: {head.previous.value if head.previous else head.previous} |" \
                     F" Next: {head.next.value if head.next else head.next}"

        else:
            return F"Value:({str(head.value)})" + \
                   F" Previous: {head.previous.value if head.previous else head.previous} |" \
                   F" Next: {head.next.value} " + \
                   " <-> " + self.__print_helper_links(head.next)

if __name__ == "__main__":

    # Initialize a Stack Object.
    stack = Stack()

    # Push Elements onto the Stack.
    stack.push(1)  # 1
    stack.push(2)  # 2 <--> 1
    stack.push(3)  # 3 <--> 2 <--> 1

    # Pop Elements from the Stack.
    stack.pop()  # 2 <--> 1

    # Traverse our Stack.
    print(stack.traversal(back=True))   # 1
    print(stack.traversal(back=False))  # 2

    # Print our Stack (with Links)
    print(stack.print_links())


import asyncio
import time

from enum import Enum, auto
from random import choice

start_time = time.time()

class Action(Enum):
    HIGHKICK = auto()
    LOWKICK = auto()
    HIGHBLOCK = auto()
    LOWBLOCK = auto()

class Agent:
    def __init__(self):
        self.__aiter__()

    def __aiter__(self, health=5):
        self.health = health
        self.actions = list(Action)
        return self

    async def __anext__(self):
        return choice(self.actions)

    async def act(self):
        return await self.__anext__()

class Neo:

    action = None

    async def fight(self):
        agents = [Agent() for _ in range(10)]

        while agents:
            index = choice([0, len(agents) - 1])
            agent = agents[index]
            reply = asyncio.create_task(self.reply(agent))
            agent_action = await reply
            if self.action == Action.LOWKICK or self.action == Action.HIGHKICK:
                agent = agent.__aiter__(agent.health - 1)
            print({'Agent': agent_action.name, 'Neo': self.action.name, 'Agent Health': agent.health})
            if agent.health == 0:
                agents.pop(index)
        print('Neo wins')
        print("--- %s seconds ---" % (time.time() - start_time))

    async def reply(self, agent):
        action = await agent.act()
        if action == Action.HIGHKICK:
            self.action = Action.HIGHBLOCK
        if action == Action.HIGHBLOCK:
            self.action = Action.LOWKICK
        if action == Action.LOWKICK:
            self.action = Action.LOWBLOCK
        if action == Action.LOWBLOCK:
            self.action = Action.HIGHKICK
        return action

if __name__ == "__main__":
    neo = Neo()
    asyncio.run(neo.fight())


RaceHours = int(input("Insert race time hours: "))
RaceMinutes = int(input("Insert race time minutes: "))
RaceSeconds = int(input("Insert race time seconds: "))

PersonalBestTime = int(input("Insert your personal best time (in seconds): "))

RaceTime = RaceSeconds + 60 * (RaceMinutes + 60 * RaceHours)

print("Race time in seconds: {}".format(RaceTime))

if RaceTime < PersonalBestTime:
    print("Personal best time is unchanged")
elif RaceTime > PersonalBestTime:
    print("New personal best time")
else:
    print("Equals personal best time")


import folium
import pandas
from platform import system
from subprocess import call, DEVNULL
from datetime import datetime

# DEVNULL is used to supress output of ping command.
def ping_to_server(host):
    if system().lower() == 'windows':
        command = ['ping', '-n', '2', host]
    else:
        command = ['ping', '-c', '2', host]
    return call(command, stdout=DEVNULL) == 0

def pinpoint(color, latitude, longitude, plc, srv_name):
    if color == 'red':
        pop_up_msg = r""+srv_name+"
  Down At:"+str(datetime.now())+""
    else:
        pop_up_msg = r""+srv_name+""

    return folium.Marker([latitude, longitude], popup=pop_up_msg, tooltip=plc,
                         icon=folium.Icon(color=color))

def add_markers(feature_grp, lat, lon, place, server):
    for lt, ln, plc, srv in zip(lat, lon, place, server):
        # Pinging to servers and adding Circle Marker on Map.
        if ping_to_server(srv):
            feature_grp.add_child(pinpoint('green', lt, ln, plc, srv))
        else:
            feature_grp.add_child(pinpoint('red', lt, ln, plc, srv))

def draw_map(lat, lon, place, server):
    # Creating Map.
    worldmap = folium.Map(tiles="OpenStreetMap", width=1100, height=600,
                          zoom_start=7, zoom_control=True)
    # Add feature group.
    fg = folium.FeatureGroup(name="locations")
    add_markers(fg, lat, lon, place, server)
    worldmap.add_child(fg)
    worldmap.save("C:/Users/91976/PycharmProjects/FlaskPractice/templates/latitude-longitute.html")

def load_data():
    # Read file and retrieve latitude, longitude, location, server name.
    data = pandas.read_csv("server-locations.txt")
    lat_f = list(data["latitude"])
    lon_f = list(data["longitude"])
    place_f = list(data["place_name"])
    server_f = list(data["server_name"])
    return (lat_f, lon_f, place_f, server_f)

def render_map():
    lat, lon, place, server = load_data()
    draw_map(lat, lon, place, server)


import random
def gamewin(comp , you):
# all possiblity of water(w)
    if comp == you:
        return None
    elif comp == "w":
        if you == "g":
            return False
        elif you == "s":
            return True
#all possiblity of snake(s)
    elif comp == "s":
        if you == "w":
            return False
        elif you == "g":
            return True
# all possiblity of gun(g)
    elif comp == "g":
        if you == "w":
            return True
        elif you == "s":
            return False
print("computer trun: snake(s) , water(w) , gun(g)?")
randno = random.randint(1,3)
if randno == 1:
    comp = 's'
elif randno == 2:
    comp = 'w'
elif randno == 3:
    comp = 'g'
you = input("your turn: snake(s) , water(w) , gun(g)?   ")
a = gamewin(comp , you)
print(f"computer choice: {comp}")
print(f"Your choice: {you}")
if a == None:
    print("Game is Tie")
elif a:
    print("you win")
else :
    print("computer win")


from django.shortcuts import render,HttpResponse
from your_recipes.models import Recipes
from django.conf.urls import url
import requests

# Create your views here.
def search_recipe(request):
    recipes=Recipes()
    search_result=[]
    search_result_api=[]
    username=request.GET['username']
    searched_recipe=request.GET['searched_recipe']

    response=requests.get('http://www.recipepuppy.com/api/?i='+searched_recipe+'&q=omelet&p=3')
    api_data=response.json()
    api_data_results=api_data['results']

    search=[_.title for _ in Recipes.objects.all().filter(title__icontains=searched_recipe)]
    for j in search:
        if (searched_recipe.lower() in j.lower()) or \
                (searched_recipe in [_.ingredients for _ in Recipes.objects.all().filter(ingredients__icontains=searched_recipe)]):
            for _ in (Recipes.objects.filter(title__icontains=searched_recipe)):
                search_result.append([_.id,_.title,_.ingredients,_.image])
            for _ in (Recipes.objects.filter(ingredients__icontains=searched_recipe)):
                search_result.append([_.id,_.title,_.ingredients,_.image])

    for _ in api_data_results:
        search_result_api.append([_["href"],_['title'],_['ingredients']])

    return render(request,'search_recipe/search_result.html',
                  {'search_result':search_result,'search_result_api':search_result_api,'username':username})

def recipe_detail(request,id):
    idd=id
    recipe=Recipes.objects.get(id=idd)
    return render(request,'search_recipe/recipe_detail.html',
                  {
                   'title':recipe.title,
                   'image':recipe.image,
                   'author_name':recipe.author_name,
                   'date_posted':recipe.date_posted,
                   'ingredients':recipe.ingredients,
                   'description':recipe.description})


#!/usr/bin/python3

import rospy
import tf2_ros as tf
from nav_msgs.msg import Odometry
from geometry_msgs.msg import Twist, Pose, Vector3, PointStamped
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
import numpy as np
import math
import tf.transformations as tft

# Global variables for object detection
green_detected = False
red_detected = False
red_direction = 0.0

# Callback for sonar data
def sonar_callback(msg, state):
    state['sonar_data'] = (msg.point.x, msg.point.y)

# Callback for odometry data
def odom_callback(msg, state):
    state['odom_data'] = msg.pose.pose

# Callback for image data
def image_callback(msg):
    global green_detected
    global red_detected
    global red_direction

    bridge = CvBridge()
    cv_image = bridge.imgmsg_to_cv2(msg, desired_encoding='bgr8')

    # Convert image to HSV
    hsv = cv2.cvtColor(cv_image, cv2.COLOR_BGR2HSV)

    # Define color range for green
    green_low = np.array([40, 50, 50])
    green_high = np.array([80, 255, 255])

    # Define color range for red
    red_low1 = np.array([0, 70, 50])
    red_high1 = np.array([10, 255, 255])
    red_low2 = np.array([170, 70, 50])
    red_high2 = np.array([180, 255, 255])

    # Threshold the image for green and red colors
    green_mask = cv2.inRange(hsv, green_low, green_high)
    red_mask1 = cv2.inRange(hsv, red_low1, red_high1)
    red_mask2 = cv2.inRange(hsv, red_low2, red_high2)
    red_mask = cv2.bitwise_or(red_mask1, red_mask2)

    # Find contours in the green and red masks
    green_contours, _ = cv2.findContours(green_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    red_contours, _ = cv2.findContours(red_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # Reset detection flags
    green_detected = False
    red_detected = False

    # If a green object is detected, set green_detected flag
    if len(green_contours) > 0:
        green_detected = True

    # If a red object is detected, and green is not, set red_detected flag
    elif len(red_contours) > 0 and not len(green_contours) > 0:
        red_detected = True

# Function to calculate angular velocity required for orientation
def orientar(state):
    if 'sonar_data' in state and 'odom_data' in state:
        sonar_data = state['sonar_data']
        odom_data = state['odom_data']

        # Extract position and orientation data from the odom message
        px = odom_data.position.x
        py = odom_data.position.y
        orientation = odom_data.orientation

        # Convert orientation to Euler angles and extract yaw angle
        quat = [orientation.x, orientation.y, orientation.z, orientation.w]
        _, _, yaw = tft.euler_from_quaternion(quat)

        # Extract sonar position data
        x_m= sonar_data[0]
        y_m= -sonar_data[1]

        rospy.loginfo(str(x_m)+ " : " +str(y_m))
        # Calculate target angle using cross product of two vectors
        target_angle = math.atan2(x_m, y_m)
        aerror = target_angle - yaw

        rospy.loginfo('yaw:'+ str(yaw) +'tangl: ' + str(target_angle)+ ' aer: '+str(aerror) )

        # Normalize angle error to -pi to pi range
        while aerror > math.pi:
            aerror -= 2 * math.pi
        while aerror < -math.pi:
            aerror += 2 * math.pi

        rospy.loginfo('aer after norm: '+ str(aerror))

        # Calculate angular velocity required for orientation
        vel_ang = aerror

        return vel_ang

def control_speed(state):
    #importa variavel de estado do sonar
    if 'sonar_data' in state:
        sonar_data = state['sonar_data']
        # extrai posição do sonar
        x_m= sonar_data[0]
        y_m= -sonar_data[1]

        #calcula distancia
        dist = math.sqrt(x_m**2 + y_m**2)

        #define distancia min e max
        min_dist = 2.0
        max_dist = 5.0

        speed_fator = (dist - min_dist) / (max_dist - min_dist)
        speed_fator = min(1.0, max(0.0, speed_fator)) #map de 0 a 1

        max_speed = 2.0
        min_speed = 0.0

        speed = (max_speed - min_speed) * speed_fator + min_speed

        return speed

def andar(state, pub, rate):
            twist = Twist()

            # Calculate angular velocity for orientation
            vel_ang = orientar(state)

            # Set angular velocity in twist message
            if vel_ang is not None:
                twist.angular.z = vel_ang * 4

            # Set linear velocity in twist message =
            speed = control_speed(state)
            if speed is not None:
                twist.linear.y = float(speed)
            else:
                twist.linear.y = 0.0

            # Publish twist message
            pub.publish(twist)

def main():
    # Initialize node
    rospy.init_node("algo")

    # Create state dictionary
    state = {}

    # Subscribe to sonar and odometry topics
    rospy.Subscriber("/sonar_data", PointStamped, sonar_callback, state)
    rospy.Subscriber("/odom", Odometry, odom_callback, state)
    rospy.Subscriber("/camera/image_raw", Image, image_callback)

    # Setup publisher for velocity commands
    pub = rospy.Publisher("/cmd_vel", Twist, queue_size=10)

    rate = rospy.Rate(30)

    # Main loop
    while not rospy.is_shutdown():
       if green_detected == True:
           andar(state, pub, rate)
       elif red_detected == True:
           #desviar
           pass
       elif red_detected == False and green_detected == False:
           andar(state, pub, rate)

if __name__ == "__main__":
    main()


import os
import urllib

from slave import recipe_api

class AndroidApi(recipe_api.RecipeApi):
  def __init__(self, **kwargs):
    super(AndroidApi, self).__init__(**kwargs)

  def get_config_defaults(self):
    return {
      'REVISION': self.m.properties.get('revision', '')
    }

  @property
  def internal_dir(self):
    assert self.c.INTERNAL, (
        'Attempt to get internal_dir, but not internal build')
    return self.m.path['checkout'].join(self.c.internal_dir_name)

  @property
  def out_path(self):
    return self.m.path['checkout'].join('out')

  @property
  def coverage_dir(self):
    return self.out_path.join(self.c.BUILD_CONFIG, 'coverage')

  def get_env(self):
    env = {
        'PATH': self.m.path.pathsep.join(map(str, [
                   self.m.path['checkout'].join('third_party', 'android_tools',
                                                'sdk', 'platform-tools'),
                   self.m.path['checkout'].join('build', 'android'),
                   '%(PATH)s']))
    }
    if self.c.adb_vendor_keys:
      env.update({'ADB_VENDOR_KEYS': self.c.adb_vendor_keys})
    return env

  def configure_from_properties(self, config_name, **kwargs):
    def set_property(prop, var):
      if prop in self.m.properties:
        if var in kwargs:
          assert kwargs[var] == self.m.properties[prop], (
              "Property/Config conflict: %s=%s but %s=%s", (
                  prop, self.m.properties[prop],
                  var, kwargs[var]))
        kwargs[var] = self.m.properties[prop]

    set_property('target', 'BUILD_CONFIG')
    set_property('internal', 'INTERNAL')
    set_property('repo_name', 'REPO_NAME')
    set_property('repo_url', 'REPO_URL')

    self.set_config(config_name, **kwargs)

  def make_zip_archive(self, step_name, archive_name, files=None,
                       preserve_paths=True, filters=None, **kwargs):
    """Creates and stores the archive file.

    Args:
      step_name: Name of the step.
      archive_name: Name of the archive file.
      files: If specified, only include files here instead of out/<target>.
      filters: List of globs to be included in the archive.
      preserve_paths: If True, files will be stored using the subdolders
        in the archive.
    """
    archive_args = ['--target', self.m.chromium.c.BUILD_CONFIG,
                    '--name', archive_name]

    # TODO(luqui): Clean up when these are covered by the external builders.
    if files:              # pragma: no cover
      archive_args.extend(['--files', ','.join(files)])
    if filters:
      archive_args.extend(['--filters', ','.join(filters)])
    if not preserve_paths: # pragma: no cover
      archive_args.append('--ignore-subfolder-names')

    self.m.python(
      step_name,
      str(self.m.path['build'].join(
          'scripts', 'slave', 'android', 'archive_build.py')),
      archive_args,
      infra_step=True,
      **kwargs
    )

  def init_and_sync(self):
    # TODO(sivachandra): Move the setting of the gclient spec below to an
    # internal config extension when they are supported by the recipe system.
    spec = self.m.gclient.make_config('android_bare')
    spec.target_os = ['android']
    s = spec.solutions[0]
    s.name = self.c.deps_dir
    s.url = self.c.REPO_URL
    s.custom_deps = self.c.gclient_custom_deps or {}
    s.deps_file = self.c.deps_file
    s.custom_vars = self.c.gclient_custom_vars or {}
    s.managed = self.c.managed
    s.revision = self.c.revision
    spec.revisions = self.c.revisions

    self.m.gclient.break_locks()
    result = self.m.bot_update.ensure_checkout(spec)
    if not result.json.output['did_run']:
      result = self.m.gclient.checkout(spec)

    # TODO(sivachandra): Manufacture gclient spec such that it contains "src"
    # solution + repo_name solution. Then checkout will be automatically
    # correctly set by gclient.checkout
    self.m.path['checkout'] = self.m.path['slave_build'].join('src')

    self.clean_local_files()

    return result

  def clean_local_files(self):
    target = self.c.BUILD_CONFIG
    debug_info_dumps = self.m.path['checkout'].join('out',
                                                    target,
                                                    'debug_info_dumps')
    test_logs = self.m.path['checkout'].join('out', target, 'test_logs')
    build_product = self.m.path['checkout'].join('out', 'build_product.zip')
    self.m.python.inline(
        'clean local files',
        """
          import shutil, sys, os
          shutil.rmtree(sys.argv[1], True)
          shutil.rmtree(sys.argv[2], True)
          try:
            os.remove(sys.argv[3])
          except OSError:
            pass
          for base, _dirs, files in os.walk(sys.argv[4]):
            for f in files:
              if f.endswith('.pyc'):
                os.remove(os.path.join(base, f))
        """,
        args=[debug_info_dumps, test_logs, build_product,
              self.m.path['checkout']],
        infra_step=True,
    )

  def run_tree_truth(self):
    # TODO(sivachandra): The downstream ToT builder will require
    # 'Show Revisions' step.
    repos = ['src', 'src-internal']
    if self.c.REPO_NAME not in repos:
      repos.append(self.c.REPO_NAME)
    # TODO(sivachandra): Disable subannottations after cleaning up
    # tree_truth.sh.
    self.m.step('tree truth steps',
                [self.m.path['checkout'].join('build', 'tree_truth.sh'),
                self.m.path['checkout']] + repos,
                allow_subannotations=False)

  def runhooks(self, extra_env={}):
    self.m.chromium.runhooks(
        env=dict(self.get_env().items() + extra_env.items()))

  def apply_svn_patch(self):
    # TODO(sivachandra): We should probably pull this into its own module
    # (maybe a 'tryserver' module) at some point.
    self.m.step(
        'apply_patch',
        [self.m.path['build'].join('scripts', 'slave', 'apply_svn_patch.py'),
         '-p', self.m.properties['patch_url'],
         '-r', self.internal_dir])

  def compile(self, **kwargs):
    assert 'env' not in kwargs, (
        "chromium_andoid compile clobbers env in keyword arguments")
    kwargs['env'] = self.get_env()
    self.m.chromium.compile(**kwargs)

  def findbugs(self, findbugs_options=[]):
    cmd = [self.m.path['checkout'].join('build', 'android', 'findbugs_diff.py')]
    cmd.extend(findbugs_options)

    if self.m.chromium.c.BUILD_CONFIG == 'Release':
      cmd.append('--release-build')

    self.m.step('findbugs', cmd, env=self.get_env())

    cmd = [self.m.path['checkout'].join('tools', 'android', 'findbugs_plugin',
               'test', 'run_findbugs_plugin_tests.py')]
    if self.m.chromium.c.BUILD_CONFIG == 'Release':
      cmd.append('--release-build')
    self.m.step('findbugs_tests', cmd, env=self.get_env())

  def git_number(self, **kwargs):
    return self.m.step(
        'git_number',
        [self.m.path['depot_tools'].join('git_number.py')],
        stdout = self.m.raw_io.output(),
        step_test_data=(
          lambda:
            self.m.raw_io.test_api.stream_output('3000\n')
        ),
        cwd=self.m.path['checkout'],
        infra_step=True,
        **kwargs)

  def check_webview_licenses(self):
    self.m.python(
        'check licenses',
        self.m.path['checkout'].join('android_webview',
                                     'tools',
                                     'webview_licenses.py'),
        args=['scan'],
        cwd=self.m.path['checkout'])

  def upload_build(self, bucket, path):
    archive_name = 'build_product.zip'

    zipfile = self.m.path['checkout'].join('out', archive_name)

    self.make_zip_archive(
      'zip_build_product',
      archive_name,
      preserve_paths=True,
      cwd=self.m.path['checkout']
    )

    self.m.gsutil.upload(
        name='upload_build_product',
        source=zipfile,
        bucket=bucket,
        dest=path)

  def download_build(self, bucket, path):
    zipfile = self.m.path['checkout'].join('out', 'build_product.zip')
    self.m.gsutil.download(
        name='download_build_product',
        bucket=bucket,
        source=path,
        dest=zipfile
    )
    self.m.step(
      'unzip_build_product',
      ['unzip', '-o', zipfile],
      cwd=self.m.path['checkout'],
      infra_step=True,
    )

  def spawn_logcat_monitor(self):
    self.m.step(
        'spawn_logcat_monitor',
        [self.m.path['build'].join('scripts', 'slave', 'daemonizer.py'),
         '--', self.c.cr_build_android.join('adb_logcat_monitor.py'),
         self.m.chromium.c.build_dir.join('logcat')],
        env=self.get_env(),
        infra_step=True)

  def detect_and_setup_devices(self, restart_usb=False, skip_wipe=False,
                               disable_location=False):
    self.device_status_check(restart_usb=restart_usb)
    self.provision_devices(
      skip_wipe=skip_wipe, disable_location=disable_location)

  def device_status_check(self, restart_usb=False, **kwargs):
    args = []
    if restart_usb:
      args = ['--restart-usb']

    try:
      self.m.step(
          'device_status_check',
          [self.m.path['checkout'].join('build', 'android', 'buildbot',
                                'bb_device_status_check.py')] + args,
          env=self.get_env(),
          infra_step=True,
          **kwargs)
    except self.m.step.InfraFailure as f:
      params = {
        'summary': ('Device Offline on %s %s' %
          (self.m.properties['mastername'], self.m.properties['slavename'])),
        'comment': ('Buildbot: %s\n(Please do not change any labels)' %
          self.m.properties['buildername']),
        'labels': 'Restrict-View-Google,OS-Android,Infra,Infra-Labs',
      }
      link = ('https://code.google.com/p/chromium/issues/entry?%s' %
        urllib.urlencode(params))
      f.result.presentation.links.update({
        'report a bug': link
      })
      raise

  def provision_devices(self, skip_wipe=False, disable_location=False,
                        **kwargs):
    args = ['-t', self.m.chromium.c.BUILD_CONFIG]
    if skip_wipe:
      args.append('--skip-wipe')
    if disable_location:
      args.append('--disable-location')
    self.m.python(
      'provision_devices',
      self.m.path['checkout'].join(
          'build', 'android', 'provision_devices.py'),
      args=args,
      env=self.get_env(),
      infra_step=True,
      **kwargs)

  def adb_install_apk(self, apk, apk_package):
    install_cmd = [
        self.m.path['checkout'].join('build',
                                     'android',
                                     'adb_install_apk.py'),
        '--apk', apk,
        '--apk_package', apk_package
    ]
    if self.m.chromium.c.BUILD_CONFIG == 'Release':
      install_cmd.append('--release')
    return self.m.step('install ' + apk, install_cmd,
                       infra_step=True,
                       env=self.get_env())

  def monkey_test(self, **kwargs):
    args = [
        'monkey',
        '-v',
        '--package=%s' % self.c.channel,
        '--event-count=50000'
    ]
    return self.m.python(
        'Monkey Test',
        str(self.m.path['checkout'].join('build', 'android', 'test_runner.py')),
        args,
        env={'BUILDTYPE': self.c.BUILD_CONFIG},
        **kwargs)

  def _run_sharded_tests(self,
                         config='sharded_perf_tests.json',
                         flaky_config=None,
                         **kwargs):
    args = ['perf', '--release', '--verbose', '--steps', config]
    if flaky_config:
      args.extend(['--flaky-steps', flaky_config])

    self.m.python(
        'Sharded Perf Tests',
        self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
        args,
        cwd=self.m.path['checkout'],
        env=self.get_env(),
        **kwargs)

  def run_sharded_perf_tests(self, config, flaky_config=None, perf_id=None,
                             test_type_transform=lambda x: x, **kwargs):
    """Run the perf tests from the given config file.

    config: the path of the config file containing perf tests.
    flaky_config: optional file of tests to avoid.
    perf_id: the id of the builder running these tests
    test_type_transform: a lambda transforming the test name to the
      test_type to upload to.
    """
    # test_runner.py actually runs the tests and records the results
    self._run_sharded_tests(config=config, flaky_config=flaky_config,
                                  **kwargs)

    # now obtain the list of tests that were executed.
    result = self.m.step(
        'get perf test list',
        [self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
         'perf', '--steps', config, '--output-json-list', self.m.json.output()],
        step_test_data=lambda: self.m.json.test_api.output([
            'perf_test.foo', 'page_cycler.foo']),
        env=self.get_env()
    )
    perf_tests = result.json.output

    failures = []
    for test_name in perf_tests:
      test_name = str(test_name)  # un-unicode
      test_type = test_type_transform(test_name)
      annotate = self.m.chromium.get_annotate_by_test_name(test_name)

      try:
        self.m.chromium.runtest(
          self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
          ['perf', '--print-step', test_name, '--verbose'],
          name=test_name,
          perf_dashboard_id=test_type,
          test_type=test_type,
          annotate=annotate,
          results_url='https://chromeperf.appspot.com',
          perf_id=perf_id,
          env=self.get_env())
      except self.m.step.StepFailure as f:
        failures.append(f)

    if failures:
      raise self.m.step.StepFailure('sharded perf tests failed %s' % failures)

  @recipe_api.composite_step
  def run_instrumentation_suite(self, test_apk, test_data=None,
                                flakiness_dashboard=None,
                                annotation=None, except_annotation=None,
                                screenshot=False, verbose=False,
                                apk_package=None, host_driven_root=None,
                                official_build=False, install_apk=None,
                                **kwargs):
    if install_apk:
      self.adb_install_apk(install_apk['apk'], install_apk['package'])

    args = ['--test-apk', test_apk]
    if test_data:
      args.extend(['--test_data', test_data])
    if flakiness_dashboard:
      args.extend(['--flakiness-dashboard-server', flakiness_dashboard])
    if annotation:
      args.extend(['-A', annotation])
    if except_annotation:
      args.extend(['-E', except_annotation])
    if screenshot:
      args.append('--screenshot')
    if verbose:
      args.append('--verbose')
    if self.m.chromium.c.BUILD_CONFIG == 'Release':
      args.append('--release')
    if self.c.coverage:
      args.extend(['--coverage-dir', self.coverage_dir,
                   '--python-only'])
    if host_driven_root:
      args.extend(['--host-driven-root', host_driven_root])
    if official_build:
      args.extend(['--official-build'])

    self.m.python(
        'Instrumentation test %s' % (annotation or test_apk),
        self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
        args=['instrumentation'] + args,
        **kwargs)

  @recipe_api.composite_step
  def logcat_dump(self, gs_bucket=None):
    if gs_bucket:
      log_path = self.m.chromium.output_dir.join('full_log')
      self.m.python(
          'logcat_dump',
          self.m.path['checkout'].join('build', 'android',
                                       'adb_logcat_printer.py'),
          [ '--output-path', log_path,
            self.m.path['checkout'].join('out', 'logcat') ],
          infra_step=True)
      self.m.gsutil.upload(
          log_path,
          gs_bucket,
          'logcat_dumps/%s/%s' % (self.m.properties['buildername'],
                                  self.m.properties['buildnumber']),
          link_name='logcat dump')
    else:
      self.m.python(
          'logcat_dump',
          self.m.path['build'].join('scripts', 'slave', 'tee.py'),
          [self.m.chromium.output_dir.join('full_log'),
           '--',
           self.m.path['checkout'].join('build', 'android',
                                        'adb_logcat_printer.py'),
           self.m.path['checkout'].join('out', 'logcat')],
          infra_step=True,
          )

  def stack_tool_steps(self):
    log_file = self.m.path['checkout'].join('out',
                                            self.m.chromium.c.BUILD_CONFIG,
                                            'full_log')
    target_arch = self.m.chromium.c.gyp_env.GYP_DEFINES['target_arch']
    # gyp converts ia32 to x86, bot needs to do the same
    target_arch = {'ia32': 'x86'}.get(target_arch) or target_arch
    self.m.step(
        'stack_tool_with_logcat_dump',
        [self.m.path['checkout'].join('third_party', 'android_platform',
                              'development', 'scripts', 'stack'),
         '--arch', target_arch, '--more-info', log_file], env=self.get_env(),
        infra_step=True)
    self.m.step(
        'stack_tool_for_tombstones',
        [self.m.path['checkout'].join('build', 'android', 'tombstones.py'),
         '-a', '-s', '-w'], env=self.get_env(),
        infra_step=True)
    if self.c.asan_symbolize:
      self.m.step(
          'stack_tool_for_asan',
          [self.m.path['checkout'].join('build',
                                        'android',
                                        'asan_symbolize.py'),
           '-l', log_file], env=self.get_env(),
          infra_step=True)

  def test_report(self):
    self.m.python.inline(
        'test_report',
         """
            import glob, os, sys
            for report in glob.glob(sys.argv[1]):
              with open(report, 'r') as f:
                for l in f.readlines():
                  print l
              os.remove(report)
         """,
         args=[self.m.path['checkout'].join('out',
                                            self.m.chromium.c.BUILD_CONFIG,
                                            'test_logs',
                                            '*.log')],
    )

  def common_tests_setup_steps(self):
    self.spawn_logcat_monitor()
    self.device_status_check()
    self.provision_devices()

  def common_tests_final_steps(self):
    self.logcat_dump()
    self.stack_tool_steps()
    self.test_report()

  def run_bisect_script(self, extra_src='', path_to_config=''):
    self.m.step('prepare bisect perf regression',
        [self.m.path['checkout'].join('tools',
                                      'prepare-bisect-perf-regression.py'),
         '-w', self.m.path['slave_build']])

    args = []
    if extra_src:
      args = args + ['--extra_src', extra_src]
    if path_to_config:
      args = args + ['--path_to_config', path_to_config]
    self.m.step('run bisect perf regression',
        [self.m.path['checkout'].join('tools',
                                      'run-bisect-perf-regression.py'),
         '-w', self.m.path['slave_build']] + args)

  def run_test_suite(self, suite, verbose=True, isolate_file_path=None,
                     gtest_filter=None, tool=None, **kwargs):
    args = []
    if verbose:
      args.append('--verbose')
    if self.c.BUILD_CONFIG == 'Release':
      args.append('--release')
    if isolate_file_path:
      args.append('--isolate_file_path=%s' % isolate_file_path)
    if gtest_filter:
      args.append('--gtest_filter=%s' % gtest_filter)
    if tool:
      args.append('--tool=%s' % tool)

    self.m.python(
        str(suite),
        self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
        ['gtest', '-s', suite] + args,
        env=self.get_env(),
        **kwargs)

  def run_java_unit_test_suite(self, suite, verbose=True, **kwargs):
    args = []
    if verbose:
      args.append('--verbose')
    if self.c.BUILD_CONFIG == 'Release':
      args.append('--release')

    self.m.python(
      str(suite),
      self.m.path['checkout'].join('build', 'android', 'test_runner.py'),
      ['junit', '-s', suite] + args,
      env=self.get_env(),
      **kwargs)

  def coverage_report(self, **kwargs):
    assert self.c.coverage, (
        'Trying to generate coverage report but coverage is not enabled')
    gs_dest = 'java/%s/%s' % (
        self.m.properties['buildername'], self.m.properties['revision'])

    self.m.python(
        'Generate coverage report',
        self.m.path['checkout'].join(
            'build', 'android', 'generate_emma_html.py'),
        args=['--coverage-dir', self.coverage_dir,
              '--metadata-dir', self.out_path.join(self.c.BUILD_CONFIG),
              '--cleanup',
              '--output', self.coverage_dir.join('coverage_html',
                                                 'index.html')],
        infra_step=True,
        **kwargs)

    self.m.gsutil.upload(
        source=self.coverage_dir.join('coverage_html'),
        bucket='chrome-code-coverage',
        dest=gs_dest,
        args=['-R'],
        name='upload coverage report',
        link_name='Coverage report',
        **kwargs)


# -*- coding: utf-8 -*-
from odoo import api, fields, models
from odoo.addons.base.models.res_users import name_selection_groups
from odoo.exceptions import ValidationError

class ResUsers(models.Model):
    _inherit = 'res.users'

    is_user = fields.Boolean(string='Purchase User')
    is_manager = fields.Boolean(string='Purchase Manager')
    authorization_create = fields.Boolean(string='Authorization For Creation Purchase', default=True)
    date_baned = fields.Datetime(string='Date Banned')

    @api.onchange('is_user')
    def is_user_on_change(self):
        if self.is_user:
            self.is_manager = False

    @api.onchange('is_manager')
    def is_manager_on_change(self):
        if self.is_manager:
            self.is_user = False

    @api.model
    def create(self, vals):
        res = super(ResUsers, self).create(vals)
        group_user_types = self.env['res.groups'].search(
            [('category_id', '=', self.env.ref('base.module_category_user_type').id)])
        field_user_type = name_selection_groups(group_user_types.ids)
        portal = vals.get(str(field_user_type))
        portal_id = self.env.ref('base.group_portal').id
        if portal != portal_id and (vals.get('is_user') or vals.get('is_manager')):
            raise ValidationError('Sorry you are not allowed please Change to portal User')
        return res

    def write(self, vals):
        res = super(ResUsers, self).write(vals)
        group_user_types = self.env['res.groups'].search(
            [('category_id', '=', self.env.ref('base.module_category_user_type').id)])
        field_user_type = name_selection_groups(group_user_types.ids)
        portal = vals.get(str(field_user_type))
        portal_id = self.env.ref('base.group_portal').id
        if portal and portal != portal_id and (
                vals.get('is_user') or vals.get('is_manager') or self.is_user or self.is_manager):
            raise ValidationError('Sorry you are not allowed please Change to portal User')
        return res


from django.urls import path, include
from rest_framework.routers import DefaultRouter
from hydro_capsule.api.views import (
    CapsuleViewSet,
    PlantTypeViewSet,
    PlantViewSet,
    GrowRuleViewSet,
    SlotViewSet,
    FertilizerViewSet,
    FertilizerInRuleViewSet,
    FertilizerInSlotViewSet
)

router = DefaultRouter()

router.register("capsules", CapsuleViewSet)
router.register("plant_types", PlantTypeViewSet)
router.register("plants", PlantViewSet)
router.register("grow_rules", GrowRuleViewSet)
router.register("slots", SlotViewSet)
router.register("fertilizers", FertilizerViewSet)
router.register("fertilizer_in_rules", FertilizerInRuleViewSet)
router.register("fertilizer_in_slots", FertilizerInSlotViewSet)

urlpatterns = [
    path("", include(router.urls))
]


from Funcoes import Funcoes_Menus
from os import system
import pickle

meses = ('Janeiro','Fevereiro','Março', 'Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro',1,2,3,4,5,6,7,8,9,10,11,12)

############## Dividas
##### Funções

# Validação de numero ↓
def validacao_numero(num1):
  while num1.isdecimal() == False:
    num1 = input(f'Digite um número válido!\n')
  num1 = int(num1)
  return num1
''''''

# Validação de Mes
def validacao_mes():
  global meses
  mes = input('As dívidas são de qual mês?\n').capitalize()

  if mes.isdecimal() == True:
    mes = int(mes)
    if (mes >= 1) and (mes <= 12):
      mes = meses[mes-1]

  while mes not in meses:
    mes = input('Digite um mês válido!\n')
    if mes.isdecimal() == True:
      mes = int(mes)
      if (mes >= 1) and (mes <= 12):
        mes = meses[mes-1]
      else:
        mes = input(f'Digite um mês válido!\n').capitalize()
  return mes
''''''

# Salvar
def divida_salvar():
  with open('divida.dat', 'wb') as arq_divida:
    pickle.dump(dividas_dicionario, arq_divida)
''''''

# Cadastrar
def divida_cadastrar():
  global dividas_dicionario
  mes = validacao_mes()

  Q_dividas = input(f'Quantas dívidas você quer cadastrar?\n')
  Q_dividas = validacao_numero(Q_dividas)

  matriz = []

   # mes ainda não existe no dicionário ↓
  if mes not in dividas_dicionario:
    for i in range(1, Q_dividas + 1):
      divida = []
      print('\n')

      nome_Divida = input(f'Nome da dívida {i}:\n')

      # Validação de valor
      valor = input(f'Quanto é o valor de {nome_Divida}?\n')
      valor = validacao_numero(valor)

      divida += [nome_Divida,valor]
      matriz += [divida]

    # mes já existe no dicionário ↓
  else:
    print('\n')
    for i in range(1, Q_dividas + 1):
      divida = []
      nome_Divida = input(f'Nome da dívida {i}:\n')
      valor = input(f'Quanto é o valor de {nome_Divida}?\n')
      valor = validacao_numero(valor)

    matriz += dividas_dicionario[mes]
    divida += [nome_Divida,valor]
    matriz.extend([divida])

  dividas_dicionario [mes] = matriz

  divida_salvar()

  input('Tecle ENTER para continuar!')
''''''

# Vizualizar
def divida_vizualizar():
  global dividas_dicionario
  try:
    print('Todas as dívidas:\n')

    for mes in dividas_dicionario.keys():
      print(f'{mes}:\t{dividas_dicionario[mes]}')
  except:
    print('Não há dívidas registradas')

  print('\n')
''''''

# Pesquisar
def divida_pesquisar():
  global dividas_dicionario
  print('Pesquisa')
  print('\n')
  mes = validacao_mes()

  if mes in dividas_dicionario:

    print('\n')
    print('Mês:\t',mes)
    print('Conta:\t',dividas_dicionario[mes][0])
    print('Valor:\t', dividas_dicionario[mes][1])
    print('\n')

  else:
    print('Mês não encontrato!')

  input('Aperte ENTER para continuar\n')
''''''

# Editar
def divida_editar():
  global dividas_dicionario
  print('\n')
  divida_vizualizar()
  mes = validacao_mes()

  if mes in dividas_dicionario:
    matriz = dividas_dicionario[mes]
    print(f'No mes {mes} tem essas dividas:\n{dividas_dicionario[mes]}')
    print('\n')

    q_qual_divida = input('Quantas deseja alterar?\n')
    q_qual_divida = validacao_numero(q_qual_divida)

    for i in range (1,q_qual_divida+1):
      editar = []
      qual_divida = input('Qual deseja alterar?\n')
      qual_divida = validacao_numero(qual_divida)
      qual_divida -= 1
      matriz.pop(qual_divida)

      nome_Divida = input('Novo nome da dívida:\n')

      valor = input('Novo valor da dívida:\n')
      valor = validacao_numero(valor)

      editar = [nome_Divida, valor]
      matriz.insert(qual_divida,editar)

    dividas_dicionario[mes] = matriz
    divida_salvar()

    print('Conta alterada com sucesso...')

  else:
    print('Mês não encontrato!')
  input('Tecle ENTER para continuar!')
''''''

# Excluir
def divida_excluir():
  global dividas_dicionario
  print('\n')
  divida_vizualizar()
  mes = validacao_mes()

  try:
    if mes in dividas_dicionario:

      del dividas_dicionario[mes]
      print('Mês excluído com sucesso...')
      divida_salvar()

    else:
      print('Mês não encontrado!')
  except:
    print('Ocorreu algum problema')

  input('Tecle ENTER para continuar!')

''''''

##############################
##### Programa Principal #####
##############################

try:
  arq_divida = open('divida.dat', 'rb')
  dividas_dicionario = pickle.load(arq_divida)
  arq_divida.close()
except:
  arq_divida = open('divida.dat', 'wb')
  arq_divida.close()
  dividas_dicionario = {}

def modulo_divida():
  system('clear')
  system('cls')
  operacao = ''
  while operacao != '0':
    Funcoes_Menus.menu_Dividas()
    operacao = input('Selecione o que quer fazer:\n')
    print('\n')

    if operacao == '1':
      divida_cadastrar()
      system('clear')
      system('cls')

    elif operacao == '2':
      divida_vizualizar()
      input('Aperte ENTER para continuar\n')
      system('clear')
      system('cls')

    elif operacao == '3':
      divida_pesquisar()
      system('clear')
      system('cls')

    elif operacao == '4':
      divida_editar()
      system('clear')
      system('cls')

    elif operacao == '5':
      divida_excluir()
      system('clear')
      system('cls')
    elif operacao == '0':
      system('clear')
      system('cls')
    else:
      system('clear')
      system('cls')
      print('Digite uma operação válida!')


import os
import sys
from dataclasses import is_dataclass

sys.path.insert(0, os.path.abspath('..'))

# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'pygmp'
copyright = '2023, Jack Hart'
author = 'Jack Hart'
release = '0.0.1'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
napoleon_attr_annotations = True

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

# -- Options for HTML output -------------------------------------------------

html_theme = 'furo'
html_title = 'pygmp'
html_static_path = ['_static']

autodoc_typehints = "description"
autodoc_class_signature = "separated"
autoclass_content = "class"

def skip(app, what, name, obj, would_skip, options):
    if name == "__init__":
        return True
    return would_skip

def setup(app):
    print("setup is run")
    app.connect("autodoc-skip-member", skip)

html_theme_options = {
    "announcement": "<b>This project is under active development. The API is subject to change.</b>",
    "source_repository": "https://github.com/jackhart/pygmp",
    "source_branch": "main",
    "source_directory": "docs/"
}


import math
import numpy as np

z = np.array([0.])

def protectedDiv(left, right):
    try:
        return left / right
    except ZeroDivisionError:
        return z

def myexp(x):
    with np.errstate(divide='ignore', invalid='ignore'):
        if isinstance(x, np.ndarray):
            x = np.exp(x)
            x[np.isinf(x)] = np.exp(700)
            x[np.isnan(x)] = np.exp(700)
            return x
        else:
            x = np.exp(x)
            if np.isinf(x):
                x = np.exp(700)
            elif np.isnan(x):
                x = np.exp(700)
            return x

def negexp(x):
    with np.errstate(divide='ignore', invalid='ignore'):
        if isinstance(x, np.ndarray):
            x = np.exp(np.negative(x))
            x[np.isinf(x)] = np.exp(np.negative(700))
            x[np.isnan(x)] = np.exp(np.negative(700))
            return x
        else:
            x = np.exp(np.negative(x))
            if np.isinf(x):
                x = np.exp(np.negative(700))
            elif np.isnan(x):
                x = np.exp(np.negative(700))
            return x

def safe_div(left, right):
    with np.errstate(divide='ignore',invalid='ignore'):
        x = np.divide(left, right)
        if isinstance(x, np.ndarray):
            x[np.isinf(x)] = 0.0
            x[np.isnan(x)] = 0.0
        elif np.isinf(x) or np.isnan(x):
            x = 0.0
    return x

def mylog(x):
    with np.errstate(divide='ignore',invalid='ignore'):
        if isinstance(x, np.ndarray):
            x=np.log10(abs(x))
            x[np.isinf(x)] = 0.
            x[np.isnan(x)] = 0.0
            return x
        else:
            if x == 0:
                return z
            else:
                return np.log10(abs(x))

def mysqrt(x):
    if isinstance(x, np.ndarray):
        x[x < 0.0] = 0.0
        return np.sqrt(x)
    else:
        if x <= 0.0:
            return z
        else:
            return np.sqrt(x)

def mypower2(x):
    if isinstance(x,np.ndarray):
        y = np.power(x, 2)
    else:
        y = [np.power(x, 2)]
    if np.logical_or(isinstance(y, complex), np.isinf(y), np.isnan(y)).all():
        return z
    else:
        return np.array(y)

def mypower3(x):
    if isinstance(x,np.ndarray):
        y = np.power(x, 3)
    else:
        y = [np.power(x, 3)]
    if np.logical_or(isinstance(y, complex), np.isinf(y), np.isnan(y)).all():
        return z
    else:
        return np.array(y)

def negative(x):
    if isinstance(x, np.ndarray):
        return np.negative(x)
    else:
        return -x

def absolute(x):
    if isinstance(x, np.ndarray):
        return np.absolute(x)
    else:
        return abs(x)

def undivide(x):
    if isinstance(x,np.ndarray):
        with np.errstate(divide='ignore',invalid='ignore'):
            x = np.divide(1.0, x)
            x[np.isinf(x)] = 0.0
            x[np.isnan(x)] = 0.0
            return x
    else:
        if x == 0:
            return 1.0
        else:
            return 1.0/x

def avg_nodes(population):
    n_nodes = []
    for ind in population:
        n_nodes.append(len(ind))
    nn_nodes = np.asarray(n_nodes)
    max_size = max(nn_nodes)
    min_size = min(nn_nodes)
    av_size = np.mean(nn_nodes)
    return av_size, max_size, min_size


from collections import defaultdict
from functools import lru_cache

class Solution:
    def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, K: int) -> int:

        adj = defaultdict(set)

        for f in flights:
            adj[f[0]].add((f[1], f[2]))

        @lru_cache(None)
        def dfs(s, d, k):
            if s == d:
                return 0 if k >= 0 else float('inf')
            if k <= 0:
                return float('inf')
            ans = float('inf')
            for a in adj[s]:
                ans = min(ans, a[1] + dfs(a[0], d, k-1))
            return ans

        ret = dfs(src, dst, K+1)
        return ret if ret != float('inf') else -1


# -*- encoding: utf-8 -*-

import argparse
import json
import os

import mock

from s4.commands.add_command import AddCommand

from tests import utils

@mock.patch("s4.utils.get_input")
class TestAddCommand(object):
    def test_correct_behaviour(self, get_input, config_file):
        get_input.side_effect = [
            "/home/user/Documents",
            None,
            "mybucket",
            "Documents",
            "eu-west-2",
            "aaaaaaaaaaaaaaaaaaaaaaaa",
            "bbbbbbbbbbbbbbbbbbbbbbbb",
            "",
        ]
        args = argparse.Namespace(copy_target_credentials=None)

        command = AddCommand(args, {"targets": {}}, utils.create_logger())
        command.run()

        with open(config_file, "r") as fp:
            new_config = json.load(fp)

        expected_config = {
            "targets": {
                "Documents": {
                    "local_folder": "/home/user/Documents",
                    "endpoint_url": None,
                    "s3_uri": "s3://mybucket/Documents",
                    "aws_access_key_id": "aaaaaaaaaaaaaaaaaaaaaaaa",
                    "aws_secret_access_key": "bbbbbbbbbbbbbbbbbbbbbbbb",
                    "region_name": "eu-west-2",
                }
            }
        }
        assert new_config == expected_config

    def test_default_local_folder(self, get_input, config_file):
        get_input.side_effect = [
            None,
            None,
            "mybucket",
            "Documents",
            "eu-west-2",
            "aaaaaaaaaaaaaaaaaaaaaaaa",
            "bbbbbbbbbbbbbbbbbbbbbbbb",
            "",
        ]
        args = argparse.Namespace(copy_target_credentials=None)

        command = AddCommand(args, {"targets": {}}, utils.create_logger())
        command.run()

        with open(config_file, "r") as fp:
            config = json.load(fp)

        assert config["targets"]["Documents"]["local_folder"] == os.getcwd()

    def test_copy_target_credentials(self, get_input, config_file):
        get_input.side_effect = [
            "/home/user/Animals",
            None,
            "mybucket",
            "Zoo",
            "us-west-2",
            "Beasts",
        ]
        args = argparse.Namespace(copy_target_credentials="bar")

        command = AddCommand(
            args,
            {
                "targets": {
                    "bar": {
                        "aws_secret_access_key": "bar-secretz",
                        "aws_access_key_id": "so-much-bar",
                    }
                }
            },
            utils.create_logger(),
        )
        command.run()

        with open(config_file, "r") as fp:
            new_config = json.load(fp)

        expected_config = {
            "targets": {
                "bar": {
                    "aws_access_key_id": "so-much-bar",
                    "aws_secret_access_key": "bar-secretz",
                },
                "Beasts": {
                    "local_folder": "/home/user/Animals",
                    "endpoint_url": None,
                    "s3_uri": "s3://mybucket/Zoo",
                    "aws_access_key_id": "so-much-bar",
                    "aws_secret_access_key": "bar-secretz",
                    "region_name": "us-west-2",
                },
            }
        }
        assert new_config == expected_config

    def test_copy_target_credentials_bad_target(self, get_input, capsys):
        get_input.side_effect = [
            "/home/user/Animals",
            "",
            "mybucket",
            "Zoo",
            "us-west-2",
            "Beasts",
        ]
        args = argparse.Namespace(copy_target_credentials="Foo")

        command = AddCommand(args, {"targets": {"bar": {}}}, utils.create_logger())
        command.run()

        out, err = capsys.readouterr()
        assert out == ""
        assert err == ('"Foo" is an unknown target\n' "Choices are: ['bar']\n")

    def test_custom_target_name(self, get_input, config_file):
        get_input.side_effect = [
            "/home/user/Music",
            None,
            "mybucket",
            "Musiccccc",
            "us-west-1",
            "1234567890",
            "abcdefghij",
            "Tunes",
        ]
        args = argparse.Namespace(copy_target_credentials=None)

        command = AddCommand(args, {"targets": {}}, utils.create_logger())
        command.run()

        with open(config_file, "r") as fp:
            new_config = json.load(fp)

        expected_config = {
            "targets": {
                "Tunes": {
                    "local_folder": "/home/user/Music",
                    "endpoint_url": None,
                    "s3_uri": "s3://mybucket/Musiccccc",
                    "aws_access_key_id": "1234567890",
                    "aws_secret_access_key": "abcdefghij",
                    "region_name": "us-west-1",
                }
            }
        }
        assert new_config == expected_config