<commit_before>#!/usr/bin/env python

"""
Class describing implementation of a SN universe describing the types of SN in the universe, the abundances of each type of SN, and the distribution of subtypes/parameters of each type of SN. To allow for convenient usage in multiple application situations (eg. where the population of galaxies is known or where it is not), it should be possible to describe such a universe in terms of the galaxies present (giving environmental properties) or on the average, with no knowledge of galaxies but through a rate.

In practice the class is specified by the following attributes and methods:

    atrributes:
        SNModel: Physically this is a phenomenological model of SN such as\
            the SALT2 model. In practice, this could point to an SNCosmo Model\
            object.
    methods:
        SNdists: This specifies how the parameters of SNModel described above
            are distributed.

"""
import sncosmo
import numpy as np
import Sources

class TypeInfo(object):
      """docstring for TypeInfo"""
      def __init__(self, model, pdf):
          super(TypeInfo, self).__init__()
          self.model = model
          self._pdf=pdf

class TSSUniverse (object):

    def __init__(self, start_mjd, end_mjd, seed):
        self._types=types  = [ 'SN II-pec','SN IIL','SN IIL/P', 'SN IIP', \
            'SN IIn', 'SN Ia', 'SN Ib', 'SN Ib/c', 'SN Ic']

        self._start_mjd = start_mjd
        self._end_mjd = end_mjd
        self._seed = seed

        self.typeinfo=dict()
        for t in self._types:
            self.typeinfo[t]=TypeInfo(Sources.registry_sources_as_models(t,
                subclassName="sncosmo.TimeSeriesSource"), np.random.normal(-19.3, 0.3))

    def sneByGalaxies(self,galaxies):
        #for each type determine wehther there is a
        pass

    def sneBySNType(self,sntype):
        pass

    @property
    def seed(self):
        return self._seed
    def reset_model(self, seed, z):
        self._seed = seed
        self.set_z(z)
        return self.get_SNparams()

    @property
    def z(self):
        return self._z

    def set_z(self,z ):
        self._z = z
        self.snIaModel.set(z=z)
    @property
    def ra(self):
        return self._ra

    def get_SNparams(self):

        hundredyear = 100*365.0
        np.random.seed(self.seed)
        t0 = np.random.uniform(-hundredyear/2.0, hundredyear/2.0)
        c = np.random.normal(0., 0.3)
        x1 = np.random.normal(0., 1.0)
        mabs = np.random.normal(-19.3, 0.3)
        self.snIaModel.set(z=self.z, c=c, x1=x1)
        self.snIaModel.set_source_peakabsmag(mabs, 'bessellb', 'ab')
        x0 = self.snIaModel.get('x0')

        return np.array([t0, x0, x1, c])

if __name__ == "__main__":
    dum =  TSSUniverse(0,365.25*10,0)
<commit_msg>last change for the dat<commit_after>#!/usr/bin/env python

"""
Class describing implementation of a SN universe describing the types of SN in the universe, the abundances of each type of SN, and the distribution of subtypes/parameters of each type of SN. To allow for convenient usage in multiple application situations (eg. where the population of galaxies is known or where it is not), it should be possible to describe such a universe in terms of the galaxies present (giving environmental properties) or on the average, with no knowledge of galaxies but through a rate.

In practice the class is specified by the following attributes and methods:

    atrributes:
        SNModel: Physically this is a phenomenological model of SN such as\
            the SALT2 model. In practice, this could point to an SNCosmo Model\
            object.
    methods:
        SNdists: This specifies how the parameters of SNModel described above
            are distributed.

"""
import sncosmo
import numpy as np
import Sources

class TypeInfo(object):
      """docstring for TypeInfo"""
      def __init__(self, model, pdf, rate, rate_snu):
          super(TypeInfo, self).__init__()
          self.model = model
          self.pdf=pdf
          self.rate = rate
          self.rate_snu = rate_snu

class TSSUniverse (object):

    def __init__(self, start_mjd, end_mjd, seed):
        # self._types=types  = [ 'SN II-pec','SN IIL','SN IIL/P', 'SN IIP', \
        #     'SN IIn', 'SN Ib', 'SN Ib/c', 'SN Ic']
        self.types=types  = [ 'SN IIL', 'SN IIP','SN Ib', 'SN Ib/c', 'SN Ic']

        self.start_mjd = start_mjd
        self.end_mjd = end_mjd
        # self.seed = seed

        self.typeinfo=dict()
        for t in self.types:
            self.typeinfo[t]=TypeInfo(Sources.registry_sources_as_models(t,
                subclassName="sncosmo.TimeSeriesSource"), np.random.normal(-19.3, 0.3),
                1,1e-2/len(self.types))

    def sneByGalaxy(self,galaxy):
        np.random.seed(seed=galaxy.seed)
        #for each type determine whether there is a SN
        for t in self.types:
            info = self.typeinfo[t]
            mn = info.rate_snu * (self.end_mjd-self.start_mjd)/(1+galaxy.z)
            ans=np.random.poisson(mn)
            for i in xrange(ans):
                pass
        pass

    def sneBySNType(self,sntype):
        pass

    @property
    def seed(self):
        return self._seed
    def reset_model(self, seed, z):
        self._seed = seed
        self.set_z(z)
        return self.get_SNparams()

    @property
    def z(self):
        return self._z

    def set_z(self,z ):
        self._z = z
        self.snIaModel.set(z=z)
    @property
    def ra(self):
        return self._ra

    def get_SNparams(self):

        hundredyear = 100*365.0
        np.random.seed(self.seed)
        t0 = np.random.uniform(-hundredyear/2.0, hundredyear/2.0)
        c = np.random.normal(0., 0.3)
        x1 = np.random.normal(0., 1.0)
        mabs = np.random.normal(-19.3, 0.3)
        self.snIaModel.set(z=self.z, c=c, x1=x1)
        self.snIaModel.set_source_peakabsmag(mabs, 'bessellb', 'ab')
        x0 = self.snIaModel.get('x0')

        return np.array([t0, x0, x1, c])

class Galaxy(object):
    """docstring for Galaxy"""
    def __init__(self, z, seed):
        super(Galaxy, self).__init__()
        self.z = z
        self.seed = seed

if __name__ == "__main__":
    dum =  TSSUniverse(0.,10,0.)
    gal = Galaxy(0.5,0)
    dum.sneByGalaxy(gal)

<|endoftext|>


<commit_before>import abc
from contextlib import contextmanager

from django import forms
from django.db import transaction, DEFAULT_DB_ALIAS
from django.forms.forms import DeclarativeFieldsMetaclass
from django.forms.models import ModelFormMetaclass
import six

from .errors import InvalidInputsError

class ServiceMetaclass(abc.ABCMeta, DeclarativeFieldsMetaclass):
    pass

@six.add_metaclass(ServiceMetaclass)
class Service(forms.Form):
    """
    Based on Django's :class:`Form`, designed to encapsulate
    Business Rules functionality.  Input values are validated against
    the Service's defined fields before calling main functionality::

        class UpdateUserEmail(Service):
            user = ModelField(User)
            new_email = forms.EmailField()

            def process(self):
                old_email = user.email
                user.email = self.cleaned_data['new_email']
                user.save()

                send_email(
                    'Email Update',
                    'Your email was changed',
                    'system',
                    [old_email]
                )

        user = User.objects.get(id=20)

        UpdateUserEmail.execute({
            'user': user,
            'new_email': 'John.Smith@example.com'
        })

    :cvar boolean db_transaction: controls if :py:meth:`execute`
        is performed inside a Django database transaction.  Default
        is True.

    :cvar string using: In a multiple database setup, controls which
        database connection is used from the transaction.  Defaults
        to DEFAULT_DB_ALIAS which works in a single database setup.

    """

    db_transaction = True
    run_post_process = True
    using = DEFAULT_DB_ALIAS

    @classmethod
    def execute(cls, inputs, files=None, **kwargs):
        """
        Function to be called from the outside to kick off the Service
        functionality.

        :param dictionary inputs: data parameters for Service, checked
            against the fields defined on the Service class.

        :param dictionary files: usually request's FILES dictionary or
            None.

        :param dictionary **kwargs: any additional parameters Service may
            need, can be an empty dictionary
        """
        instance = cls(inputs, files, **kwargs)
        instance.service_clean()
        with instance._process_context():
            return instance.process()

    def service_clean(self):
        """
        Calls base Form's :meth:`is_valid` to verify ``inputs`` against
        Service's fields and raises :class:`InvalidInputsError` if necessary.
        """
        if not self.is_valid():
            raise InvalidInputsError(self.errors, self.non_field_errors())

    @abc.abstractmethod
    def process(self):
        """
        Main method to be overridden; contains the Business Rules
        functionality.
        """
        pass

    @contextmanager
    def _process_context(self):
        """
        Returns the context for :meth:`process`
        :return:
        """
        if self.db_transaction:
            with transaction.atomic(using=self.using):
                if self.run_post_process:
                    transaction.on_commit(self.post_process)
                yield
        else:
            yield
            if self.run_post_process:
                self.post_process()

    def post_process(self):
        """
        Post process method to be perform extra actions after successfully
        commits.
        """
        pass

class ModelServiceMetaclass(ServiceMetaclass, ModelFormMetaclass):
    pass

class ModelService(six.with_metaclass(ModelServiceMetaclass, Service)):
    """
    Same as :class:`Service` but auto-creates fields based on the provided
    :class:`Model`.  Additionally, You can manually create fields to override
    or extend the auto-created fields::

        class Person(models.Model):
            first_name = models.CharField(max_length=30)
            last_name = models.CharField(max_length=30)
            email = models.EmailField()

        class CreatePersonService(Service):
            class Meta:
                model = Person
                fields = '_all_'

            notify = forms.BooleanField()

            def process(self):
                person = Person(
                    first_name = self.cleaned_data['first_name'],
                    last_name = self.cleaned_data['last_name'],
                    email = self.cleaned_data['email']
                )
                person.save()

                if self.cleaned_data['notify']:
                    django.send_mail(
                        'Account Created',
                        'An account has been created for you'
                        'System',
                        [person.email]
                    )

        CreatePersonService.execute({
            'first_name': 'John',
            'last_name': 'Smith',
            'notify': True
        })
    """
    pass
<commit_msg>Update post_process doc strings to match usage. (#58)<commit_after>import abc
from contextlib import contextmanager

from django import forms
from django.db import transaction, DEFAULT_DB_ALIAS
from django.forms.forms import DeclarativeFieldsMetaclass
from django.forms.models import ModelFormMetaclass
import six

from .errors import InvalidInputsError

class ServiceMetaclass(abc.ABCMeta, DeclarativeFieldsMetaclass):
    pass

@six.add_metaclass(ServiceMetaclass)
class Service(forms.Form):
    """
    Based on Django's :class:`Form`, designed to encapsulate
    Business Rules functionality.  Input values are validated against
    the Service's defined fields before calling main functionality::

        class UpdateUserEmail(Service):
            user = ModelField(User)
            new_email = forms.EmailField()

            def process(self):
                old_email = user.email
                user.email = self.cleaned_data['new_email']
                user.save()

                send_email(
                    'Email Update',
                    'Your email was changed',
                    'system',
                    [old_email]
                )

        user = User.objects.get(id=20)

        UpdateUserEmail.execute({
            'user': user,
            'new_email': 'John.Smith@example.com'
        })

    :cvar boolean db_transaction: controls if :py:meth:`execute`
        is performed inside a Django database transaction.  Default
        is True.

    :cvar string using: In a multiple database setup, controls which
        database connection is used from the transaction.  Defaults
        to DEFAULT_DB_ALIAS which works in a single database setup.

    """

    db_transaction = True
    run_post_process = True
    using = DEFAULT_DB_ALIAS

    @classmethod
    def execute(cls, inputs, files=None, **kwargs):
        """
        Function to be called from the outside to kick off the Service
        functionality.

        :param dictionary inputs: data parameters for Service, checked
            against the fields defined on the Service class.

        :param dictionary files: usually request's FILES dictionary or
            None.

        :param dictionary **kwargs: any additional parameters Service may
            need, can be an empty dictionary
        """
        instance = cls(inputs, files, **kwargs)
        instance.service_clean()
        with instance._process_context():
            return instance.process()

    def service_clean(self):
        """
        Calls base Form's :meth:`is_valid` to verify ``inputs`` against
        Service's fields and raises :class:`InvalidInputsError` if necessary.
        """
        if not self.is_valid():
            raise InvalidInputsError(self.errors, self.non_field_errors())

    @abc.abstractmethod
    def process(self):
        """
        Main method to be overridden; contains the Business Rules
        functionality.
        """
        pass

    @contextmanager
    def _process_context(self):
        """
        Returns the context for :meth:`process`
        :return:
        """
        if self.db_transaction:
            with transaction.atomic(using=self.using):
                if self.run_post_process:
                    transaction.on_commit(self.post_process)
                yield
        else:
            yield
            if self.run_post_process:
                self.post_process()

    def post_process(self):
        """
        Post process method to be perform extra actions once :meth:`process`
        successfully executes.
        """
        pass

class ModelServiceMetaclass(ServiceMetaclass, ModelFormMetaclass):
    pass

class ModelService(six.with_metaclass(ModelServiceMetaclass, Service)):
    """
    Same as :class:`Service` but auto-creates fields based on the provided
    :class:`Model`.  Additionally, You can manually create fields to override
    or extend the auto-created fields::

        class Person(models.Model):
            first_name = models.CharField(max_length=30)
            last_name = models.CharField(max_length=30)
            email = models.EmailField()

        class CreatePersonService(Service):
            class Meta:
                model = Person
                fields = '_all_'

            notify = forms.BooleanField()

            def process(self):
                person = Person(
                    first_name = self.cleaned_data['first_name'],
                    last_name = self.cleaned_data['last_name'],
                    email = self.cleaned_data['email']
                )
                person.save()

                if self.cleaned_data['notify']:
                    django.send_mail(
                        'Account Created',
                        'An account has been created for you'
                        'System',
                        [person.email]
                    )

        CreatePersonService.execute({
            'first_name': 'John',
            'last_name': 'Smith',
            'notify': True
        })
    """
    pass
<|endoftext|>


<commit_before>"""
@file coi-services/mi.idk.dataset/nose_test.py
@author Emily Hahn
@brief Helper class to invoke nose tests for dataset agent driver
"""

__author__ = 'Emily Hahn'
__license__ = 'Apache 2.0'

import sys
import inspect
import nose
import os

from mi.core.common import BaseEnum
from mi.core.log import get_logger ; log = get_logger()

import mi.idk.nose_test
from mi.idk.config import Config
from mi.idk.nose_test import IDKTestClasses
from mi.idk.exceptions import IDKException

from mi.idk.dataset.driver_generator import DriverGenerator

from mi.idk.dataset.unit_test import DataSetUnitTestCase
from mi.idk.dataset.unit_test import DataSetIntegrationTestCase
from mi.idk.dataset.unit_test import DataSetQualificationTestCase
from mi.idk.dataset.unit_test import DataSetIngestionTestCase
from mi.idk.dataset.unit_test import DataSetTestConfig

class DSATestClasses(BaseEnum):
    """
    Define base classes for unit tests
    """
    UNIT = DataSetUnitTestCase
    INT  = DataSetIntegrationTestCase
    QUAL = DataSetQualificationTestCase
    INGEST = DataSetIngestionTestCase

class NoseTest(mi.idk.nose_test.NoseTest):

    def __init__(self, metadata, testname = None, log_file=None, suppress_stdout = False, noseargs = None, launch_data_monitor=False):
        mi.idk.nose_test.NoseTest.__init__(self, metadata, testname, log_file,
                                           suppress_stdout, launch_data_monitor)

        self._ingest_test_class = 'DataSetIngestionTestCase'

    def _init_test(self, metadata):
        """
        initialize the test with driver metadata
        """
        self.metadata = metadata
        if(not self.metadata.driver_name):
            raise DriverNotStarted()

        self._inspect_driver_module(self._driver_test_module())

    def _driver_test_module(self):
        generator = DriverGenerator(self.metadata)
        return generator.test_modulename()

    def _data_test_module(self):
        generator = DriverGenerator(self.metadata)
        return generator.data_test_modulename()

    def _driver_test_filename(self):
        generator = DriverGenerator(self.metadata)
        return generator.driver_test_path()

    def _inspect_driver_module(self, test_module):
        '''
        Search the driver module for class definitions which are UNIT, INT,
        and QUAL tests. We will import the module do a little introspection
        and set member variables for the three test types.
        @raises: ImportError - we can't load the test module
        @raises: IDKException - if all test types aren't found
        '''
        self._unit_test_class = None
        self._int_test_class = None
        self._qual_test_class = None

        log.debug("Loading test module: %s", test_module)
        __import__(test_module)
        module = sys.modules.get(test_module)
        classes = inspect.getmembers(module, inspect.isclass)

        for name,clsobj in classes:
            clsstr = "<class '%s.%s'>" % (test_module, name)

            # We only want to inspect classes defined in the test module explicitly.  Ignore imported classes
            if(clsstr == str(clsobj)):
                if(issubclass(clsobj, DSATestClasses.UNIT)):
                    self._unit_test_class = name
                if(issubclass(clsobj, DSATestClasses.INT)):
                    self._int_test_class = name
                if(issubclass(clsobj, DSATestClasses.QUAL)):
                    self._qual_test_class = name

        if not(self._int_test_class):
            raise IDKException("integration test class not found")

        if(not self._qual_test_class):
            raise IDKException("qualification test class not found")

        # store a marker so we can either run or not run unit tests,
        # since missing integration tests is not an error
        self.has_unit = True
        if(not self._unit_test_class):
            self._log("No unit test class found")
            self.has_unit = False

    def report_header(self):
        """
        @brief Output report header containing system information.  i.e. metadata stored, comm config, etc.
        @param message message to be outputted
        """
        self._log( "****************************************" )
        self._log( "***   Starting Drive Test Process    ***" )
        self._log( "****************************************\n" )

        self._output_metadata()

    def run_unit(self):
        """
        @brief Run integration tests for a driver
        """
        if self.has_unit:
            self._log("*** Starting Unit Tests ***")
            self._log(" ==> module: " + self._driver_test_module())
            args=[sys.argv[0]]
            args += [self._unit_test_module_param()]
            module = "%s" % (self._driver_test_module())

            return self._run_nose(module, args)
        else:
            self._log("No unit tests to run")
            return True

    def _ingest_test_module_param(self):
        '''
        Module name and test to run
        @return: module name and optional test as string
        '''
        result = "%s:%s" % (self._ingest_test_filename(), self._ingest_test_class)
        if(self._testname): result = "%s.%s" % (result, self._testname)
        return result

    def _ingest_test_filename(self):
        return os.path.join(Config().base_dir(), "mi", "idk", "dataset", "unit_test.py")

    def run_ingestion(self, directory, runtime):
        """
        @brief Run a dataset agent and ingest files from the specified directory.  If
        runtime is set then stop running after x seconds.
        """
        self._log("Running ingestion test, directory: %s, runtime: %s" % (directory, runtime))

        # Dynamically load the driver test module so the IDK singleton is initialized
        test_module = __import__(self._driver_test_module())

        # Adjust the harvester config to point to the new directory
        DataSetTestConfig().driver_startup_config['harvester']['directory'] = directory

        # Add ingestion parameters to the singleton
        DataSetTestConfig().initialize_ingester_test(directory, runtime)

        args=[sys.argv[0]]
        args += [self._ingest_test_module_param()]
        module = "%s.%s" % ('mi.idk.dataset.unit_test', 'DataSetIngestionTestCase')

        self._log(" ==> module: " + module)
        self._log(" ==> args: %s" % args)

        return self._run_nose(module, args)

<commit_msg>Changes to nose test to get ingestion test to work (Bill F wrote).<commit_after>"""
@file coi-services/mi.idk.dataset/nose_test.py
@author Emily Hahn
@brief Helper class to invoke nose tests for dataset agent driver
"""

__author__ = 'Emily Hahn'
__license__ = 'Apache 2.0'

import sys
import inspect
import nose
import os

from mi.core.common import BaseEnum
from mi.core.log import get_logger ; log = get_logger()

import mi.idk.nose_test
from mi.idk.config import Config
from mi.idk.nose_test import IDKTestClasses
from mi.idk.exceptions import IDKException

from mi.idk.dataset.driver_generator import DriverGenerator

from mi.idk.dataset.unit_test import DataSetUnitTestCase
from mi.idk.dataset.unit_test import DataSetIntegrationTestCase
from mi.idk.dataset.unit_test import DataSetQualificationTestCase
from mi.idk.dataset.unit_test import DataSetIngestionTestCase
from mi.idk.dataset.unit_test import DataSetTestConfig

class DSATestClasses(BaseEnum):
    """
    Define base classes for unit tests
    """
    UNIT = DataSetUnitTestCase
    INT  = DataSetIntegrationTestCase
    QUAL = DataSetQualificationTestCase
    INGEST = DataSetIngestionTestCase

class NoseTest(mi.idk.nose_test.NoseTest):

    def __init__(self, metadata, testname = None, log_file=None, suppress_stdout = False, noseargs = None, launch_data_monitor=False):
        mi.idk.nose_test.NoseTest.__init__(self, metadata, testname, log_file,
                                           suppress_stdout, launch_data_monitor)

        self._ingest_test_class = 'DataSetIngestionTestCase'

    def _init_test(self, metadata):
        """
        initialize the test with driver metadata
        """
        self.metadata = metadata
        if(not self.metadata.driver_name):
            raise DriverNotStarted()

        self._inspect_driver_module(self._driver_test_module())

    def _driver_test_module(self):
        generator = DriverGenerator(self.metadata)
        return generator.test_modulename()

    def _data_test_module(self):
        generator = DriverGenerator(self.metadata)
        return generator.data_test_modulename()

    def _driver_test_filename(self):
        generator = DriverGenerator(self.metadata)
        return generator.driver_test_path()

    def _inspect_driver_module(self, test_module):
        '''
        Search the driver module for class definitions which are UNIT, INT,
        and QUAL tests. We will import the module do a little introspection
        and set member variables for the three test types.
        @raises: ImportError - we can't load the test module
        @raises: IDKException - if all test types aren't found
        '''
        self._unit_test_class = None
        self._int_test_class = None
        self._qual_test_class = None

        log.debug("Loading test module: %s", test_module)
        __import__(test_module)
        module = sys.modules.get(test_module)
        classes = inspect.getmembers(module, inspect.isclass)

        for name,clsobj in classes:
            clsstr = "<class '%s.%s'>" % (test_module, name)

            # We only want to inspect classes defined in the test module explicitly.  Ignore imported classes
            if(clsstr == str(clsobj)):
                if(issubclass(clsobj, DSATestClasses.UNIT)):
                    self._unit_test_class = name
                if(issubclass(clsobj, DSATestClasses.INT)):
                    self._int_test_class = name
                if(issubclass(clsobj, DSATestClasses.QUAL)):
                    self._qual_test_class = name

        if not(self._int_test_class):
            raise IDKException("integration test class not found")

        if(not self._qual_test_class):
            raise IDKException("qualification test class not found")

        # store a marker so we can either run or not run unit tests,
        # since missing integration tests is not an error
        self.has_unit = True
        if(not self._unit_test_class):
            self._log("No unit test class found")
            self.has_unit = False

    def report_header(self):
        """
        @brief Output report header containing system information.  i.e. metadata stored, comm config, etc.
        @param message message to be outputted
        """
        self._log( "****************************************" )
        self._log( "***   Starting Drive Test Process    ***" )
        self._log( "****************************************\n" )

        self._output_metadata()

    def run_unit(self):
        """
        @brief Run integration tests for a driver
        """
        if self.has_unit:
            self._log("*** Starting Unit Tests ***")
            self._log(" ==> module: " + self._driver_test_module())
            args=[sys.argv[0]]
            args += [self._unit_test_module_param()]
            module = "%s" % (self._driver_test_module())

            return self._run_nose(module, args)
        else:
            self._log("No unit tests to run")
            return True

    def _ingest_test_module_param(self):
        '''
        Module name and test to run
        @return: module name and optional test as string
        '''
        result = "%s:%s" % (self._ingest_test_filename(), self._ingest_test_class)
        if(self._testname): result = "%s.%s" % (result, self._testname)
        return result

    def _ingest_test_filename(self):
        return os.path.join(Config().base_dir(), "mi", "idk", "dataset", "unit_test.py")

    def run_ingestion(self, directory, runtime):
        """
        @brief Run a dataset agent and ingest files from the specified directory.  If
        runtime is set then stop running after x seconds.
        """
        self._log("Running ingestion test, directory: %s, runtime: %s" % (directory, runtime))

        # the data source key is used to identify harvester / parser combinations in
        # multiple harvester dataset driver configurations
        data_source_key = None

        # specific data source key can be provided using a ':' for testing multiple
        # harvester drivers, i.e. my_data_source_key:/tmp/dir
        # If there is no ':' then we assume only a single harvester config
        (pre, sep, post) = directory.partition(':')

        if len(post):
            # found a ':', set the directory and data source key
            ingest_dir = post
            data_source_key = pre
        else:
            # no ':', this is just the directory
            ingest_dir = pre

        # Dynamically load the driver test module so the IDK singleton is initialized
        test_module = __import__(self._driver_test_module())

        # Adjust the harvester config to point to the new directory
        if data_source_key is None:
            DataSetTestConfig().driver_startup_config['harvester']['directory'] = ingest_dir
        else:
            DataSetTestConfig().driver_startup_config['harvester'][data_source_key]['directory'] = ingest_dir

        # Add ingestion parameters to the singleton
        DataSetTestConfig().initialize_ingester_test(directory, runtime)

        args=[sys.argv[0]]
        args += [self._ingest_test_module_param()]
        module = "%s.%s" % ('mi.idk.dataset.unit_test', 'DataSetIngestionTestCase')

        self._log(" ==> module: " + module)
        self._log(" ==> args: %s" % args)

        return self._run_nose(module, args)

<|endoftext|>


<commit_before>import numpy as np

def template(current_block, previous_block, random_parameter):
    """This is just a no-op transformation for you to see what interface you should provide."""
    return current_block

def reverse(current_block, *args):
    """Reverses the data of the current block."""
    return current_block[::-1]

def diff(current_block, previous_block, *args):
    """Subtracts the previous block from the current block."""
    return (current_block - previous_block[:len(current_block)])

def fft(current_block, *args):
    F = np.fft.rfft(current_block)
    f = np.fft.irfft(F)
    return np.real(f)

def reduce(current_block, *args):
    N = 4
    F = np.fft.fft(current_block)

    indexes_of_N_max_values = np.imag(F).argsort()[::-1][:N]

    reduced_F = np.zeros(len(F)).astype(np.complex128)
    reduced_F[indexes_of_N_max_values] = F[indexes_of_N_max_values]

    return np.real(np.fft.ifft(reduced_F))

def random_frequency(current_block, previous_block, parameter):
    F = np.fft.rfft(current_block)

    index = np.floor((len(F)-1) * parameter / 4.0)

    reduced_F = np.zeros(len(F)).astype(np.complex128)
    reduced_F[index] = F[index]

    return np.real(np.fft.irfft(reduced_F))

def reverse_diff(current_block, *args):
    return diff(current_block, reverse(current_block))

def autocorr(x):
    result = np.correlate(x, x, mode='full')
    return result[result.size/2:]

def acf(current_block, *args):
    return autocorr(current_block)
<commit_msg>use np.real instead of np.imag<commit_after>import numpy as np

def template(current_block, previous_block, random_parameter):
    """This is just a no-op transformation for you to see what interface you should provide."""
    return current_block

def reverse(current_block, *args):
    """Reverses the data of the current block."""
    return current_block[::-1]

def diff(current_block, previous_block, *args):
    """Subtracts the previous block from the current block."""
    return (current_block - previous_block[:len(current_block)])

def fft(current_block, *args):
    F = np.fft.rfft(current_block)
    f = np.fft.irfft(F)
    return np.real(f)

def reduce(current_block, *args):
    N = 4
    F = np.fft.fft(current_block)

    indexes_of_N_max_values = np.real(F).argsort()[::-1][:N]

    reduced_F = np.zeros(len(F)).astype(np.complex128)
    reduced_F[indexes_of_N_max_values] = F[indexes_of_N_max_values]

    return np.real(np.fft.ifft(reduced_F))

def random_frequency(current_block, previous_block, parameter):
    F = np.fft.rfft(current_block)

    index = np.floor((len(F)-1) * parameter / 4.0)

    reduced_F = np.zeros(len(F)).astype(np.complex128)
    reduced_F[index] = F[index]

    return np.real(np.fft.irfft(reduced_F))

def reverse_diff(current_block, *args):
    return diff(current_block, reverse(current_block))

def autocorr(x):
    result = np.correlate(x, x, mode='full')
    return result[result.size/2:]

def acf(current_block, *args):
    return autocorr(current_block)
<|endoftext|>


<commit_before>#!/usr/bin/python3

# rpi.gpio documentation at https://sourceforge.net/p/raspberry-gpio-python/wiki/
import RPi.GPIO as GPIO
from time import sleep as sleep
import logging
import threading
import sqlite3 # used to write to the tts database
from nltk.tokenize import sent_tokenize # used by saythis() to break into sentences

class BmBB:
    """ interface with the controls and motors of the big mouth billy bass """

    # assign names to the GPIO pins.
    # fishMOUTH = 13 # The mouth is now controlled by hardware
    fishTAIL = 11
    fishHEAD = 7
    # fishHEAD_reverse = 15
    fishMotorEnable = 18
    fishIsSpeaking = 13

    # variables for SQlite
    dbconnect = None
    cursor = None

    # other variables
    PWMstatus = None #declaring PWMstatus here for later assignment
    SpeechWordObjects = []
    logger = None #declaring logger here for later use

    def __init__(self):
        GPIO.cleanup()

        GPIO.setmode(GPIO.BOARD) #use P1 header pin numbering convention

        # set up gpio pins for fish
        # GPIO.setup(self.fishMOUTH, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishTAIL, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishHEAD, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishIsSpeaking, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

        # set up PWM for the enable pin on the motor driver
        GPIO.setup(self.fishMotorEnable, GPIO.OUT)
        self.PWMstatus = GPIO.PWM(self.fishMotorEnable, 50) #frequency 50 hz
        self.PWMstatus.start(0) #duty cycle of zero. Enabled but silent

        # set up error logging
        self.logger = logging.getLogger('FishControl')
        hdlr = logging.FileHandler('/var/tmp/fish.log')
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        self.logger.addHandler(hdlr)
        self.logger.setLevel(logging.DEBUG)

        # set up SQLite
        self.dbconnect = sqlite3.connect("/home/pi/rubberfish/textToSpeech.db", check_same_thread=False)
        self.cursor = self.dbconnect.cursor()

    def shut_down_fish(self):
        self.logger.info('killing the fish')
        self.PWMstatus.stop() # turn off PWM
        GPIO.cleanup() #resets the GPIO state to neutral

    def mouth(self,fishDuration=.5,enthusiasm=50):
        pass # mouth is controlled by hardware. This function deprecated

    def head(self,fishDuration=.4,enthusiasm=60):
        self.logger.info('head: duration={durate}, enthusiasm={enth}.'.format(durate=fishDuration, enth=enthusiasm))
        self.headOut(enthusiasm)
        fishDuration = fishDuration if fishDuration < 1 else 1
        t = threading.Timer(fishDuration,self.headBack)
        t.start() # after 'fishDuration' seconds, the head will return

    def headOut(self,enthusiasm=60):
        self.logger.info('headOut: enthusiasm={enth}.'.format(enth=enthusiasm))
        enthusiasm = enthusiasm if enthusiasm < 60 else 60 # more than 60 will throw the head past it's limit
        self.adjustPWM(enthusiasm)
        GPIO.output(self.fishHEAD,GPIO.HIGH)

    def headBack(self):
        self.logger.info('headBack: No Parameters')
        GPIO.output(self.fishHEAD,GPIO.LOW)

    def tail(self,fishDuration=.4,enthusiasm=75):
        self.logger.info('tail: duration={durate}, enthusiasm={enth}.'.format(durate=fishDuration, enth=enthusiasm))
        self.tailOut(enthusiasm)
        fishDuration = fishDuration if fishDuration < 1 else 1
        t = threading.Timer(fishDuration,self.tailBack)
        t.start() # after 'fishDuration' seconds, the tail will return

    def tailOut(self,enthusiasm=75):
        self.logger.info('tailOut: enthusiasm={enth}.'.format(enth=enthusiasm))
        self.adjustPWM(enthusiasm)
        GPIO.output(self.fishTAIL,GPIO.HIGH)

    def tailBack(self):
        self.logger.info('tailBack: No Parameters')
        GPIO.output(self.fishTAIL,GPIO.LOW)

    def adjustPWM(self,PWMDutyCycle=50):
        # where 0.0 <= PWMDutyCycle <= 100.0
        PWMDutyCycle = 100 if PWMDutyCycle > 100 else PWMDutyCycle
        PWMDutyCycle = 0 if PWMDutyCycle < 0 else PWMDutyCycle
        self.PWMstatus.ChangeDutyCycle(PWMDutyCycle)

    def fishSays(self,phraseToSay="Hello World",priorityToSay=5):
        sqlDoThis = 'insert into TTS (priority,stringToSay) values (?, ?)'
        # break the phrase into sentences
        for aline in sent_tokenize(phraseToSay):
            if aline[-1:] == "?":
                # if this sentence is a question
                awords = aline.split(" ")
                saystring = " ".join(awords[:-1])
                saystring += '<prosody pitch="high">'
                saystring += " ".join(awords[-1:])
                saystring += '</prosody>'
            else:
                saystring = aline
            self.cursor.execute(sqlDoThis,[priorityToSay,saystring]);
            self.dbconnect.commit()

    def get_fishIsSpeaking(self):
        return GPIO.input(self.fishIsSpeaking)

    def fishShutUp(self):
        # stops the fish from talking
        pass
<commit_msg>setup nltk and punkt<commit_after>#!/usr/bin/python3

# rpi.gpio documentation at https://sourceforge.net/p/raspberry-gpio-python/wiki/
import RPi.GPIO as GPIO
from time import sleep as sleep
import logging
import threading
import sqlite3 # used to write to the tts database
from nltk.tokenize import sent_tokenize # used by saythis() to break into sentences
import nltk

class BmBB:
    """ interface with the controls and motors of the big mouth billy bass """

    # assign names to the GPIO pins.
    # fishMOUTH = 13 # The mouth is now controlled by hardware
    fishTAIL = 11
    fishHEAD = 7
    # fishHEAD_reverse = 15
    fishMotorEnable = 18
    fishIsSpeaking = 13

    # variables for SQlite
    dbconnect = None
    cursor = None

    # other variables
    PWMstatus = None #declaring PWMstatus here for later assignment
    SpeechWordObjects = []
    logger = None #declaring logger here for later use

    def __init__(self):
        GPIO.cleanup()

        GPIO.setmode(GPIO.BOARD) #use P1 header pin numbering convention

        # set up gpio pins for fish
        # GPIO.setup(self.fishMOUTH, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishTAIL, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishHEAD, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.fishIsSpeaking, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

        # set up PWM for the enable pin on the motor driver
        GPIO.setup(self.fishMotorEnable, GPIO.OUT)
        self.PWMstatus = GPIO.PWM(self.fishMotorEnable, 50) #frequency 50 hz
        self.PWMstatus.start(0) #duty cycle of zero. Enabled but silent

        # set up error logging
        self.logger = logging.getLogger('FishControl')
        hdlr = logging.FileHandler('/var/tmp/fish.log')
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        self.logger.addHandler(hdlr)
        self.logger.setLevel(logging.DEBUG)

        # set up SQLite
        self.dbconnect = sqlite3.connect("/home/pi/rubberfish/textToSpeech.db", check_same_thread=False)
        self.cursor = self.dbconnect.cursor()

        # set up nltk
        nltk.download('punkt')

    def shut_down_fish(self):
        self.logger.info('killing the fish')
        self.PWMstatus.stop() # turn off PWM
        GPIO.cleanup() #resets the GPIO state to neutral

    def mouth(self,fishDuration=.5,enthusiasm=50):
        pass # mouth is controlled by hardware. This function deprecated

    def head(self,fishDuration=.4,enthusiasm=60):
        self.logger.info('head: duration={durate}, enthusiasm={enth}.'.format(durate=fishDuration, enth=enthusiasm))
        self.headOut(enthusiasm)
        fishDuration = fishDuration if fishDuration < 1 else 1
        t = threading.Timer(fishDuration,self.headBack)
        t.start() # after 'fishDuration' seconds, the head will return

    def headOut(self,enthusiasm=60):
        self.logger.info('headOut: enthusiasm={enth}.'.format(enth=enthusiasm))
        enthusiasm = enthusiasm if enthusiasm < 60 else 60 # more than 60 will throw the head past it's limit
        self.adjustPWM(enthusiasm)
        GPIO.output(self.fishHEAD,GPIO.HIGH)

    def headBack(self):
        self.logger.info('headBack: No Parameters')
        GPIO.output(self.fishHEAD,GPIO.LOW)

    def tail(self,fishDuration=.4,enthusiasm=75):
        self.logger.info('tail: duration={durate}, enthusiasm={enth}.'.format(durate=fishDuration, enth=enthusiasm))
        self.tailOut(enthusiasm)
        fishDuration = fishDuration if fishDuration < 1 else 1
        t = threading.Timer(fishDuration,self.tailBack)
        t.start() # after 'fishDuration' seconds, the tail will return

    def tailOut(self,enthusiasm=75):
        self.logger.info('tailOut: enthusiasm={enth}.'.format(enth=enthusiasm))
        self.adjustPWM(enthusiasm)
        GPIO.output(self.fishTAIL,GPIO.HIGH)

    def tailBack(self):
        self.logger.info('tailBack: No Parameters')
        GPIO.output(self.fishTAIL,GPIO.LOW)

    def adjustPWM(self,PWMDutyCycle=50):
        # where 0.0 <= PWMDutyCycle <= 100.0
        PWMDutyCycle = 100 if PWMDutyCycle > 100 else PWMDutyCycle
        PWMDutyCycle = 0 if PWMDutyCycle < 0 else PWMDutyCycle
        self.PWMstatus.ChangeDutyCycle(PWMDutyCycle)

    def fishSays(self,phraseToSay="Hello World",priorityToSay=5):
        sqlDoThis = 'insert into TTS (priority,stringToSay) values (?, ?)'
        # break the phrase into sentences
        for aline in sent_tokenize(phraseToSay):
            if aline[-1:] == "?":
                # if this sentence is a question
                awords = aline.split(" ")
                saystring = " ".join(awords[:-1])
                saystring += '<prosody pitch="high">'
                saystring += " ".join(awords[-1:])
                saystring += '</prosody>'
            else:
                saystring = aline
            self.cursor.execute(sqlDoThis,[priorityToSay,saystring]);
            self.dbconnect.commit()

    def get_fishIsSpeaking(self):
        return GPIO.input(self.fishIsSpeaking)

    def fishShutUp(self):
        # stops the fish from talking
        pass
<|endoftext|>


<commit_before>import datetime

from django.http import Http404
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from django.shortcuts import render, get_object_or_404
from django.template import loader

from tracker.models import SocialExam
from tracker.models import SocialExamForm
from tracker.models import Signature
from tracker.models import SignatureForm
from tracker.models import Child

def index(request, child_id):
    list = SocialExam.objects.filter(child_id=child_id)
    child = get_object_or_404(Child, pk=child_id)
    context = {
        'SocialExams': list,
        'child_id': child_id,
        'child': child
    }
    return render(request, 'tracker/add_social_exam.html', context)

def new(request, child_id):
    child = get_object_or_404(Child, pk=child_id)
    if request.method == 'POST':
        signature_form = SignatureForm(request.POST, request.FILES, request=request)
        social_exam_form = SocialExamForm(request.POST, request.FILES, request=request)
        if 'discard' in request.POST:
            return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
        else:
            if signature_form.is_valid() and social_exam_form.is_valid():
                signature = signature_form.save()
                if signature:
                    social_exam = social_exam_form.save(commit=False)
                    social_exam.signature = signature
                    social_exam.child = child
                    social_exam.save()
                    social_exam_form.save_m2m()
                    if 'save' in request.POST:
                        return HttpResponseRedirect(reverse('tracker:edit_social_exam', kwargs={'child_id': child_id, 'exam_id': saved_exam.id}))
                    else:
                        return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
    else:
        social_exam_form = SocialExamForm(initial={
                'child': child,
                'child_id': child_id,
                'date': datetime.date.today(),
            }
        )
        signature_form = SignatureForm()
    social_exam_list = SocialExam.objects.filter(child_id=child_id)
    context = {
        'child': child,
        'child_id': child_id,
        'residence_id': child.residence_id,
        'social_exam_form': social_exam_form.as_ul,
        'signature_form': signature_form.as_ul,
        'SocialExams': social_exam_list,
    }
    return render(request, 'tracker/add_social_exam.html', context)

def view(request, child_id, exam_id):
    p = get_object_or_404(SocialExam, pk=exam_id)
    child = get_object_or_404(Child, pk=child_id)
    signature = get_object_or_404(Signature, pk=p.signature_id)
    context = {
        'exam': p,
        'child': child,
        'child_id': child.id,
        'residence_id': child.residence_id,
        'signature': signature,
    }
    return render(request, 'tracker/social_exam.html', context)

def edit(request, child_id, exam_id):
    child = get_object_or_404(Child, pk=child_id)
    exam = get_object_or_404(SocialExam, pk=exam_id)
    signature = get_object_or_404(Signature, pk=exam.signature_id)
    if request.method == 'POST':
        signature_form = SignatureForm(request.POST, request.FILES, instance=signature, request=request)
        exam_form = SocialExamForm(request.POST, request.FILES, instance=exam, request=request)
        if 'discard' in request.POST:
            return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
        else:
            if signature_form.is_valid() and exam_form.is_valid():
                saved_signature = signature_form.save()
                if saved_signature:
                    saved_exam = exam_form.save(commit=False)
                    saved_exam.signature = saved_signature
                    saved_exam.child = child
                    saved_exam.save()
                    exam_form.save_m2m()
                    if 'save' in request.POST:
                        return HttpResponseRedirect(reverse('tracker:edit_social_exam', kwargs={'child_id': child_id, 'exam_id': saved_exam.id}))
                    else:
                        return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
    else:
        exam_form = SocialExamForm(
            initial={
                'child': child,
                'child_id': child_id,
                'date': datetime.date.today(),
            }, instance=exam
        )
        signature_form = SignatureForm(instance=signature)
    social_exam_list = SocialExam.objects.filter(child_id=child_id)
    context = {
        'child': child,
        'child_id': child_id,
        'residence_id': child.residence_id,
        'exam_id': exam.id,
        'social_exam_form': exam_form.as_ul,
        'signature_form': signature_form.as_ul,
        'SocialExams': social_exam_list,
    }
    return render(request, 'tracker/edit_social_exam.html', context)

<commit_msg>Fix social exam view.<commit_after>import datetime

from django.http import Http404
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from django.shortcuts import render, get_object_or_404
from django.template import loader

from tracker.models import SocialExam
from tracker.models import SocialExamForm
from tracker.models import Signature
from tracker.models import SignatureForm
from tracker.models import Child

def index(request, child_id):
    list = SocialExam.objects.filter(child_id=child_id)
    child = get_object_or_404(Child, pk=child_id)
    context = {
        'SocialExams': list,
        'child_id': child_id,
        'child': child
    }
    return render(request, 'tracker/add_social_exam.html', context)

def new(request, child_id):
    child = get_object_or_404(Child, pk=child_id)
    if request.method == 'POST':
        signature_form = SignatureForm(request.POST, request.FILES, request=request)
        exam_form = SocialExamForm(request.POST, request.FILES, request=request)
        if 'discard' in request.POST:
            return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
        else:
            if signature_form.is_valid() and exam_form.is_valid():
                saved_signature = signature_form.save()
                if saved_signature:
                    saved_exam = exam_form.save(commit=False)
                    saved_exam.signature = saved_signature
                    saved_exam.child = child
                    saved_exam.save()
                    exam_form.save_m2m()
                    if 'save' in request.POST:
                        return HttpResponseRedirect(reverse('tracker:edit_social_exam', kwargs={'child_id': child_id, 'exam_id': saved_exam.id}))
                    else:
                        return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
    else:
        exam_form = SocialExamForm(initial={
                'child': child,
                'child_id': child_id,
                'date': datetime.date.today(),
            }
        )
        signature_form = SignatureForm()
    exam_list = SocialExam.objects.filter(child_id=child_id)
    context = {
        'child': child,
        'child_id': child_id,
        'residence_id': child.residence_id,
        'social_exam_form': exam_form.as_ul,
        'signature_form': signature_form.as_ul,
        'SocialExams': exam_list,
    }
    return render(request, 'tracker/add_social_exam.html', context)

def view(request, child_id, exam_id):
    p = get_object_or_404(SocialExam, pk=exam_id)
    child = get_object_or_404(Child, pk=child_id)
    signature = get_object_or_404(Signature, pk=p.signature_id)
    context = {
        'exam': p,
        'child': child,
        'child_id': child.id,
        'residence_id': child.residence_id,
        'signature': signature,
    }
    return render(request, 'tracker/social_exam.html', context)

def edit(request, child_id, exam_id):
    child = get_object_or_404(Child, pk=child_id)
    exam = get_object_or_404(SocialExam, pk=exam_id)
    signature = get_object_or_404(Signature, pk=exam.signature_id)
    if request.method == 'POST':
        signature_form = SignatureForm(request.POST, request.FILES, instance=signature, request=request)
        exam_form = SocialExamForm(request.POST, request.FILES, instance=exam, request=request)
        if 'discard' in request.POST:
            return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
        else:
            if signature_form.is_valid() and exam_form.is_valid():
                saved_signature = signature_form.save()
                if saved_signature:
                    saved_exam = exam_form.save(commit=False)
                    saved_exam.signature = saved_signature
                    saved_exam.child = child
                    saved_exam.save()
                    exam_form.save_m2m()
                    if 'save' in request.POST:
                        return HttpResponseRedirect(reverse('tracker:edit_social_exam', kwargs={'child_id': child_id, 'exam_id': saved_exam.id}))
                    else:
                        return HttpResponseRedirect(reverse('tracker:child', kwargs={'child_id': child_id}))
    else:
        exam_form = SocialExamForm(
            initial={
                'child': child,
                'child_id': child_id,
                'date': datetime.date.today(),
            }, instance=exam
        )
        signature_form = SignatureForm(instance=signature)
    exam_list = SocialExam.objects.filter(child_id=child_id)
    context = {
        'child': child,
        'child_id': child_id,
        'residence_id': child.residence_id,
        'exam_id': exam.id,
        'social_exam_form': exam_form.as_ul,
        'signature_form': signature_form.as_ul,
        'SocialExams': exam_list,
    }
    return render(request, 'tracker/edit_social_exam.html', context)

<|endoftext|>


<commit_before>import re

from io import BytesIO
from time import sleep

from livestreamer.exceptions import PluginError
from livestreamer.packages.flashmedia import AMFPacket, AMFMessage
from livestreamer.packages.flashmedia.types import AMF3ObjectBase
from livestreamer.plugin import Plugin
from livestreamer.plugin.api import http, validate
from livestreamer.stream import AkamaiHDStream

AMF_GATEWAY = "http://c.brightcove.com/services/messagebroker/amf"
AMF_MESSAGE_PREFIX = "af6b88c640c8d7b4cc75d22f7082ad95603bc627"
STREAM_NAMES = ["360p", "480p", "720p", "source"]
HTTP_HEADERS = {
    "User-Agent": ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
                   "(KHTML, like Gecko) Chrome/36.0.1944.9 Safari/537.36")
}

_url_re = re.compile("http(s)?://(\w+\.)?azubu.tv/(?P<domain>\w+)")
CHANNEL_INFO_URL = "http://api.azubu.tv/public/channel/%s"

_viewerexp_schema = validate.Schema(
    validate.attr({
        "programmedContent": {
            "videoPlayer": validate.attr({
                "mediaDTO": validate.attr({
                    "renditions": {
                        int: validate.attr({
                            "encodingRate": int,
                            "defaultURL": validate.text
                        })
                    }
                })
            })
        }
    })
)

@AMF3ObjectBase.register("com.brightcove.experience.ViewerExperienceRequest")
class ViewerExperienceRequest(AMF3ObjectBase):
    __members__ = ["contentOverrides",
                   "experienceId",
                   "URL",
                   "playerKey",
                   "deliveryType",
                   "TTLToken"]

    def __init__(self, URL, contentOverrides, experienceId, playerKey, TTLToken=""):
        self.URL = URL
        self.deliveryType = float("nan")
        self.contentOverrides = contentOverrides
        self.experienceId = experienceId
        self.playerKey = playerKey
        self.TTLToken = TTLToken

@AMF3ObjectBase.register("com.brightcove.experience.ContentOverride")
class ContentOverride(AMF3ObjectBase):
    __members__ = ["featuredRefId",
                   "contentRefIds",
                   "contentId",
                   "contentType",
                   "contentIds",
                   "featuredId",
                   "contentRefId",
                   "target"]

    def __init__(self, contentId=float("nan"), contentRefId=None, contentType=0,
                 target="videoPlayer"):
        self.contentType = contentType
        self.contentId = contentId
        self.target = target
        self.contentIds = None
        self.contentRefId = contentRefId
        self.contentRefIds = None
        self.contentType = 0
        self.featuredId = float("nan")
        self.featuredRefId = None

class AzubuTV(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    @classmethod
    def stream_weight(cls, stream):
        if stream == "source":
            weight = 1080
        else:
            weight, group = Plugin.stream_weight(stream)

        return weight, "azubutv"

    def _create_amf_request(self, key, video_player, player_id):
        if video_player.startswith("ref:"):
            content_override = ContentOverride(contentRefId=video_player[4:])
        else:
            content_override = ContentOverride(contentId=int(video_player))
        viewer_exp_req = ViewerExperienceRequest(self.url,
                                                [content_override],
                                                int(player_id), key)

        req = AMFPacket(version=3)
        req.messages.append(AMFMessage(
            "com.brightcove.experience.ExperienceRuntimeFacade.getDataForExperience",
            "/1",
            [AMF_MESSAGE_PREFIX, viewer_exp_req]
        ))

        return req

    def _send_amf_request(self, req, key):
        headers = {
            "content-type": "application/x-amf"
        }
        res = http.post(AMF_GATEWAY, data=bytes(req.serialize()),
                        headers=headers, params=dict(playerKey=key))

        return AMFPacket.deserialize(BytesIO(res.content))

    def _get_player_params(self, retries=5):
        try:
            res = http.get(self.url, headers=HTTP_HEADERS)
        except PluginError as err:
            # The server sometimes gives us 404 for no reason
            if "404" in str(err) and retries:
                sleep(1)
                return self._get_player_params(retries - 1)
            else:
                raise

        match = re.search("<param name=\"playerKey\" value=\"(.+)\" />", res.text)
        if not match:
            # The HTML returned sometimes doesn't contain the parameters
            if not retries:
                raise PluginError("Missing key 'playerKey' in player params")
            else:
                sleep(1)
                return self._get_player_params(retries - 1)

        key = match.group(1)
        match = re.search("AZUBU.setVar\(\"firstVideoRefId\", \"(.+)\"\);", res.text)
        if not match:
            # The HTML returned sometimes doesn't contain the parameters
            if not retries:
                raise PluginError("Unable to find video reference")
            else:
                sleep(1)
                return self._get_player_params(retries - 1)

        video_player = "ref:" + match.group(1)
        match = re.search("<param name=\"playerID\" value=\"(\d+)\" />", res.text)
        if not match:
            # The HTML returned sometimes doesn't contain the parameters
            if not retries:
                raise PluginError("Missing key 'playerID' in player params")
            else:
                sleep(1)
                return self._get_player_params(retries - 1)

        player_id = match.group(1)

        #get live status from api
        match = _url_re.match(self.url);
        domain = match.group('domain');
        channel_info = http.get(CHANNEL_INFO_URL % str(domain))
        info = http.json(channel_info)
        is_live = info['data']['is_live']

        return key, video_player, player_id, is_live

    def _parse_result(self, res):
        res = _viewerexp_schema.validate(res)
        player = res.programmedContent["videoPlayer"]
        renditions = sorted(player.mediaDTO.renditions.values(),
                            key=lambda r: r.encodingRate or 100000000)

        streams = {}
        for stream_name, rendition in zip(STREAM_NAMES, renditions):
            stream = AkamaiHDStream(self.session, rendition.defaultURL)
            streams[stream_name] = stream

        return streams

    def _get_streams(self):
        key, video_player, player_id, is_live = self._get_player_params()

        if not is_live:
            return

        req = self._create_amf_request(key, video_player, player_id)
        res = self._send_amf_request(req, key)

        streams = {}
        for message in res.messages:
            if message.target_uri == "/1/onResult":
                streams = self._parse_result(message.value)

        return streams

__plugin__ = AzubuTV
<commit_msg>use new api get stream info<commit_after>import re

from io import BytesIO
from time import sleep

from livestreamer.exceptions import PluginError
from livestreamer.packages.flashmedia import AMFPacket, AMFMessage
from livestreamer.packages.flashmedia.types import AMF3ObjectBase
from livestreamer.plugin import Plugin
from livestreamer.plugin.api import http, validate
from livestreamer.stream import AkamaiHDStream

AMF_GATEWAY = "http://c.brightcove.com/services/messagebroker/amf"
AMF_MESSAGE_PREFIX = "af6b88c640c8d7b4cc75d22f7082ad95603bc627"
STREAM_NAMES = ["360p", "480p", "720p", "source"]
HTTP_HEADERS = {
    "User-Agent": ("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 "
                   "(KHTML, like Gecko) Chrome/36.0.1944.9 Safari/537.36")
}

_url_re = re.compile("http(s)?://(\w+\.)?azubu.tv/(?P<domain>\w+)")
CHANNEL_INFO_URL = "http://api.azubu.tv/public/channel/%s/player"

_viewerexp_schema = validate.Schema(
    validate.attr({
        "programmedContent": {
            "videoPlayer": validate.attr({
                "mediaDTO": validate.attr({
                    "renditions": {
                        int: validate.attr({
                            "encodingRate": int,
                            "defaultURL": validate.text
                        })
                    }
                })
            })
        }
    })
)

@AMF3ObjectBase.register("com.brightcove.experience.ViewerExperienceRequest")
class ViewerExperienceRequest(AMF3ObjectBase):
    __members__ = ["contentOverrides",
                   "experienceId",
                   "URL",
                   "playerKey",
                   "deliveryType",
                   "TTLToken"]

    def __init__(self, URL, contentOverrides, experienceId, playerKey, TTLToken=""):
        self.URL = URL
        self.deliveryType = float("nan")
        self.contentOverrides = contentOverrides
        self.experienceId = experienceId
        self.playerKey = playerKey
        self.TTLToken = TTLToken

@AMF3ObjectBase.register("com.brightcove.experience.ContentOverride")
class ContentOverride(AMF3ObjectBase):
    __members__ = ["featuredRefId",
                   "contentRefIds",
                   "contentId",
                   "contentType",
                   "contentIds",
                   "featuredId",
                   "contentRefId",
                   "target"]

    def __init__(self, contentId=float("nan"), contentRefId=None, contentType=0,
                 target="videoPlayer"):
        self.contentType = contentType
        self.contentId = contentId
        self.target = target
        self.contentIds = None
        self.contentRefId = contentRefId
        self.contentRefIds = None
        self.contentType = 0
        self.featuredId = float("nan")
        self.featuredRefId = None

class AzubuTV(Plugin):
    @classmethod
    def can_handle_url(cls, url):
        return _url_re.match(url)

    @classmethod
    def stream_weight(cls, stream):
        if stream == "source":
            weight = 1080
        else:
            weight, group = Plugin.stream_weight(stream)

        return weight, "azubutv"

    def _create_amf_request(self, key, video_player, player_id):
        if video_player.startswith("ref:"):
            content_override = ContentOverride(contentRefId=video_player[4:])
        else:
            content_override = ContentOverride(contentId=int(video_player))
        viewer_exp_req = ViewerExperienceRequest(self.url,
                                                [content_override],
                                                int(player_id), key)

        req = AMFPacket(version=3)
        req.messages.append(AMFMessage(
            "com.brightcove.experience.ExperienceRuntimeFacade.getDataForExperience",
            "/1",
            [AMF_MESSAGE_PREFIX, viewer_exp_req]
        ))

        return req

    def _send_amf_request(self, req, key):
        headers = {
            "content-type": "application/x-amf"
        }
        res = http.post(AMF_GATEWAY, data=bytes(req.serialize()),
                        headers=headers, params=dict(playerKey=key))

        return AMFPacket.deserialize(BytesIO(res.content))

    def _get_player_params(self, retries=5):
        match = _url_re.match(self.url);
        domain = match.group('domain');
        try:
            res = http.get(CHANNEL_INFO_URL % str(domain))
        except PluginError as err:
            # The server sometimes gives us 404 for no reason
            if "404" in str(err) and retries:
                sleep(1)
                return self._get_player_params(retries - 1)
            else:
                raise
        channel_info = http.json(res)
        channel_info = channel_info['data']

        key = channel_info['player_key'];

        is_live = channel_info['is_live'];

        stream_video = channel_info['stream_video']
        if stream_video:
            video_player = stream_video['reference_id']
        else:
            is_live = False

        player_id = channel_info['player_id']

        return key, video_player, player_id, is_live

    def _parse_result(self, res):
        res = _viewerexp_schema.validate(res)
        player = res.programmedContent["videoPlayer"]
        renditions = sorted(player.mediaDTO.renditions.values(),
                            key=lambda r: r.encodingRate or 100000000)

        streams = {}
        for stream_name, rendition in zip(STREAM_NAMES, renditions):
            stream = AkamaiHDStream(self.session, rendition.defaultURL)
            streams[stream_name] = stream

        return streams

    def _get_streams(self):
        key, video_player, player_id, is_live = self._get_player_params()

        if not is_live:
            return

        req = self._create_amf_request(key, video_player, player_id)
        res = self._send_amf_request(req, key)

        streams = {}
        for message in res.messages:
            if message.target_uri == "/1/onResult":
                streams = self._parse_result(message.value)

        return streams

__plugin__ = AzubuTV
<|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
# encoding: utf-8
# The contents of this file are subject to the Mozilla Public License
# Version 2.0 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
#    http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# OS2Webscanner was developed by Magenta in collaboration with OS2 the
# Danish community of open source municipalities (http://www.os2web.dk/).
#
# The code is currently governed by OS2 the Danish community of open
# source municipalities ( http://www.os2web.dk/ )

from django.db import models

from .scanner_model import Scanner
from .filedomain_model import FileDomain

class FileScanner(Scanner):

    """File scanner for scanning network drives and folders"""

    domains = models.ManyToManyField(FileDomain, related_name='filedomains',
                                     verbose_name='Fil Domæner')

    def create_scan(self):
        """
        Creates a file scan.
        :return: A file scan object
        """
        # hvad kan gå galt: mount fejler, login er forkert,
        # login mangler, login skal slet ikke være der, stien til netværksdrev er forkert.
        for domain in self.domains.all():
            if not domain.smbmount():
                return FileDomain.MOUNT_FAILED

        from .filescan_model import FileScan
        return FileScan.create(self)

    def get_type(self):
        return 'file'

    def get_absolute_url(self):
        """Get the absolute URL for scanners."""
        return '/filescanners/'

    class Meta:
        db_table = 'os2webscanner_filescanner'
<commit_msg>* smb_mount method is renamed.<commit_after># -*- coding: UTF-8 -*-
# encoding: utf-8
# The contents of this file are subject to the Mozilla Public License
# Version 2.0 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
#    http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS"basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# OS2Webscanner was developed by Magenta in collaboration with OS2 the
# Danish community of open source municipalities (http://www.os2web.dk/).
#
# The code is currently governed by OS2 the Danish community of open
# source municipalities ( http://www.os2web.dk/ )

from django.db import models

from .scanner_model import Scanner
from .filedomain_model import FileDomain

class FileScanner(Scanner):

    """File scanner for scanning network drives and folders"""

    domains = models.ManyToManyField(FileDomain, related_name='filedomains',
                                     verbose_name='Fil Domæner')

    def create_scan(self):
        """
        Creates a file scan.
        :return: A file scan object
        """
        # hvad kan gå galt: mount fejler, login er forkert,
        # login mangler, login skal slet ikke være der, stien til netværksdrev er forkert.
        for domain in self.domains.all():
            if not domain.smb_mount():
                return FileDomain.MOUNT_FAILED

        from .filescan_model import FileScan
        return FileScan.create(self)

    def get_type(self):
        return 'file'

    def get_absolute_url(self):
        """Get the absolute URL for scanners."""
        return '/filescanners/'

    class Meta:
        db_table = 'os2webscanner_filescanner'
<|endoftext|>


<commit_before>#  Copyright (c) 2001-2016, Canal TP and/or its affiliates. All rights reserved.
#
# This file is part of Navitia,
#     the software to build cool stuff with public transport.
#
# Hope you'll enjoy and contribute to this project,
#     powered by Canal TP (www.canaltp.fr).
# Help us simplify mobility and open public transport:
#     a non ending quest to the responsive locomotion way of traveling!
#
# LICENCE: This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Stay tuned using
# twitter @navitia
# channel `#navitia` on riot https://riot.im/app/#/room/#navitia:matrix.org
# https://groups.google.com/d/forum/navitia
# www.navitia.io

from __future__ import absolute_import, print_function, unicode_literals, division
import logging
import copy

import jormungandr.street_network.utils
from jormungandr.exceptions import TechnicalError
from navitiacommon import request_pb2, type_pb2, response_pb2
from jormungandr.street_network.street_network import (
    AbstractStreetNetworkService,
    StreetNetworkPathType,
    StreetNetworkPathKey,
)
from jormungandr import utils
import six
from functools import cmp_to_key
from jormungandr.street_network.utils import crowfly_distance_between
from jormungandr.fallback_modes import FallbackModes

class Kraken(AbstractStreetNetworkService):
    def __init__(self, instance, service_url, modes=None, id=None, timeout=10, api_key=None, **kwargs):
        self.instance = instance
        self.modes = modes or []
        self.sn_system_id = id or 'kraken'

    def status(self):
        return {'id': six.text_type(self.sn_system_id), 'class': self.__class__.__name__, 'modes': self.modes}

    def _reverse_journeys(self, response):
        if not getattr(response, "journeys"):
            return response
        for j in response.journeys:
            if not getattr(j, "sections"):
                continue
            previous_section_begin = j.arrival_date_time
            for s in j.sections:
                o = copy.deepcopy(s.origin)
                d = copy.deepcopy(s.destination)
                s.origin.CopyFrom(d)
                s.destination.CopyFrom(o)
                s.end_date_time = previous_section_begin
                previous_section_begin = s.begin_date_time = s.end_date_time - s.duration
            j.sections.sort(key=cmp_to_key(utils.SectionSorter()))
        return response

    def _direct_path(
        self,
        instance,
        mode,
        pt_object_origin,
        pt_object_destination,
        fallback_extremity,
        request,
        direct_path_type,
        request_id,
    ):
        """
        :param direct_path_type: we need to "invert" a direct path when it's a ending fallback by car if and only if
                                 it's returned by kraken. In other case, it's ignored
        """
        should_invert_journey = mode == 'car' and direct_path_type == StreetNetworkPathType.ENDING_FALLBACK
        if should_invert_journey:
            pt_object_origin, pt_object_destination = pt_object_destination, pt_object_origin

        direct_path_request = {}
        for attr in [
            'walking_speed',
            'max_walking_duration_to_pt',
            'bike_speed',
            'max_bike_duration_to_pt',
            'bss_speed',
            'max_bss_duration_to_pt',
            'car_speed',
            'max_car_duration_to_pt',
            'car_no_park_speed',
            'max_car_no_park_duration_to_pt',
            'taxi_speed',
            'max_taxi_duration_to_pt',
            'ridesharing_speed',
            'max_ridesharing_duration_to_pt',
        ]:
            direct_path_request[attr] = request[attr]

        if direct_path_type == StreetNetworkPathType.DIRECT:
            # in distributed scenario, we allow the street network calculator to compute a very long direct path
            # in case of Kraken, the stop condition of direct path in Kraken is defined as
            # max_{mode}_duration_to_pt * 2.
            # When it comes to a direct path request, we override this parameter with
            # max_{mode}_direct_path_duration / 2.0
            from jormungandr.fallback_modes import FallbackModes as fm

            direct_path_request['max_{mode}_duration_to_pt'.format(mode=mode)] = int(
                request['max_{mode}_direct_path_duration'.format(mode=mode)] / 2
            )
            # if the crowfly distance between origin and destination is too large, there is no need to call kraken
            crowfly_distance = crowfly_distance_between(
                utils.get_pt_object_coord(pt_object_origin), utils.get_pt_object_coord(pt_object_destination)
            )

            if (
                crowfly_distance / float(direct_path_request['{mode}_speed'.format(mode=mode)])
                > request['max_{mode}_direct_path_duration'.format(mode=mode)]
            ):
                return response_pb2.Response()

        req = self._create_direct_path_request(
            mode, pt_object_origin, pt_object_destination, fallback_extremity, direct_path_request
        )

        response = instance.send_and_receive(req, request_id=request_id)
        if should_invert_journey:
            return self._reverse_journeys(response)

        def has_bss_section(journey):
            # Here is a little trick with python's generator
            # the next 3 lines check not only the existences of BSS_RENT and BSS_PUT_BACK, but also check the fact that
            # BSS_RENT must be located Before BSS_PUT_BACK
            sections = (s for s in journey.sections)
            bss_rent = next((True for s in sections if s.type == response_pb2.BSS_RENT), False)
            bss_put_back = next((True for s in sections if s.type == response_pb2.BSS_PUT_BACK), False)
            return bss_rent and bss_put_back

        if response.journeys:
            if mode == FallbackModes.bss.name and (not has_bss_section(response.journeys[0])):
                response.journeys[0].sections[0].street_network.mode = FallbackModes.walking.value
            else:
                response.journeys[0].sections[0].street_network.mode = FallbackModes[mode].value
        return response

    def _hanlde_car_no_park_modes(self, mode):
        if mode in (FallbackModes.ridesharing.name, FallbackModes.taxi.name, FallbackModes.car.name):
            return FallbackModes.car_no_park.name
        return mode

    def _create_direct_path_request(
        self, mode, pt_object_origin, pt_object_destination, fallback_extremity, request
    ):
        req = request_pb2.Request()
        req.requested_api = type_pb2.direct_path
        req.direct_path.origin.place = self.get_uri_pt_object(pt_object_origin)
        req.direct_path.origin.access_duration = 0
        req.direct_path.destination.place = self.get_uri_pt_object(pt_object_destination)
        req.direct_path.destination.access_duration = 0
        req.direct_path.datetime = fallback_extremity.datetime
        req.direct_path.clockwise = fallback_extremity.represents_start
        req.direct_path.streetnetwork_params.origin_mode = self._hanlde_car_no_park_modes(mode)
        req.direct_path.streetnetwork_params.destination_mode = self._hanlde_car_no_park_modes(mode)
        req.direct_path.streetnetwork_params.walking_speed = request['walking_speed']
        req.direct_path.streetnetwork_params.max_walking_duration_to_pt = request['max_walking_duration_to_pt']
        req.direct_path.streetnetwork_params.bike_speed = request['bike_speed']
        req.direct_path.streetnetwork_params.max_bike_duration_to_pt = request['max_bike_duration_to_pt']
        req.direct_path.streetnetwork_params.bss_speed = request['bss_speed']
        req.direct_path.streetnetwork_params.max_bss_duration_to_pt = request['max_bss_duration_to_pt']
        req.direct_path.streetnetwork_params.car_speed = request['car_speed']
        req.direct_path.streetnetwork_params.max_car_duration_to_pt = request['max_car_duration_to_pt']
        if mode in (
            FallbackModes.ridesharing.name,
            FallbackModes.taxi.name,
            FallbackModes.car_no_park.name,
            FallbackModes.car.name,
        ):
            req.direct_path.streetnetwork_params.car_no_park_speed = request['{}_speed'.format(mode)]
            req.direct_path.streetnetwork_params.max_car_no_park_duration_to_pt = request[
                'max_{}_duration_to_pt'.format(mode)
            ]

        return req

    def get_uri_pt_object(self, pt_object):
        return utils.get_uri_pt_object(pt_object)

    def get_street_network_routing_matrix(
        self, instance, origins, destinations, street_network_mode, max_duration, request, request_id, **kwargs
    ):
        # TODO: reverse is not handled as so far
        speed_switcher = jormungandr.street_network.utils.make_speed_switcher(request)

        # kraken can only manage 1-n request, so we reverse request if needed
        if len(origins) > 1:
            if len(destinations) > 1:
                logging.getLogger(__name__).error('routing matrix error, no unique center point')
                raise TechnicalError('routing matrix error, no unique center point')
            else:
                origins, destinations = destinations, origins

        req = self._create_sn_routing_matrix_request(
            origins, destinations, street_network_mode, max_duration, speed_switcher, **kwargs
        )

        res = instance.send_and_receive(req, request_id=request_id)
        self._check_for_error_and_raise(res)

        return res.sn_routing_matrix

    def _create_sn_routing_matrix_request(
        self, origins, destinations, street_network_mode, max_duration, speed_switcher, **kwargs
    ):
        req = request_pb2.Request()
        req.requested_api = type_pb2.street_network_routing_matrix

        req.sn_routing_matrix.origins.extend(
            (type_pb2.LocationContext(place=self.get_uri_pt_object(o), access_duration=0) for o in origins)
        )
        req.sn_routing_matrix.destinations.extend(
            (type_pb2.LocationContext(place=self.get_uri_pt_object(d), access_duration=0) for d in destinations)
        )

        req.sn_routing_matrix.mode = self._hanlde_car_no_park_modes(street_network_mode)
        req.sn_routing_matrix.speed = speed_switcher.get(street_network_mode, kwargs.get("walking"))
        req.sn_routing_matrix.max_duration = max_duration

        return req

    def _check_for_error_and_raise(self, res):
        if res.HasField('error'):
            logging.getLogger(__name__).error('routing matrix query error {}'.format(res.error))
            raise TechnicalError('routing matrix fail')

    def make_path_key(self, mode, orig_uri, dest_uri, streetnetwork_path_type, period_extremity):
        """
        :param orig_uri, dest_uri, mode: matters obviously
        :param streetnetwork_path_type: whether it's a fallback at
        the beginning, the end of journey or a direct path without PT also matters especially for car (to know if we
        park before or after)
        :param period_extremity: is a PeriodExtremity (a datetime and its meaning on the
        fallback period)
        Nota: period_extremity is not taken into consideration so far because we assume that a
        direct path from A to B remains the same even the departure time are different (no realtime)
        """
        return StreetNetworkPathKey(mode, orig_uri, dest_uri, streetnetwork_path_type, None)
<commit_msg>fix after review<commit_after>#  Copyright (c) 2001-2016, Canal TP and/or its affiliates. All rights reserved.
#
# This file is part of Navitia,
#     the software to build cool stuff with public transport.
#
# Hope you'll enjoy and contribute to this project,
#     powered by Canal TP (www.canaltp.fr).
# Help us simplify mobility and open public transport:
#     a non ending quest to the responsive locomotion way of traveling!
#
# LICENCE: This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Stay tuned using
# twitter @navitia
# channel `#navitia` on riot https://riot.im/app/#/room/#navitia:matrix.org
# https://groups.google.com/d/forum/navitia
# www.navitia.io

from __future__ import absolute_import, print_function, unicode_literals, division
import logging
import copy

import jormungandr.street_network.utils
from jormungandr.exceptions import TechnicalError
from navitiacommon import request_pb2, type_pb2, response_pb2
from jormungandr.street_network.street_network import (
    AbstractStreetNetworkService,
    StreetNetworkPathType,
    StreetNetworkPathKey,
)
from jormungandr import utils
import six
from functools import cmp_to_key
from jormungandr.street_network.utils import crowfly_distance_between
from jormungandr.fallback_modes import FallbackModes

class Kraken(AbstractStreetNetworkService):
    def __init__(self, instance, service_url, modes=None, id=None, timeout=10, api_key=None, **kwargs):
        self.instance = instance
        self.modes = modes or []
        self.sn_system_id = id or 'kraken'

    def status(self):
        return {'id': six.text_type(self.sn_system_id), 'class': self.__class__.__name__, 'modes': self.modes}

    def _reverse_journeys(self, response):
        if not getattr(response, "journeys"):
            return response
        for j in response.journeys:
            if not getattr(j, "sections"):
                continue
            previous_section_begin = j.arrival_date_time
            for s in j.sections:
                o = copy.deepcopy(s.origin)
                d = copy.deepcopy(s.destination)
                s.origin.CopyFrom(d)
                s.destination.CopyFrom(o)
                s.end_date_time = previous_section_begin
                previous_section_begin = s.begin_date_time = s.end_date_time - s.duration
            j.sections.sort(key=cmp_to_key(utils.SectionSorter()))
        return response

    def _direct_path(
        self,
        instance,
        mode,
        pt_object_origin,
        pt_object_destination,
        fallback_extremity,
        request,
        direct_path_type,
        request_id,
    ):
        """
        :param direct_path_type: we need to "invert" a direct path when it's a ending fallback by car if and only if
                                 it's returned by kraken. In other case, it's ignored
        """
        should_invert_journey = mode == 'car' and direct_path_type == StreetNetworkPathType.ENDING_FALLBACK
        if should_invert_journey:
            pt_object_origin, pt_object_destination = pt_object_destination, pt_object_origin

        direct_path_request = {}
        for attr in [
            'walking_speed',
            'max_walking_duration_to_pt',
            'bike_speed',
            'max_bike_duration_to_pt',
            'bss_speed',
            'max_bss_duration_to_pt',
            'car_speed',
            'max_car_duration_to_pt',
            'car_no_park_speed',
            'max_car_no_park_duration_to_pt',
            'taxi_speed',
            'max_taxi_duration_to_pt',
            'ridesharing_speed',
            'max_ridesharing_duration_to_pt',
        ]:
            direct_path_request[attr] = request[attr]

        if direct_path_type == StreetNetworkPathType.DIRECT:
            # in distributed scenario, we allow the street network calculator to compute a very long direct path
            # in case of Kraken, the stop condition of direct path in Kraken is defined as
            # max_{mode}_duration_to_pt * 2.
            # When it comes to a direct path request, we override this parameter with
            # max_{mode}_direct_path_duration / 2.0
            from jormungandr.fallback_modes import FallbackModes as fm

            direct_path_request['max_{mode}_duration_to_pt'.format(mode=mode)] = int(
                request['max_{mode}_direct_path_duration'.format(mode=mode)] / 2
            )
            # if the crowfly distance between origin and destination is too large, there is no need to call kraken
            crowfly_distance = crowfly_distance_between(
                utils.get_pt_object_coord(pt_object_origin), utils.get_pt_object_coord(pt_object_destination)
            )

            if (
                crowfly_distance / float(direct_path_request['{mode}_speed'.format(mode=mode)])
                > request['max_{mode}_direct_path_duration'.format(mode=mode)]
            ):
                return response_pb2.Response()

        req = self._create_direct_path_request(
            mode, pt_object_origin, pt_object_destination, fallback_extremity, direct_path_request
        )

        response = instance.send_and_receive(req, request_id=request_id)
        if should_invert_journey:
            response = self._reverse_journeys(response)

        def has_bss_rent_before_put_back_section(journey):
            # Here is a little trick with python's generator
            # the next 3 lines check not only the existences of BSS_RENT and BSS_PUT_BACK, but also check the fact that
            # BSS_RENT must be located Before BSS_PUT_BACK
            sections = (s for s in journey.sections)
            bss_rent = next((True for s in sections if s.type == response_pb2.BSS_RENT), False)
            bss_put_back = next((True for s in sections if s.type == response_pb2.BSS_PUT_BACK), False)
            return bss_rent and bss_put_back

        if response.journeys:
            # Note that: the journey returned by Kraken is a direct path. A direct path of walking/bike/car/car_no_park/
            # contains only one section. But for bss, there may be one or three sections.
            # For bss,we only need attribute the mode to the first section. The most significant mode will be chosen
            # later
            if mode == FallbackModes.bss.name and (
                not has_bss_rent_before_put_back_section(response.journeys[0])
            ):
                response.journeys[0].sections[0].street_network.mode = FallbackModes.walking.value
            else:
                response.journeys[0].sections[0].street_network.mode = FallbackModes[mode].value
        return response

    def _hanlde_car_no_park_modes(self, mode):
        if mode in (FallbackModes.ridesharing.name, FallbackModes.taxi.name, FallbackModes.car.name):
            return FallbackModes.car_no_park.name
        return mode

    def _create_direct_path_request(
        self, mode, pt_object_origin, pt_object_destination, fallback_extremity, request
    ):
        req = request_pb2.Request()
        req.requested_api = type_pb2.direct_path
        req.direct_path.origin.place = self.get_uri_pt_object(pt_object_origin)
        req.direct_path.origin.access_duration = 0
        req.direct_path.destination.place = self.get_uri_pt_object(pt_object_destination)
        req.direct_path.destination.access_duration = 0
        req.direct_path.datetime = fallback_extremity.datetime
        req.direct_path.clockwise = fallback_extremity.represents_start
        req.direct_path.streetnetwork_params.origin_mode = self._hanlde_car_no_park_modes(mode)
        req.direct_path.streetnetwork_params.destination_mode = self._hanlde_car_no_park_modes(mode)
        req.direct_path.streetnetwork_params.walking_speed = request['walking_speed']
        req.direct_path.streetnetwork_params.max_walking_duration_to_pt = request['max_walking_duration_to_pt']
        req.direct_path.streetnetwork_params.bike_speed = request['bike_speed']
        req.direct_path.streetnetwork_params.max_bike_duration_to_pt = request['max_bike_duration_to_pt']
        req.direct_path.streetnetwork_params.bss_speed = request['bss_speed']
        req.direct_path.streetnetwork_params.max_bss_duration_to_pt = request['max_bss_duration_to_pt']
        req.direct_path.streetnetwork_params.car_speed = request['car_speed']
        req.direct_path.streetnetwork_params.max_car_duration_to_pt = request['max_car_duration_to_pt']
        if mode in (
            FallbackModes.ridesharing.name,
            FallbackModes.taxi.name,
            FallbackModes.car_no_park.name,
            FallbackModes.car.name,
        ):
            req.direct_path.streetnetwork_params.car_no_park_speed = request['{}_speed'.format(mode)]
            req.direct_path.streetnetwork_params.max_car_no_park_duration_to_pt = request[
                'max_{}_duration_to_pt'.format(mode)
            ]

        return req

    def get_uri_pt_object(self, pt_object):
        return utils.get_uri_pt_object(pt_object)

    def get_street_network_routing_matrix(
        self, instance, origins, destinations, street_network_mode, max_duration, request, request_id, **kwargs
    ):
        # TODO: reverse is not handled as so far
        speed_switcher = jormungandr.street_network.utils.make_speed_switcher(request)

        # kraken can only manage 1-n request, so we reverse request if needed
        if len(origins) > 1:
            if len(destinations) > 1:
                logging.getLogger(__name__).error('routing matrix error, no unique center point')
                raise TechnicalError('routing matrix error, no unique center point')
            else:
                origins, destinations = destinations, origins

        req = self._create_sn_routing_matrix_request(
            origins, destinations, street_network_mode, max_duration, speed_switcher, **kwargs
        )

        res = instance.send_and_receive(req, request_id=request_id)
        self._check_for_error_and_raise(res)

        return res.sn_routing_matrix

    def _create_sn_routing_matrix_request(
        self, origins, destinations, street_network_mode, max_duration, speed_switcher, **kwargs
    ):
        req = request_pb2.Request()
        req.requested_api = type_pb2.street_network_routing_matrix

        req.sn_routing_matrix.origins.extend(
            (type_pb2.LocationContext(place=self.get_uri_pt_object(o), access_duration=0) for o in origins)
        )
        req.sn_routing_matrix.destinations.extend(
            (type_pb2.LocationContext(place=self.get_uri_pt_object(d), access_duration=0) for d in destinations)
        )

        req.sn_routing_matrix.mode = self._hanlde_car_no_park_modes(street_network_mode)
        req.sn_routing_matrix.speed = speed_switcher.get(street_network_mode, kwargs.get("walking"))
        req.sn_routing_matrix.max_duration = max_duration

        return req

    def _check_for_error_and_raise(self, res):
        if res.HasField('error'):
            logging.getLogger(__name__).error('routing matrix query error {}'.format(res.error))
            raise TechnicalError('routing matrix fail')

    def make_path_key(self, mode, orig_uri, dest_uri, streetnetwork_path_type, period_extremity):
        """
        :param orig_uri, dest_uri, mode: matters obviously
        :param streetnetwork_path_type: whether it's a fallback at
        the beginning, the end of journey or a direct path without PT also matters especially for car (to know if we
        park before or after)
        :param period_extremity: is a PeriodExtremity (a datetime and its meaning on the
        fallback period)
        Nota: period_extremity is not taken into consideration so far because we assume that a
        direct path from A to B remains the same even the departure time are different (no realtime)
        """
        return StreetNetworkPathKey(mode, orig_uri, dest_uri, streetnetwork_path_type, None)
<|endoftext|>