<commit_before>import pandas as pd
from snorkel.models import StableLabel
from snorkel.db_helpers import reload_annotator_labels

FPATH = 'data/gold_labels.tsv'

def number_of_people(sentence):
    active_sequence = False
    count = 0
    for tag in sentence.ner_tags:
        if tag == 'PERSON' and not active_sequence:
            active_sequence = True
            count += 1
        elif tag != 'PERSON' and active_sequence:
            active_sequence = False
    return count

def load_external_labels(session, candidate_class, annotator_name='gold'):
    gold_labels = pd.read_csv(FPATH, sep="\t")
    for index, row in gold_labels.iterrows():

        # We check if the label already exists, in case this cell was already executed
        context_stable_ids = "~~".join([row['person1'], row['person2']])
        query = session.query(StableLabel).filter(StableLabel.context_stable_ids == context_stable_ids)
        query = query.filter(StableLabel.annotator_name == annotator_name)
        if query.count() == 0:
            session.add(StableLabel(
                context_stable_ids=context_stable_ids,
                annotator_name=annotator_name,
                value=row['label']))

        # Because it's a symmetric relation, load both directions...
        context_stable_ids = "~~".join([row['person2'], row['person1']])
        query = session.query(StableLabel).filter(StableLabel.context_stable_ids == context_stable_ids)
        query = query.filter(StableLabel.annotator_name == annotator_name)
        if query.count() == 0:
            session.add(StableLabel(
                context_stable_ids=context_stable_ids,
                annotator_name=annotator_name,
                value=row['label']))

    # Commit session
    session.commit()

    # Reload annotator labels
    reload_annotator_labels(session, candidate_class, annotator_name, split=1, filter_label_split=False)
    reload_annotator_labels(session, candidate_class, annotator_name, split=2, filter_label_split=False)
<commit_msg>Intro tutorial runs but problem with gold label alignment, due to string parsing perhaps<commit_after>from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from builtins import *

import pandas as pd
from snorkel.models import StableLabel
from snorkel.db_helpers import reload_annotator_labels

FPATH = 'data/gold_labels.tsv'

def number_of_people(sentence):
    active_sequence = False
    count = 0
    for tag in sentence.ner_tags:
        if tag == 'PERSON' and not active_sequence:
            active_sequence = True
            count += 1
        elif tag != 'PERSON' and active_sequence:
            active_sequence = False
    return count

def load_external_labels(session, candidate_class, annotator_name='gold'):
    gold_labels = pd.read_csv(FPATH, sep="\t")
    for index, row in gold_labels.iterrows():

        # We check if the label already exists, in case this cell was already executed
        context_stable_ids = "~~".join([row['person1'], row['person2']])
        query = session.query(StableLabel).filter(StableLabel.context_stable_ids == context_stable_ids)
        query = query.filter(StableLabel.annotator_name == annotator_name)
        if query.count() == 0:
            session.add(StableLabel(
                context_stable_ids=context_stable_ids,
                annotator_name=annotator_name,
                value=row['label']))

        # Because it's a symmetric relation, load both directions...
        context_stable_ids = "~~".join([row['person2'], row['person1']])
        query = session.query(StableLabel).filter(StableLabel.context_stable_ids == context_stable_ids)
        query = query.filter(StableLabel.annotator_name == annotator_name)
        if query.count() == 0:
            session.add(StableLabel(
                context_stable_ids=context_stable_ids,
                annotator_name=annotator_name,
                value=row['label']))

    # Commit session
    session.commit()

    # Reload annotator labels
    reload_annotator_labels(session, candidate_class, annotator_name, split=1, filter_label_split=False)
    reload_annotator_labels(session, candidate_class, annotator_name, split=2, filter_label_split=False)<|endoftext|>


<commit_before>from time import time
from functools import wraps
__all__ = ['measure', 'measure_each']

def print_metric(name, count, elapsed):
    """A metric function that prints

    :arg str name: name of the metric
    :arg int count: number of elements
    :arg float elapsed: time in seconds
    """
    if name is not None:
        print("%s: %d elements in %.2f seconds"%(name, count, elapsed))
    else:
        print("%d elements in %.2f seconds"%(count, elapsed))

def measure(iterable, metric = print_metric, name = None):
    """Measure total time and element count for consuming an iterable

    :arg iterable: any iterable
    :arg function metric: f(name, count, total_time)
    :arg str name: name for the metric
    """
    total_time = 0
    count = 0
    it = enumerate(iterable, 1) # count, element
    try:
        while True:
            t = time()
            try:
                count, x = next(it)
            finally:
                total_time += time() - t
            yield x
    finally:
        # underlying iterable is exhausted (StopIteration) or errored. Record
        # the `metric` and allow exception to propogate
        metric(name, count, total_time)

def measure_each(iterable, metric = print_metric, name = None):
    """Measure time elapsed to produce each item of an iterable

    :arg iterable: any iterable
    :arg function metric: f(name, 1, time)
    :arg str name: name for the metric
    """
    it = iter(iterable)
    while True:
        t = time()
        try:
            x = next(it)
        except StopIteration:
            # don't record a metric for final next() call
            raise
        except Exception:
            # record a metric for other exceptions, than raise
            metric(name, 1, time() - t)
            raise
        else:
            # normal path, record metric and yield
            metric(name, 1, time() - t)
            yield x

def _make_decorator(measuring_func):
    """morass of closures for making decorators/descriptors"""
    def _decorator(metric = print_metric, name = None):
        def wrapper(func):

            name_ = name if name is not None else func.__module__ + '.' +func.__name__
            class measure_it_decorator(object): # must be a class for descriptor magic to work
                @wraps(func)
                def __call__(self, *args, **kwargs):
                    return measuring_func(func(*args, **kwargs), metric, name_)

                def __get__(self, instance, class_):
                    name_ = name if name is not None else\
                        ".".join((class_.__module__, class_.__name__, func.__name__))
                    @wraps(func)
                    def wrapped_method(*args, **kwargs):
                        return measuring_func(func(instance, *args, **kwargs), metric, name_)
                    return wrapped_method
            return measure_it_decorator()

        return wrapper
    return _decorator

measure.func = _make_decorator(measure)
measure_each.func = _make_decorator(measure_each)

try:
    from statsd import statsd, StatsClient
    if statsd is None: statsd = StatsClient()
except ImportError:
    pass
else:
    def statsd_metric(name, count, elapsed):
        """Metric that records to `statsd`"""
        with statsd.pipeline as pipe:
            pipe.incr(name, count)
            pipe.timing(name, int(round(1000 * dt)))  # milliseconds<commit_msg>fix bugs in statsd_metric<commit_after>from time import time
from functools import wraps
__all__ = ['measure', 'measure_each']

def print_metric(name, count, elapsed):
    """A metric function that prints

    :arg str name: name of the metric
    :arg int count: number of elements
    :arg float elapsed: time in seconds
    """
    if name is not None:
        print("%s: %d elements in %.2f seconds"%(name, count, elapsed))
    else:
        print("%d elements in %.2f seconds"%(count, elapsed))

def measure(iterable, metric = print_metric, name = None):
    """Measure total time and element count for consuming an iterable

    :arg iterable: any iterable
    :arg function metric: f(name, count, total_time)
    :arg str name: name for the metric
    """
    total_time = 0
    count = 0
    it = enumerate(iterable, 1) # count, element
    try:
        while True:
            t = time()
            try:
                count, x = next(it)
            finally:
                total_time += time() - t
            yield x
    finally:
        # underlying iterable is exhausted (StopIteration) or errored. Record
        # the `metric` and allow exception to propogate
        metric(name, count, total_time)

def measure_each(iterable, metric = print_metric, name = None):
    """Measure time elapsed to produce each item of an iterable

    :arg iterable: any iterable
    :arg function metric: f(name, 1, time)
    :arg str name: name for the metric
    """
    it = iter(iterable)
    while True:
        t = time()
        try:
            x = next(it)
        except StopIteration:
            # don't record a metric for final next() call
            raise
        except Exception:
            # record a metric for other exceptions, than raise
            metric(name, 1, time() - t)
            raise
        else:
            # normal path, record metric and yield
            metric(name, 1, time() - t)
            yield x

def _make_decorator(measuring_func):
    """morass of closures for making decorators/descriptors"""
    def _decorator(metric = print_metric, name = None):
        def wrapper(func):

            name_ = name if name is not None else func.__module__ + '.' +func.__name__
            class measure_it_decorator(object): # must be a class for descriptor magic to work
                @wraps(func)
                def __call__(self, *args, **kwargs):
                    return measuring_func(func(*args, **kwargs), metric, name_)

                def __get__(self, instance, class_):
                    name_ = name if name is not None else\
                        ".".join((class_.__module__, class_.__name__, func.__name__))
                    @wraps(func)
                    def wrapped_method(*args, **kwargs):
                        return measuring_func(func(instance, *args, **kwargs), metric, name_)
                    return wrapped_method
            return measure_it_decorator()

        return wrapper
    return _decorator

measure.func = _make_decorator(measure)
measure_each.func = _make_decorator(measure_each)

try:
    from statsd import statsd, StatsClient
    if statsd is None: statsd = StatsClient()
except ImportError:
    pass
else:
    def statsd_metric(name, count, elapsed):
        """Metric that records to `statsd`"""
        with statsd.pipeline() as pipe:
            pipe.incr(name, count)
            pipe.timing(name, int(round(1000 * elapsed)))  # milliseconds<|endoftext|>


<commit_before>def generate_ngrams(text, n):
    ''' Generates all possible n-grams of a
    piece of text

    >>> text = 'this is a random piece'
    >>> n = 2
    >>> generate_ngrams(text, n)
    this is
    is a
    a random
    random piece
    '''
    text_array = text.split(' ')
    for i in range(0, len(text_array) - n + 1):
        print text_array[i:i + n]

generate_ngrams('this is a random piece', 2)
generate_ngrams('this is a random piece', 3)
<commit_msg>Return a list of lists<commit_after>def generate_ngrams(text, n):
    ''' Generates all possible n-grams of a
    piece of text

    >>> text = 'this is a random piece'
    >>> n = 2
    >>> generate_ngrams(text, n)
    this is
    is a
    a random
    random piece
    '''
    text_array = text.split(' ')
    ngram_list = []
    for i in range(0, len(text_array) - n + 1):
        ngram_list.append(text_array[i:i + n])
    return ngram_list

print generate_ngrams('this is a random piece', 2)
print generate_ngrams('this is a random piece', 3)
print generate_ngrams('this is a random piece', 4)
<|endoftext|>


<commit_before>import os
from pkg_resources import DistributionNotFound, get_distribution
from six.moves.configparser import SafeConfigParser

from . import log_utils

try:
    __version__ = get_distribution(__name__).version
except DistributionNotFound:
    # package is not installed
    pass

__license__ = 'Apache 2.0'

PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
# Read the configuration files
_cfgs = ('worker.dist.cfg', 'worker.local.cfg')

config = SafeConfigParser({
    'RABBITMQ_USER': os.environ.get('RABBITMQ_USER', 'guest'),
    'RABBITMQ_PASS': os.environ.get('RABBITMQ_PASS', 'guest'),
    'RABBITMQ_HOST': os.environ.get('RABBITMQ_HOST', 'localhost')
})

config.read([os.path.join(PACKAGE_DIR, f) for f in _cfgs])

# Create and configure our logger
logger = log_utils.setupLogger(config)

class GirderWorkerPluginABC(object):
    """
    Abstract base class for Girder Worker plugins. Plugins must descend from this
    class; see the :ref:`plugins` section for more information.
    """
    def __init__(*args, **kwargs):
        pass

    def task_imports(self):
        """Plugins should override this method if they have tasks."""
        return []

class GirderWorkerPlugin(GirderWorkerPluginABC):

    def __init__(self, app, *args, **kwargs):
        self.app = app

    def task_imports(self):
        return ['girder_worker.tasks']
<commit_msg>Import ConfigParser, not SafeConfigParser<commit_after>import os
from pkg_resources import DistributionNotFound, get_distribution
from configparser import ConfigParser

from . import log_utils

try:
    __version__ = get_distribution(__name__).version
except DistributionNotFound:
    # package is not installed
    pass

__license__ = 'Apache 2.0'

PACKAGE_DIR = os.path.dirname(os.path.abspath(__file__))
# Read the configuration files
_cfgs = ('worker.dist.cfg', 'worker.local.cfg')

config = ConfigParser({
    'RABBITMQ_USER': os.environ.get('RABBITMQ_USER', 'guest'),
    'RABBITMQ_PASS': os.environ.get('RABBITMQ_PASS', 'guest'),
    'RABBITMQ_HOST': os.environ.get('RABBITMQ_HOST', 'localhost')
})

config.read([os.path.join(PACKAGE_DIR, f) for f in _cfgs])

# Create and configure our logger
logger = log_utils.setupLogger(config)

class GirderWorkerPluginABC(object):
    """
    Abstract base class for Girder Worker plugins. Plugins must descend from this
    class; see the :ref:`plugins` section for more information.
    """
    def __init__(*args, **kwargs):
        pass

    def task_imports(self):
        """Plugins should override this method if they have tasks."""
        return []

class GirderWorkerPlugin(GirderWorkerPluginABC):

    def __init__(self, app, *args, **kwargs):
        self.app = app

    def task_imports(self):
        return ['girder_worker.tasks']
<|endoftext|>


<commit_before>import pytest
import sys
import os
sys.path.insert(0, os.path.dirname(__file__)+"/../krobot")
import data
import datetime
#import mock
import time
import communication

def test_Communication():
    ruList = []
    personList = []
    comm = communication.Communication(personList, ruList)
    comm.startBot()
    comm.printMenus()
<commit_msg>correction for Travis<commit_after>import pytest
import sys
import os
sys.path.insert(0, os.path.dirname(__file__)+"/../krobot")
import data
import datetime
#import mock
import time
import communication

# Rémi, you definetely need to make a test that tests something, and not just call functions :)
def test_Communication():
    ruList = []
    personList = []
    #comm = communication.Communication(personList, ruList)
    #comm.startBot()
    #comm.printMenus()
<|endoftext|>


<commit_before>"""
Support for ZigBee Home Automation devices.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/zha/
"""
import asyncio
import logging

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant import const as ha_const
from homeassistant.helpers import discovery, entity
from homeassistant.util import slugify

REQUIREMENTS = ['bellows==0.2.7']

DOMAIN = 'zha'

CONF_USB_PATH = 'usb_path'
CONF_DATABASE = 'database_path'
CONF_DEVICE_CONFIG = 'device_config'
DATA_DEVICE_CONFIG = 'zha_device_config'

DEVICE_CONFIG_SCHEMA_ENTRY = vol.Schema({
    vol.Optional(ha_const.CONF_TYPE): cv.string,
})

CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.Schema({
        CONF_USB_PATH: cv.string,
        CONF_DATABASE: cv.string,
        vol.Optional(CONF_DEVICE_CONFIG, default={}):
            vol.Schema({cv.string: DEVICE_CONFIG_SCHEMA_ENTRY}),
    })
}, extra=vol.ALLOW_EXTRA)

ATTR_DURATION = 'duration'

SERVICE_PERMIT = 'permit'
SERVICE_DESCRIPTIONS = {
    SERVICE_PERMIT: {
        "description": "Allow nodes to join the Zigbee network",
        "fields": {
            "duration": {
                "description": "Time to permit joins, in seconds",
                "example": "60",
            },
        },
    },
}
SERVICE_SCHEMAS = {
    SERVICE_PERMIT: vol.Schema({
        vol.Optional(ATTR_DURATION, default=60):
            vol.All(vol.Coerce(int), vol.Range(1, 254)),
    }),
}

# ZigBee definitions
CENTICELSIUS = 'C-100'
# Key in hass.data dict containing discovery info
DISCOVERY_KEY = 'zha_discovery_info'

# Internal definitions
APPLICATION_CONTROLLER = None
_LOGGER = logging.getLogger(__name__)

@asyncio.coroutine
def async_setup(hass, config):
    """Set up ZHA.

    Will automatically load components to support devices found on the network.
    """
    global APPLICATION_CONTROLLER

    import bellows.ezsp
    from bellows.zigbee.application import ControllerApplication

    ezsp_ = bellows.ezsp.EZSP()
    usb_path = config[DOMAIN].get(CONF_USB_PATH)
    yield from ezsp_.connect(usb_path)

    database = config[DOMAIN].get(CONF_DATABASE)
    APPLICATION_CONTROLLER = ControllerApplication(ezsp_, database)
    listener = ApplicationListener(hass, config)
    APPLICATION_CONTROLLER.add_listener(listener)
    yield from APPLICATION_CONTROLLER.startup(auto_form=True)

    for device in APPLICATION_CONTROLLER.devices.values():
        hass.async_add_job(listener.async_device_initialized(device, False))

    @asyncio.coroutine
    def permit(service):
        """Allow devices to join this network."""
        duration = service.data.get(ATTR_DURATION)
        _LOGGER.info("Permitting joins for %ss", duration)
        yield from APPLICATION_CONTROLLER.permit(duration)

    hass.services.async_register(DOMAIN, SERVICE_PERMIT, permit,
                                 SERVICE_DESCRIPTIONS[SERVICE_PERMIT],
                                 SERVICE_SCHEMAS[SERVICE_PERMIT])

    return True

class ApplicationListener:
    """All handlers for events that happen on the ZigBee application."""

    def __init__(self, hass, config):
        """Initialize the listener."""
        self._hass = hass
        self._config = config
        hass.data[DISCOVERY_KEY] = hass.data.get(DISCOVERY_KEY, {})

    def device_joined(self, device):
        """Handle device joined.

        At this point, no information about the device is known other than its
        address
        """
        # Wait for device_initialized, instead
        pass

    def device_initialized(self, device):
        """Handle device joined and basic information discovered."""
        self._hass.async_add_job(self.async_device_initialized(device, True))

    @asyncio.coroutine
    def async_device_initialized(self, device, join):
        """Handle device joined and basic information discovered (async)."""
        import bellows.zigbee.profiles
        import homeassistant.components.zha.const as zha_const
        zha_const.populate_data()

        for endpoint_id, endpoint in device.endpoints.items():
            if endpoint_id == 0:  # ZDO
                continue

            discovered_info = yield from _discover_endpoint_info(endpoint)

            component = None
            used_clusters = []
            device_key = '%s-%s' % (str(device.ieee), endpoint_id)
            node_config = self._config[DOMAIN][CONF_DEVICE_CONFIG].get(
                device_key, {})

            if endpoint.profile_id in bellows.zigbee.profiles.PROFILES:
                profile = bellows.zigbee.profiles.PROFILES[endpoint.profile_id]
                if zha_const.DEVICE_CLASS.get(endpoint.profile_id,
                                              {}).get(endpoint.device_type,
                                                      None):
                    used_clusters = profile.CLUSTERS[endpoint.device_type]
                    profile_info = zha_const.DEVICE_CLASS[endpoint.profile_id]
                    component = profile_info[endpoint.device_type]

            if ha_const.CONF_TYPE in node_config:
                component = node_config[ha_const.CONF_TYPE]
                used_clusters = zha_const.COMPONENT_CLUSTERS[component]

            if component:
                clusters = [endpoint.clusters[c] for c in used_clusters if c in
                            endpoint.clusters]
                discovery_info = {
                    'endpoint': endpoint,
                    'clusters': clusters,
                    'new_join': join,
                }
                discovery_info.update(discovered_info)
                self._hass.data[DISCOVERY_KEY][device_key] = discovery_info

                yield from discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {'discovery_key': device_key},
                    self._config,
                )

            for cluster_id, cluster in endpoint.clusters.items():
                cluster_type = type(cluster)
                if cluster_id in used_clusters:
                    continue
                if cluster_type not in zha_const.SINGLE_CLUSTER_DEVICE_CLASS:
                    continue

                component = zha_const.SINGLE_CLUSTER_DEVICE_CLASS[cluster_type]
                discovery_info = {
                    'endpoint': endpoint,
                    'clusters': [cluster],
                    'new_join': join,
                }
                discovery_info.update(discovered_info)
                cluster_key = '%s-%s' % (device_key, cluster_id)
                self._hass.data[DISCOVERY_KEY][cluster_key] = discovery_info

                yield from discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {'discovery_key': cluster_key},
                    self._config,
                )

class Entity(entity.Entity):
    """A base class for ZHA entities."""

    _domain = None  # Must be overriden by subclasses

    def __init__(self, endpoint, clusters, manufacturer, model, **kwargs):
        """Init ZHA entity."""
        self._device_state_attributes = {}
        ieeetail = ''.join([
            '%02x' % (o, ) for o in endpoint.device.ieee[-4:]
        ])
        if manufacturer and model is not None:
            self.entity_id = '%s.%s_%s_%s_%s' % (
                self._domain,
                slugify(manufacturer),
                slugify(model),
                ieeetail,
                endpoint.endpoint_id,
            )
            self._device_state_attributes['friendly_name'] = '%s %s' % (
                manufacturer,
                model,
            )
        else:
            self.entity_id = "%s.zha_%s_%s" % (
                self._domain,
                ieeetail,
                endpoint.endpoint_id,
            )
        for cluster in clusters:
            cluster.add_listener(self)
        self._endpoint = endpoint
        self._clusters = {c.cluster_id: c for c in clusters}
        self._state = ha_const.STATE_UNKNOWN

    def attribute_updated(self, attribute, value):
        """Handle an attribute updated on this cluster."""
        pass

    def zdo_command(self, aps_frame, tsn, command_id, args):
        """Handle a ZDO command received on this cluster."""
        pass

    @property
    def device_state_attributes(self):
        """Return device specific state attributes."""
        return self._device_state_attributes

@asyncio.coroutine
def _discover_endpoint_info(endpoint):
    """Find some basic information about an endpoint."""
    extra_info = {
        'manufacturer': None,
        'model': None,
    }
    if 0 not in endpoint.clusters:
        return extra_info

    result, _ = yield from endpoint.clusters[0].read_attributes(
        ['manufacturer', 'model'],
        allow_cache=True,
    )
    extra_info.update(result)

    for key, value in extra_info.items():
        if isinstance(value, bytes):
            try:
                extra_info[key] = value.decode('ascii')
            except UnicodeDecodeError:
                # Unsure what the best behaviour here is. Unset the key?
                pass

    return extra_info

def get_discovery_info(hass, discovery_info):
    """Get the full discovery info for a device.

    Some of the info that needs to be passed to platforms is not JSON
    serializable, so it cannot be put in the discovery_info dictionary. This
    component places that info we need to pass to the platform in hass.data,
    and this function is a helper for platforms to retrieve the complete
    discovery info.
    """
    if discovery_info is None:
        return

    discovery_key = discovery_info.get('discovery_key', None)
    all_discovery_info = hass.data.get(DISCOVERY_KEY, {})
    discovery_info = all_discovery_info.get(discovery_key, None)
    return discovery_info
<commit_msg>zha: Strip whitespace from device names (#8306)<commit_after>"""
Support for ZigBee Home Automation devices.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/zha/
"""
import asyncio
import logging

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant import const as ha_const
from homeassistant.helpers import discovery, entity
from homeassistant.util import slugify

REQUIREMENTS = ['bellows==0.2.7']

DOMAIN = 'zha'

CONF_USB_PATH = 'usb_path'
CONF_DATABASE = 'database_path'
CONF_DEVICE_CONFIG = 'device_config'
DATA_DEVICE_CONFIG = 'zha_device_config'

DEVICE_CONFIG_SCHEMA_ENTRY = vol.Schema({
    vol.Optional(ha_const.CONF_TYPE): cv.string,
})

CONFIG_SCHEMA = vol.Schema({
    DOMAIN: vol.Schema({
        CONF_USB_PATH: cv.string,
        CONF_DATABASE: cv.string,
        vol.Optional(CONF_DEVICE_CONFIG, default={}):
            vol.Schema({cv.string: DEVICE_CONFIG_SCHEMA_ENTRY}),
    })
}, extra=vol.ALLOW_EXTRA)

ATTR_DURATION = 'duration'

SERVICE_PERMIT = 'permit'
SERVICE_DESCRIPTIONS = {
    SERVICE_PERMIT: {
        "description": "Allow nodes to join the Zigbee network",
        "fields": {
            "duration": {
                "description": "Time to permit joins, in seconds",
                "example": "60",
            },
        },
    },
}
SERVICE_SCHEMAS = {
    SERVICE_PERMIT: vol.Schema({
        vol.Optional(ATTR_DURATION, default=60):
            vol.All(vol.Coerce(int), vol.Range(1, 254)),
    }),
}

# ZigBee definitions
CENTICELSIUS = 'C-100'
# Key in hass.data dict containing discovery info
DISCOVERY_KEY = 'zha_discovery_info'

# Internal definitions
APPLICATION_CONTROLLER = None
_LOGGER = logging.getLogger(__name__)

@asyncio.coroutine
def async_setup(hass, config):
    """Set up ZHA.

    Will automatically load components to support devices found on the network.
    """
    global APPLICATION_CONTROLLER

    import bellows.ezsp
    from bellows.zigbee.application import ControllerApplication

    ezsp_ = bellows.ezsp.EZSP()
    usb_path = config[DOMAIN].get(CONF_USB_PATH)
    yield from ezsp_.connect(usb_path)

    database = config[DOMAIN].get(CONF_DATABASE)
    APPLICATION_CONTROLLER = ControllerApplication(ezsp_, database)
    listener = ApplicationListener(hass, config)
    APPLICATION_CONTROLLER.add_listener(listener)
    yield from APPLICATION_CONTROLLER.startup(auto_form=True)

    for device in APPLICATION_CONTROLLER.devices.values():
        hass.async_add_job(listener.async_device_initialized(device, False))

    @asyncio.coroutine
    def permit(service):
        """Allow devices to join this network."""
        duration = service.data.get(ATTR_DURATION)
        _LOGGER.info("Permitting joins for %ss", duration)
        yield from APPLICATION_CONTROLLER.permit(duration)

    hass.services.async_register(DOMAIN, SERVICE_PERMIT, permit,
                                 SERVICE_DESCRIPTIONS[SERVICE_PERMIT],
                                 SERVICE_SCHEMAS[SERVICE_PERMIT])

    return True

class ApplicationListener:
    """All handlers for events that happen on the ZigBee application."""

    def __init__(self, hass, config):
        """Initialize the listener."""
        self._hass = hass
        self._config = config
        hass.data[DISCOVERY_KEY] = hass.data.get(DISCOVERY_KEY, {})

    def device_joined(self, device):
        """Handle device joined.

        At this point, no information about the device is known other than its
        address
        """
        # Wait for device_initialized, instead
        pass

    def device_initialized(self, device):
        """Handle device joined and basic information discovered."""
        self._hass.async_add_job(self.async_device_initialized(device, True))

    @asyncio.coroutine
    def async_device_initialized(self, device, join):
        """Handle device joined and basic information discovered (async)."""
        import bellows.zigbee.profiles
        import homeassistant.components.zha.const as zha_const
        zha_const.populate_data()

        for endpoint_id, endpoint in device.endpoints.items():
            if endpoint_id == 0:  # ZDO
                continue

            discovered_info = yield from _discover_endpoint_info(endpoint)

            component = None
            used_clusters = []
            device_key = '%s-%s' % (str(device.ieee), endpoint_id)
            node_config = self._config[DOMAIN][CONF_DEVICE_CONFIG].get(
                device_key, {})

            if endpoint.profile_id in bellows.zigbee.profiles.PROFILES:
                profile = bellows.zigbee.profiles.PROFILES[endpoint.profile_id]
                if zha_const.DEVICE_CLASS.get(endpoint.profile_id,
                                              {}).get(endpoint.device_type,
                                                      None):
                    used_clusters = profile.CLUSTERS[endpoint.device_type]
                    profile_info = zha_const.DEVICE_CLASS[endpoint.profile_id]
                    component = profile_info[endpoint.device_type]

            if ha_const.CONF_TYPE in node_config:
                component = node_config[ha_const.CONF_TYPE]
                used_clusters = zha_const.COMPONENT_CLUSTERS[component]

            if component:
                clusters = [endpoint.clusters[c] for c in used_clusters if c in
                            endpoint.clusters]
                discovery_info = {
                    'endpoint': endpoint,
                    'clusters': clusters,
                    'new_join': join,
                }
                discovery_info.update(discovered_info)
                self._hass.data[DISCOVERY_KEY][device_key] = discovery_info

                yield from discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {'discovery_key': device_key},
                    self._config,
                )

            for cluster_id, cluster in endpoint.clusters.items():
                cluster_type = type(cluster)
                if cluster_id in used_clusters:
                    continue
                if cluster_type not in zha_const.SINGLE_CLUSTER_DEVICE_CLASS:
                    continue

                component = zha_const.SINGLE_CLUSTER_DEVICE_CLASS[cluster_type]
                discovery_info = {
                    'endpoint': endpoint,
                    'clusters': [cluster],
                    'new_join': join,
                }
                discovery_info.update(discovered_info)
                cluster_key = '%s-%s' % (device_key, cluster_id)
                self._hass.data[DISCOVERY_KEY][cluster_key] = discovery_info

                yield from discovery.async_load_platform(
                    self._hass,
                    component,
                    DOMAIN,
                    {'discovery_key': cluster_key},
                    self._config,
                )

class Entity(entity.Entity):
    """A base class for ZHA entities."""

    _domain = None  # Must be overriden by subclasses

    def __init__(self, endpoint, clusters, manufacturer, model, **kwargs):
        """Init ZHA entity."""
        self._device_state_attributes = {}
        ieeetail = ''.join([
            '%02x' % (o, ) for o in endpoint.device.ieee[-4:]
        ])
        if manufacturer and model is not None:
            self.entity_id = '%s.%s_%s_%s_%s' % (
                self._domain,
                slugify(manufacturer),
                slugify(model),
                ieeetail,
                endpoint.endpoint_id,
            )
            self._device_state_attributes['friendly_name'] = '%s %s' % (
                manufacturer,
                model,
            )
        else:
            self.entity_id = "%s.zha_%s_%s" % (
                self._domain,
                ieeetail,
                endpoint.endpoint_id,
            )
        for cluster in clusters:
            cluster.add_listener(self)
        self._endpoint = endpoint
        self._clusters = {c.cluster_id: c for c in clusters}
        self._state = ha_const.STATE_UNKNOWN

    def attribute_updated(self, attribute, value):
        """Handle an attribute updated on this cluster."""
        pass

    def zdo_command(self, aps_frame, tsn, command_id, args):
        """Handle a ZDO command received on this cluster."""
        pass

    @property
    def device_state_attributes(self):
        """Return device specific state attributes."""
        return self._device_state_attributes

@asyncio.coroutine
def _discover_endpoint_info(endpoint):
    """Find some basic information about an endpoint."""
    extra_info = {
        'manufacturer': None,
        'model': None,
    }
    if 0 not in endpoint.clusters:
        return extra_info

    result, _ = yield from endpoint.clusters[0].read_attributes(
        ['manufacturer', 'model'],
        allow_cache=True,
    )
    extra_info.update(result)

    for key, value in extra_info.items():
        if isinstance(value, bytes):
            try:
                extra_info[key] = value.decode('ascii').strip()
            except UnicodeDecodeError:
                # Unsure what the best behaviour here is. Unset the key?
                pass

    return extra_info

def get_discovery_info(hass, discovery_info):
    """Get the full discovery info for a device.

    Some of the info that needs to be passed to platforms is not JSON
    serializable, so it cannot be put in the discovery_info dictionary. This
    component places that info we need to pass to the platform in hass.data,
    and this function is a helper for platforms to retrieve the complete
    discovery info.
    """
    if discovery_info is None:
        return

    discovery_key = discovery_info.get('discovery_key', None)
    all_discovery_info = hass.data.get(DISCOVERY_KEY, {})
    discovery_info = all_discovery_info.get(discovery_key, None)
    return discovery_info
<|endoftext|>


<commit_before>"""
.. module:: trimming
    :platform: Unix, Windows
    :synopsis: Provides helper functions for surface trimming

.. moduleauthor:: Onur Rauf Bingol <orbingol@gmail.com>

"""

import math
from . import linalg
from . import shortcuts
from .exceptions import GeomdlException
from ._utilities import export

@export
def map_trim_to_geometry(obj, trim_idx=-1, **kwargs):
    """ Generates 3-dimensional surface mapping of trimming curves.

    If `trim_idx=-1`, the function maps all 2-dimensional trims to their 3-dimensional
    correspondants.

    :param obj: spline geometry
    :type obj: abstract.SplineGeometry
    :param trim_idx: index of the trimming curve in the geometry object
    :type trim_idx: int
    :return: 3-dimensional mapping of trimming curve(s)
    :rtype: freeform.Freeform
    """
    # Get keyword arguments
    delta = kwargs.get('delta', -1.0)

    # Initialize return list
    ret = []

    # Process trims
    if trim_idx < 0:
        # Process all trims
        for trim in obj.trims:
            # Set delta
            if delta > 0:
                trim.delta = delta

            # Evaluate trim
            epts = obj.evaluate_list(trim.evalpts)
            fcurve = shortcuts.generate_freeform()
            fcurve.evaluate(points=epts)
            ret.append(fcurve)
    else:
        # Process a single trim
        try:
            trim = obj.trims[trim_idx]
        except KeyError:
            raise GeomdlException("Trim curve at index " + str(trim_idx) + " does not exist")

        # Set delta
        if delta > 0:
            trim.delta = delta

        # Evaluate trim
        epts = obj.evaluate_list(trim.evalpts)
        fcurve = shortcuts.generate_freeform()
        fcurve.evaluate(points=epts)
        ret.append(fcurve)

    # Return curves
    return ret

@export
def fix_multi_trim_curves(obj, **kwargs):
    """ Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trims in curve containers, i.e. trims consisting of multiple curves.

    Keyword Arguments:
        * ``tol``: tolerance value for comparing floats. *Default: 10e-8*
        * ``delta``: evaluation delta of the trim curves. *Default: 0.05*

    :param obj: input surface
    :type obj: abstract.BSplineGeometry, multi.AbstractContainer
    :return: updated surface
    """
    if obj.pdimension != 2:
        raise GeomdlException("Can only work with surfaces")

    # Get keyword arguments
    tol = kwargs.get('tol', 10e-8)
    eval_delta = kwargs.get('delta', 0.05)

    # Loop through the surfaces
    for o in obj:
        # Get the trims
        trims = o.trims

        # Initialize a list for the connected trims
        new_trims = []

        # Traverse through the trims
        for trim in trims:
            trim_size = len(trim)

            # Directly add to the new trims array if the trim is a single curve
            if trim_size == 1:
                new_trims.append(trim)
                continue

            new_trim = []
            for idx in range(0, trim_size):
                # Close the loop
                if idx == trim_size - 1:
                    idx2 = 0
                else:
                    idx2 = idx + 1

                ###
                # Assuming that we have two curves with starting and ending positions defined as P1-P2 and P3-P4,
                # respectively. There are 5 possibilities:
                # 1. P2 = P3 (end of 1st and start of 2nd)
                # 2. P2 = P4 (end of 1st and end of 2nd)
                # 3. P1 = P3 (start of 1st and start of 2nd)
                # 4. P1 = P4 (start of 1st and end of 2nd)
                # 5. the ends of the curves are far away from each other
                ###

                # End of 1st curve vs start of 2nd curve
                if abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # They are in the same direction
                    new_trim.append(trim[idx])
                # End of 1st curve vs end of 2nd curve
                elif abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse the second curve inplace
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and start of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # Reverse the first curve inplace
                    trim[idx].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and end of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse both curves inplace
                    trim[idx].reverse()
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # The trim curves are far away from each other
                else:
                    # Find which end is closer to the current trim curve's end point
                    dist1 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[0])
                    dist2 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[-1])

                    # Find start and end points of the connector curve
                    start_pt = trim[idx].evalpts[-1]
                    if dist1 < dist2:
                        end_pt = trim[idx2].evalpts[0]
                    else:
                        end_pt = trim[idx2].evalpts[-1]

                    # Generate the connector curve
                    crv = shortcuts.generate_curve()
                    crv.degree = 1
                    crv.ctrlpts = [start_pt, end_pt]
                    crv.knotvector = [0, 0, 1, 1]
                    crv.opt = ['reversed', trim[idx].opt_get('reversed')]

                    # Add trims
                    new_trim.append(trim[idx])
                    new_trim.append(crv)

            # Create a curve container from the new trim list
            cc = shortcuts.generate_container_curve()
            cc.add(new_trim)
            cc.opt = ['reversed', trim.opt_get('reversed')]
            cc.delta = eval_delta

            # Add curve container to the new trims list
            new_trims.append(cc)

        # Update input geometry
        o.trims = new_trims

    return obj

@export
def fix_trim_curves(obj):
    """ Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trim curves consisting of a single curve.

    :param obj: input surface
    :type obj: abstract.Surface
    """
    # Validate input
    if obj.pdimension != 2:
        raise GeomdlException("Input geometry must be a surface")

    # Get trims of the surface
    for o in obj:
        trims = o.trims
        if not trims:
            continue

        # Get parameter space bounding box
        parbox = get_par_box(o.domain, True)

        # Check and update trim curves with respect to the underlying surface
        updated_trims = []
        for trim in trims:
            flag, trm = check_trim_curve(trim, parbox)
            if flag:
                if trm:
                    cont = shortcuts.generate_container_curve()
                    cont.add(trm)
                    updated_trims.append(cont)
                else:
                    updated_trims.append(trim)

        # Set updated trims
        obj.trims = updated_trims

def check_trim_curve(curve, parbox, **kwargs):
    """ Checks if the trim curve was closed and sense was set.

    :param curve: trim curve
    :param parbox: parameter space bounding box of the underlying surface
    :return: a tuple containing the status of the operation and list of extra trim curves generated
    :rtype: tuple
    """
    def next_idx(edge_idx, direction):
        tmp = edge_idx + direction
        if tmp < 0:
            return 3
        if tmp > 3:
            return 0
        return tmp

    # Keyword arguments
    tol = kwargs.get('tol', 10e-8)

    # First, check if the curve is closed
    dist = linalg.point_distance(curve.evalpts[0], curve.evalpts[-1])
    if dist <= tol:
        # Curve is closed
        return detect_sense(curve, tol), []
    else:
        # Define start and end points of the trim curve
        pt_start = curve.evalpts[0]
        pt_end = curve.evalpts[-1]

        # Search for intersections
        idx_spt = -1
        idx_ept = -1
        for idx in range(len(parbox) - 1):
            if detect_intersection(parbox[idx], parbox[idx + 1], pt_start, tol):
                idx_spt = idx
            if detect_intersection(parbox[idx], parbox[idx + 1], pt_end, tol):
                idx_ept = idx

        # Check result of the intersection
        if idx_spt < 0 or idx_ept < 0:
            # Curve does not intersect any edges of the parametric space
            # TODO: Extrapolate the curve using the tangent vector and find intersections
            return False, []
        else:
            # Get sense of the original curve
            c_sense = curve.opt_get('reversed')

            # If sense is None, then detect sense
            if c_sense is None:
                # Get evaluated points
                pts = curve.evalpts
                num_pts = len(pts)

                # Find sense
                tmp_sense = 0
                for pti in range(1, num_pts - 1):
                    tmp_sense = detect_ccw(pts[pti - 1], pts[pti], pts[pti + 1], tol)
                    if tmp_sense != 0:
                        break
                if tmp_sense == 0:
                    tmp_sense2 = detect_ccw(pts[int(num_pts/3)], pts[int(2*num_pts/3)], pts[-int(num_pts/3)], tol)
                    if tmp_sense2 != 0:
                        tmp_sense = -tmp_sense2
                    else:
                        # We cannot decide which region to trim. Therefore, ignore this curve.
                        return False, []

                c_sense = 0 if tmp_sense > 0 else 1

                # Update sense of the original curve
                curve.opt = ['reversed', c_sense]

            # Generate a curve container and add the original curve
            cont = [curve]

            move_dir = -1 if c_sense == 0 else 1

            # Curve intersects with the edges of the parametric space
            counter = 0
            while counter < 4:
                if idx_ept == idx_spt:
                    counter = 5
                    pt_start = curve.evalpts[0]
                else:
                    # Find next index
                    idx_ept = next_idx(idx_ept, move_dir)
                    # Update tracked last point
                    pt_start = parbox[idx_ept + 1 - c_sense]
                    # Increment counter
                    counter += 1

                # Generate the curve segment
                crv = shortcuts.generate_curve()
                crv.degree = 1
                crv.ctrlpts = [pt_end, pt_start]
                crv.knotvector = [0, 0, 1, 1]
                crv.opt = ['reversed', c_sense]

                pt_end = pt_start

                # Add it to the container
                cont.append(crv)

            # Update curve
            return True, cont

def get_par_box(domain, last=False):
    """ Returns the bounding box of the surface parametric domain in ccw direction.

    :param domain: parametric domain
    :type domain: list, tuple
    :param last: if True, adds the first vertex to the end of the return list
    :type last: bool
    :return: edges of the parametric domain
    :rtype: tuple
    """
    u_range = domain[0]
    v_range = domain[1]
    verts = [(u_range[0], v_range[0]), (u_range[1], v_range[0]), (u_range[1], v_range[1]), (u_range[0], v_range[1])]
    if last:
        verts.append(verts[0])
    return tuple(verts)

def detect_sense(curve, tol):
    """ Detects the sense, i.e. clockwise or counter-clockwise, of the curve.

    :param curve: 2-dimensional trim curve
    :type curve: abstract.Curve
    :param tol: tolerance value
    :type tol: float
    :return: True if detection is successful, False otherwise
    :rtype: bool
    """
    if curve.opt_get('reversed') is None:
        # Detect sense since it is unset
        pts = curve.evalpts
        num_pts = len(pts)
        for idx in range(1, num_pts - 1):
            sense = detect_ccw(pts[idx - 1], pts[idx], pts[idx + 1], tol)
            if sense < 0:  # cw
                curve.opt = ['reversed', 0]
                return True
            elif sense > 0:  # ccw
                curve.opt = ['reversed', 1]
                return True
            else:
                continue
        # One final test with random points to determine the orientation
        sense = detect_ccw(pts[int(num_pts/3)], pts[int(2*num_pts/3)], pts[-int(num_pts/3)], tol)
        if sense < 0:  # cw
            curve.opt = ['reversed', 0]
            return True
        elif sense > 0:  # ccw
            curve.opt = ['reversed', 1]
            return True
        else:
            # Cannot determine the sense
            return False
    else:
        # Don't touch the sense value as it has been already set
        return True

def detect_ccw(pt1, pt2, pt3, tol):
    vec1 = linalg.vector_generate(pt1, pt2)
    vec2 = linalg.vector_generate(pt2, pt3)
    cross = linalg.vector_cross(vec1, vec2)
    if cross[2] > tol:  # cw
        return -1
    elif cross[2] < -tol:  # ccw
        return 1
    return 0

def detect_intersection(start_pt, end_pt, test_pt, tol):
    dist_num = abs(((end_pt[1] - start_pt[1]) * test_pt[0]) - ((end_pt[0] - start_pt[0]) * test_pt[1]) +
                   (end_pt[0] * start_pt[1]) - (end_pt[1] * start_pt[0]))
    dist_denom = math.sqrt(math.pow(end_pt[1] - start_pt[1], 2) + math.pow(end_pt[0] - start_pt[0], 2))
    dist = dist_num / dist_denom
    if abs(dist) < tol:
        return True
    return False
<commit_msg>Doctring updates and input validity checks<commit_after>"""
.. module:: trimming
    :platform: Unix, Windows
    :synopsis: Provides helper functions for surface trimming

.. moduleauthor:: Onur Rauf Bingol <orbingol@gmail.com>

"""

import math
from . import linalg
from . import shortcuts
from .exceptions import GeomdlException
from ._utilities import export

@export
def map_trim_to_geometry(obj, trim_idx=-1, **kwargs):
    """ Generates 3-dimensional mapping of 2-dimensional trimming curves.

    If `trim_idx=-1`, the function maps all 2-dimensional trims to their 3-dimensional
    correspondants.

    :param obj: spline geometry
    :type obj: abstract.SplineGeometry
    :param trim_idx: index of the trimming curve in the geometry object
    :type trim_idx: int
    :return: 3-dimensional mapping of trimming curve(s)
    :rtype: freeform.Freeform
    """
    if obj.pdimension < 2:
        raise GeomdlException("Input geometry should be defined on, at least, 2-dimensional parametric space")

    # Get keyword arguments
    delta = kwargs.get('delta', -1.0)

    # Initialize return list
    ret = []

    # Process trims
    if trim_idx < 0:
        # Process all trims
        for trim in obj.trims:
            # Set delta
            if delta > 0:
                trim.delta = delta

            # Evaluate trim
            epts = obj.evaluate_list(trim.evalpts)
            fcurve = shortcuts.generate_freeform()
            fcurve.evaluate(points=epts)
            ret.append(fcurve)
    else:
        # Process a single trim
        try:
            trim = obj.trims[trim_idx]
        except KeyError:
            raise GeomdlException("Trim curve at index " + str(trim_idx) + " does not exist")

        # Set delta
        if delta > 0:
            trim.delta = delta

        # Evaluate trim
        epts = obj.evaluate_list(trim.evalpts)
        fcurve = shortcuts.generate_freeform()
        fcurve.evaluate(points=epts)
        ret.append(fcurve)

    # Return curves
    return ret

@export
def fix_multi_trim_curves(obj, **kwargs):
    """ Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trims in curve containers, i.e. trims consisting of multiple curves.

    Keyword Arguments:
        * ``tol``: tolerance value for comparing floats. *Default: 10e-8*
        * ``delta``: evaluation delta of the trim curves. *Default: 0.05*

    :param obj: input surface
    :type obj: abstract.BSplineGeometry, multi.AbstractContainer
    :return: updated surface
    """
    if obj.pdimension != 2:
        raise GeomdlException("Can only work with surfaces")

    # Get keyword arguments
    tol = kwargs.get('tol', 10e-8)
    eval_delta = kwargs.get('delta', 0.05)

    # Loop through the surfaces
    for o in obj:
        # Get the trims
        trims = o.trims

        # Initialize a list for the connected trims
        new_trims = []

        # Traverse through the trims
        for trim in trims:
            trim_size = len(trim)

            # Directly add to the new trims array if the trim is a single curve
            if trim_size == 1:
                new_trims.append(trim)
                continue

            new_trim = []
            for idx in range(0, trim_size):
                # Close the loop
                if idx == trim_size - 1:
                    idx2 = 0
                else:
                    idx2 = idx + 1

                ###
                # Assuming that we have two curves with starting and ending positions defined as P1-P2 and P3-P4,
                # respectively. There are 5 possibilities:
                # 1. P2 = P3 (end of 1st and start of 2nd)
                # 2. P2 = P4 (end of 1st and end of 2nd)
                # 3. P1 = P3 (start of 1st and start of 2nd)
                # 4. P1 = P4 (start of 1st and end of 2nd)
                # 5. the ends of the curves are far away from each other
                ###

                # End of 1st curve vs start of 2nd curve
                if abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # They are in the same direction
                    new_trim.append(trim[idx])
                # End of 1st curve vs end of 2nd curve
                elif abs(trim[idx].evalpts[-1][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[-1][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse the second curve inplace
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and start of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[0][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[0][1]) <= tol:
                    # Reverse the first curve inplace
                    trim[idx].reverse()
                    new_trim.append(trim[idx])
                # Start of 1st curve and end of 2nd curve
                elif abs(trim[idx].evalpts[0][0] - trim[idx2].evalpts[-1][0]) <= tol and \
                        abs(trim[idx].evalpts[0][1] - trim[idx2].evalpts[-1][1]) <= tol:
                    # Reverse both curves inplace
                    trim[idx].reverse()
                    trim[idx2].reverse()
                    new_trim.append(trim[idx])
                # The trim curves are far away from each other
                else:
                    # Find which end is closer to the current trim curve's end point
                    dist1 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[0])
                    dist2 = linalg.point_distance(trim[idx].evalpts[-1], trim[idx2].evalpts[-1])

                    # Find start and end points of the connector curve
                    start_pt = trim[idx].evalpts[-1]
                    if dist1 < dist2:
                        end_pt = trim[idx2].evalpts[0]
                    else:
                        end_pt = trim[idx2].evalpts[-1]

                    # Generate the connector curve
                    crv = shortcuts.generate_curve()
                    crv.degree = 1
                    crv.ctrlpts = [start_pt, end_pt]
                    crv.knotvector = [0, 0, 1, 1]
                    crv.opt = ['reversed', trim[idx].opt_get('reversed')]

                    # Add trims
                    new_trim.append(trim[idx])
                    new_trim.append(crv)

            # Create a curve container from the new trim list
            cc = shortcuts.generate_container_curve()
            cc.add(new_trim)
            cc.opt = ['reversed', trim.opt_get('reversed')]
            cc.delta = eval_delta

            # Add curve container to the new trims list
            new_trims.append(cc)

        # Update input geometry
        o.trims = new_trims

    return obj

@export
def fix_trim_curves(obj):
    """ Fixes direction, connectivity and similar issues of the trim curves.

    This function works for surface trim curves consisting of a single curve.

    :param obj: input surface
    :type obj: abstract.Surface
    """
    # Validate input
    if obj.pdimension != 2:
        raise GeomdlException("Input geometry must be a surface")

    # Get trims of the surface
    for o in obj:
        trims = o.trims
        if not trims:
            continue

        # Get parameter space bounding box
        parbox = get_par_box(o.domain, True)

        # Check and update trim curves with respect to the underlying surface
        updated_trims = []
        for trim in trims:
            flag, trm = check_trim_curve(trim, parbox)
            if flag:
                if trm:
                    cont = shortcuts.generate_container_curve()
                    cont.add(trm)
                    updated_trims.append(cont)
                else:
                    updated_trims.append(trim)

        # Set updated trims
        obj.trims = updated_trims

def check_trim_curve(curve, parbox, **kwargs):
    """ Checks if the trim curve was closed and sense was set.

    :param curve: trim curve
    :param parbox: parameter space bounding box of the underlying surface
    :return: a tuple containing the status of the operation and list of extra trim curves generated
    :rtype: tuple
    """
    def next_idx(edge_idx, direction):
        tmp = edge_idx + direction
        if tmp < 0:
            return 3
        if tmp > 3:
            return 0
        return tmp

    # Keyword arguments
    tol = kwargs.get('tol', 10e-8)

    # First, check if the curve is closed
    dist = linalg.point_distance(curve.evalpts[0], curve.evalpts[-1])
    if dist <= tol:
        # Curve is closed
        return detect_sense(curve, tol), []
    else:
        # Define start and end points of the trim curve
        pt_start = curve.evalpts[0]
        pt_end = curve.evalpts[-1]

        # Search for intersections
        idx_spt = -1
        idx_ept = -1
        for idx in range(len(parbox) - 1):
            if detect_intersection(parbox[idx], parbox[idx + 1], pt_start, tol):
                idx_spt = idx
            if detect_intersection(parbox[idx], parbox[idx + 1], pt_end, tol):
                idx_ept = idx

        # Check result of the intersection
        if idx_spt < 0 or idx_ept < 0:
            # Curve does not intersect any edges of the parametric space
            # TODO: Extrapolate the curve using the tangent vector and find intersections
            return False, []
        else:
            # Get sense of the original curve
            c_sense = curve.opt_get('reversed')

            # If sense is None, then detect sense
            if c_sense is None:
                # Get evaluated points
                pts = curve.evalpts
                num_pts = len(pts)

                # Find sense
                tmp_sense = 0
                for pti in range(1, num_pts - 1):
                    tmp_sense = detect_ccw(pts[pti - 1], pts[pti], pts[pti + 1], tol)
                    if tmp_sense != 0:
                        break
                if tmp_sense == 0:
                    tmp_sense2 = detect_ccw(pts[int(num_pts/3)], pts[int(2*num_pts/3)], pts[-int(num_pts/3)], tol)
                    if tmp_sense2 != 0:
                        tmp_sense = -tmp_sense2
                    else:
                        # We cannot decide which region to trim. Therefore, ignore this curve.
                        return False, []

                c_sense = 0 if tmp_sense > 0 else 1

                # Update sense of the original curve
                curve.opt = ['reversed', c_sense]

            # Generate a curve container and add the original curve
            cont = [curve]

            move_dir = -1 if c_sense == 0 else 1

            # Curve intersects with the edges of the parametric space
            counter = 0
            while counter < 4:
                if idx_ept == idx_spt:
                    counter = 5
                    pt_start = curve.evalpts[0]
                else:
                    # Find next index
                    idx_ept = next_idx(idx_ept, move_dir)
                    # Update tracked last point
                    pt_start = parbox[idx_ept + 1 - c_sense]
                    # Increment counter
                    counter += 1

                # Generate the curve segment
                crv = shortcuts.generate_curve()
                crv.degree = 1
                crv.ctrlpts = [pt_end, pt_start]
                crv.knotvector = [0, 0, 1, 1]
                crv.opt = ['reversed', c_sense]

                pt_end = pt_start

                # Add it to the container
                cont.append(crv)

            # Update curve
            return True, cont

def get_par_box(domain, last=False):
    """ Returns the bounding box of the surface parametric domain in ccw direction.

    :param domain: parametric domain
    :type domain: list, tuple
    :param last: if True, adds the first vertex to the end of the return list
    :type last: bool
    :return: edges of the parametric domain
    :rtype: tuple
    """
    u_range = domain[0]
    v_range = domain[1]
    verts = [(u_range[0], v_range[0]), (u_range[1], v_range[0]), (u_range[1], v_range[1]), (u_range[0], v_range[1])]
    if last:
        verts.append(verts[0])
    return tuple(verts)

def detect_sense(curve, tol):
    """ Detects the sense, i.e. clockwise or counter-clockwise, of the curve.

    :param curve: 2-dimensional trim curve
    :type curve: abstract.Curve
    :param tol: tolerance value
    :type tol: float
    :return: True if detection is successful, False otherwise
    :rtype: bool
    """
    if curve.opt_get('reversed') is None:
        # Detect sense since it is unset
        pts = curve.evalpts
        num_pts = len(pts)
        for idx in range(1, num_pts - 1):
            sense = detect_ccw(pts[idx - 1], pts[idx], pts[idx + 1], tol)
            if sense < 0:  # cw
                curve.opt = ['reversed', 0]
                return True
            elif sense > 0:  # ccw
                curve.opt = ['reversed', 1]
                return True
            else:
                continue
        # One final test with random points to determine the orientation
        sense = detect_ccw(pts[int(num_pts/3)], pts[int(2*num_pts/3)], pts[-int(num_pts/3)], tol)
        if sense < 0:  # cw
            curve.opt = ['reversed', 0]
            return True
        elif sense > 0:  # ccw
            curve.opt = ['reversed', 1]
            return True
        else:
            # Cannot determine the sense
            return False
    else:
        # Don't touch the sense value as it has been already set
        return True

def detect_ccw(pt1, pt2, pt3, tol):
    vec1 = linalg.vector_generate(pt1, pt2)
    vec2 = linalg.vector_generate(pt2, pt3)
    cross = linalg.vector_cross(vec1, vec2)
    if cross[2] > tol:  # cw
        return -1
    elif cross[2] < -tol:  # ccw
        return 1
    return 0

def detect_intersection(start_pt, end_pt, test_pt, tol):
    dist_num = abs(((end_pt[1] - start_pt[1]) * test_pt[0]) - ((end_pt[0] - start_pt[0]) * test_pt[1]) +
                   (end_pt[0] * start_pt[1]) - (end_pt[1] * start_pt[0]))
    dist_denom = math.sqrt(math.pow(end_pt[1] - start_pt[1], 2) + math.pow(end_pt[0] - start_pt[0], 2))
    dist = dist_num / dist_denom
    if abs(dist) < tol:
        return True
    return False
<|endoftext|>


<commit_before>import graphene
from graphene_django import DjangoObjectType
from django.utils import timezone
from accelerator.models import (
    ExpertProfile,
    UserRole,
    ProgramRole,
    Program,
)
from impact.graphql.types.industry_type import IndustryType  # noqa: F401
from impact.graphql.types.startup_type import StartupType
from impact.graphql.types.program_family_type import ProgramFamilyType  # noqa: F401, E501
from impact.graphql.types.user_type import UserType  # noqa: F401
from impact.graphql.types.functional_expertise_type import FunctionalExpertiseType  # noqa: F401, E501
from impact.graphql.types.interest_category_type import InterestCategoryType  # noqa: F401, E501

class ExpertProfileType(DjangoObjectType):
    mentees = graphene.List(StartupType)
    image_url = graphene.String()
    program_interests = graphene.List(graphene.String)
    available_office_hours = graphene.Boolean()

    class Meta:
        model = ExpertProfile
        only_fields = (
            'title',
            'company',
            'phone',
            'twitter_handle',
            'linked_in_url',
            'personal_website_url',
            'bio',
            'expert_category',
            'primary_industry',
            'additional_industries',
            'home_program_family',
            'user',
            'functional_expertise',
            'interest_categories',
        )

    def resolve_image_url(self, info, **kwargs):
        return self.image and self.image.url

    def resolve_program_interests(self, info, **kwargs):
        return self.interest_categories.all().values_list(
            'program__program_family__name', flat=True).distinct()

    def resolve_available_office_hours(self, info, **kwargs):
        user = info.context.user
        filter_kwargs = {
            'finalist__isnull': True,
            'date__gte': timezone.now(),
            'start_time__gte': timezone.now().time()
        }
        if not user.is_staff:
            filter_kwargs['program__in'] = get_user_programs(user)
        return self.user.mentor_officehours.filter(
            **filter_kwargs).exists()

def get_user_programs(user):
    # todo: refactor this and move it to a sensible place
    # todo: test this
    participant_roles = UserRole.FINALIST_USER_ROLES
    user_program_roles_as_participant = ProgramRole.objects.filter(
        programrolegrant__person=user,
        user_role__name__in=participant_roles
    )
    return Program.objects.filter(
        programrole__in=user_program_roles_as_participant).distinct()
<commit_msg>[AC-5666] rename get_user_programs to be private<commit_after>import graphene
from graphene_django import DjangoObjectType
from django.utils import timezone
from accelerator.models import (
    ExpertProfile,
    UserRole,
    ProgramRole,
    Program,
)
from impact.graphql.types.industry_type import IndustryType  # noqa: F401
from impact.graphql.types.startup_type import StartupType
from impact.graphql.types.program_family_type import ProgramFamilyType  # noqa: F401, E501
from impact.graphql.types.user_type import UserType  # noqa: F401
from impact.graphql.types.functional_expertise_type import FunctionalExpertiseType  # noqa: F401, E501
from impact.graphql.types.interest_category_type import InterestCategoryType  # noqa: F401, E501

class ExpertProfileType(DjangoObjectType):
    mentees = graphene.List(StartupType)
    image_url = graphene.String()
    program_interests = graphene.List(graphene.String)
    available_office_hours = graphene.Boolean()

    class Meta:
        model = ExpertProfile
        only_fields = (
            'title',
            'company',
            'phone',
            'twitter_handle',
            'linked_in_url',
            'personal_website_url',
            'bio',
            'expert_category',
            'primary_industry',
            'additional_industries',
            'home_program_family',
            'user',
            'functional_expertise',
            'interest_categories',
        )

    def resolve_image_url(self, info, **kwargs):
        return self.image and self.image.url

    def resolve_program_interests(self, info, **kwargs):
        return self.interest_categories.all().values_list(
            'program__program_family__name', flat=True).distinct()

    def resolve_available_office_hours(self, info, **kwargs):
        user = info.context.user
        filter_kwargs = {
            'finalist__isnull': True,
            'date__gte': timezone.now(),
            'start_time__gte': timezone.now().time()
        }
        if not user.is_staff:
            filter_kwargs['program__in'] = _get_user_programs(user)
        return self.user.mentor_officehours.filter(
            **filter_kwargs).exists()

def _get_user_programs(user):
    # todo: refactor this and move it to a sensible place
    # todo: test this
    participant_roles = UserRole.FINALIST_USER_ROLES
    user_program_roles_as_participant = ProgramRole.objects.filter(
        programrolegrant__person=user,
        user_role__name__in=participant_roles
    )
    return Program.objects.filter(
        programrole__in=user_program_roles_as_participant).distinct()
<|endoftext|>


<commit_before>import numpy as np
from gym import utils
from gym.envs.mujoco import mujoco_env
import mujoco_py.mjlib

class Box3dReachEnv(mujoco_env.MujocoEnv, utils.EzPickle):
    def __init__(self):
        mujoco_env.MujocoEnv.__init__(self, 'arm_claw.xml', 4)
        utils.EzPickle.__init__(self)

    def _randomize_box(self):
        state_noise = np.zeros(16)
        state_noise[9:11] = self.np_random.uniform(low=-0.1, high=0.1, size=2)
        self.set_state(
                self.model.data.qpos.ravel() + state_noise,
                self.model.data.qvel.ravel(),
        )

    def _step(self, a):
        self.do_simulation(a, self.frame_skip)

        obs = self._get_obs()
        done = False

        contact_reward = 0.0

        # Check for contact
        d = self.unwrapped.data
        for coni in range(d.ncon):
            con = d.obj.contact[coni]
            if con.geom1 != 0 and con.geom2 == 12:
                # Small box is touched but not by table
                contact_reward = 1.0

        reward = contact_reward

        return obs, reward, done, dict(reward_contact=contact_reward)

    def viewer_setup(self):
        # print self.viewer.cam.mode
        # print type(self.viewer.cam)
        # mujoco_py.mjlib.mjv_defaultCamera(ctypes.byref(cam))
        self.viewer.cam.trackbodyid = 0
        self.viewer.cam.distance = self.model.stat.extent * 2.5
        self.viewer.cam.elevation += 20

    def reset_model(self):
        c = 0.01
        self.set_state(
            self.init_qpos + self.np_random.uniform(low=-c, high=c, size=self.model.nq),
            self.init_qvel + self.np_random.uniform(low=-c, high=c, size=self.model.nv,)
        )
        self._randomize_box()
        return self._get_obs()

    def _get_obs(self):
        return np.concatenate([
            self.model.data.qpos.flat,
            self.model.data.qvel.flat
        ])

class Box3dGraspEnv(mujoco_env.MujocoEnv, utils.EzPickle):
    def __init__(self):
        mujoco_env.MujocoEnv.__init__(self, 'arm_claw.xml', 4)
        utils.EzPickle.__init__(self)

    def _step(self, a):
        self.do_simulation(a, self.frame_skip)

        obs = self._get_obs()
        done = False

        contact_reward = 0.0
        grasp_reward = 0.0

        # Check for contact
        d = self.unwrapped.data
        for coni in range(d.ncon):
            con = d.obj.contact[coni]
            if con.geom1 != 0 and con.geom2 == 12:
                # Small box is touched but not by table
                box_height = self.model.data.qpos[11] - 0.025
                if box_height > 0.05:
                    grasp_reward = 1.0

        reward = contact_reward + grasp_reward

        return obs, reward, done, dict(reward_contact=contact_reward, reward_grasp=grasp_reward)

    def viewer_setup(self):
        # self.viewer.cam.trackbodyid = 0
        self.viewer.cam.distance = self.model.stat.extent * 2.5
        self.viewer.cam.elevation += 20

    def reset_model(self):
        c = 0.01
        self.set_state(
            self.init_qpos + self.np_random.uniform(low=-c, high=c, size=self.model.nq),
            self.init_qvel + self.np_random.uniform(low=-c, high=c, size=self.model.nv,)
        )
        return self._get_obs()

    def _get_obs(self):
        return np.concatenate([
            self.model.data.qpos.flat,
            self.model.data.qvel.flat
        ])
<commit_msg>random during init<commit_after>import numpy as np
from gym import utils
from gym.envs.mujoco import mujoco_env
import mujoco_py.mjlib

class Box3dReachEnv(mujoco_env.MujocoEnv, utils.EzPickle):
    def __init__(self):
        mujoco_env.MujocoEnv.__init__(self, 'arm_claw.xml', 4)
        utils.EzPickle.__init__(self)

        self._randomize_box()

    def _randomize_box(self):
        state_noise = np.zeros(16)
        state_noise[9:11] = self.np_random.uniform(low=-0.1, high=0.1, size=2)
        self.set_state(
                self.model.data.qpos.ravel() + state_noise,
                self.model.data.qvel.ravel(),
        )

    def _step(self, a):
        self.do_simulation(a, self.frame_skip)

        obs = self._get_obs()
        done = False

        contact_reward = 0.0

        # Check for contact
        d = self.unwrapped.data
        for coni in range(d.ncon):
            con = d.obj.contact[coni]
            if con.geom1 != 0 and con.geom2 == 12:
                # Small box is touched but not by table
                contact_reward = 1.0

        reward = contact_reward

        return obs, reward, done, dict(reward_contact=contact_reward)

    def viewer_setup(self):
        # print self.viewer.cam.mode
        # print type(self.viewer.cam)
        # mujoco_py.mjlib.mjv_defaultCamera(ctypes.byref(cam))
        self.viewer.cam.trackbodyid = 0
        self.viewer.cam.distance = self.model.stat.extent * 2.5
        self.viewer.cam.elevation += 20

    def reset_model(self):
        c = 0.01
        self.set_state(
            self.init_qpos + self.np_random.uniform(low=-c, high=c, size=self.model.nq),
            self.init_qvel + self.np_random.uniform(low=-c, high=c, size=self.model.nv,)
        )
        self._randomize_box()
        return self._get_obs()

    def _get_obs(self):
        return np.concatenate([
            self.model.data.qpos.flat,
            self.model.data.qvel.flat
        ])

class Box3dGraspEnv(mujoco_env.MujocoEnv, utils.EzPickle):
    def __init__(self):
        mujoco_env.MujocoEnv.__init__(self, 'arm_claw.xml', 4)
        utils.EzPickle.__init__(self)

    def _step(self, a):
        self.do_simulation(a, self.frame_skip)

        obs = self._get_obs()
        done = False

        contact_reward = 0.0
        grasp_reward = 0.0

        # Check for contact
        d = self.unwrapped.data
        for coni in range(d.ncon):
            con = d.obj.contact[coni]
            if con.geom1 != 0 and con.geom2 == 12:
                # Small box is touched but not by table
                box_height = self.model.data.qpos[11] - 0.025
                if box_height > 0.05:
                    grasp_reward = 1.0

        reward = contact_reward + grasp_reward

        return obs, reward, done, dict(reward_contact=contact_reward, reward_grasp=grasp_reward)

    def viewer_setup(self):
        # self.viewer.cam.trackbodyid = 0
        self.viewer.cam.distance = self.model.stat.extent * 2.5
        self.viewer.cam.elevation += 20

    def reset_model(self):
        c = 0.01
        self.set_state(
            self.init_qpos + self.np_random.uniform(low=-c, high=c, size=self.model.nq),
            self.init_qvel + self.np_random.uniform(low=-c, high=c, size=self.model.nv,)
        )
        return self._get_obs()

    def _get_obs(self):
        return np.concatenate([
            self.model.data.qpos.flat,
            self.model.data.qvel.flat
        ])
<|endoftext|>


<commit_before>import logging
import tempfile

from bzt.engine import Configuration
from bzt.utils import BetterDict
from tests import BZTestCase, __dir__

class TestConfiguration(BZTestCase):
    def test_load(self):
        obj = Configuration()
        configs = [
            __dir__() + "/../bzt/10-base.json",
            __dir__() + "/json/jmx.json",
            __dir__() + "/json/concurrency.json"
        ]
        obj.load(configs)
        logging.debug("config:\n%s", obj)

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.JSON)
        with open(fname) as fh:
            logging.debug("JSON:\n%s", fh.read())

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.YAML)
        with open(fname) as fh:
            logging.debug("YAML:\n%s", fh.read())

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.INI)
        with open(fname) as fh:
            logging.debug("INI:\n%s", fh.read())

    def test_merge(self):
        obj = Configuration()
        configs = [
            __dir__() + "/yaml/test.yml",
            __dir__() + "/json/merge1.json",
            __dir__() + "/json/merge2.json",
        ]
        obj.load(configs)
        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.JSON)
        with open(fname) as fh:
            logging.debug("JSON:\n%s", fh.read())
        jmeter = obj['modules']['jmeter']
        classval = jmeter['class']
        self.assertEquals("bzt.modules.jmeter.JMeterExecutor", classval)
        self.assertEquals("value", obj['key'])
        self.assertEquals(6, len(obj["list-append"]))
        self.assertEquals(2, len(obj["list-replace"]))
        self.assertEquals(2, len(obj["list-replace-notexistent"]))
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertFalse("properties" in jmeter)

        fname = tempfile.mkstemp()[1]
        obj.dump(fname)
        checker = Configuration()
        checker.load([fname])
        token = checker["list-complex"][1][0]['token']
        self.assertNotEquals('test', token)
        token_orig = obj["list-complex"][1][0]['token']
        self.assertEquals('test', token_orig)
<commit_msg>Fix test<commit_after>import logging
import tempfile

from bzt.engine import Configuration
from bzt.utils import BetterDict
from tests import BZTestCase, __dir__

class TestConfiguration(BZTestCase):
    def test_load(self):
        obj = Configuration()
        configs = [
            __dir__() + "/../bzt/10-base.json",
            __dir__() + "/json/jmx.json",
            __dir__() + "/json/concurrency.json"
        ]
        obj.load(configs)
        logging.debug("config:\n%s", obj)

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.JSON)
        with open(fname) as fh:
            logging.debug("JSON:\n%s", fh.read())

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.YAML)
        with open(fname) as fh:
            logging.debug("YAML:\n%s", fh.read())

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.INI)
        with open(fname) as fh:
            logging.debug("INI:\n%s", fh.read())

    def test_merge(self):
        obj = Configuration()
        configs = [
            __dir__() + "/yaml/test.yml",
            __dir__() + "/json/merge1.json",
            __dir__() + "/json/merge2.json",
        ]
        obj.load(configs)
        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.JSON)
        with open(fname) as fh:
            logging.debug("JSON:\n%s", fh.read())
        jmeter = obj['modules']['jmeter']
        classval = jmeter['class']
        self.assertEquals("bzt.modules.jmeter.JMeterExecutor", classval)
        self.assertEquals("value", obj['key'])
        self.assertEquals(6, len(obj["list-append"]))
        self.assertEquals(2, len(obj["list-replace"]))
        self.assertEquals(2, len(obj["list-replace-notexistent"]))
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertIsInstance(obj["list-complex"][1][0], BetterDict)
        self.assertFalse("properties" in jmeter)

        fname = tempfile.mkstemp()[1]
        obj.dump(fname, Configuration.JSON)
        checker = Configuration()
        checker.load([fname])
        token = checker["list-complex"][1][0]['token']
        self.assertNotEquals('test', token)
        token_orig = obj["list-complex"][1][0]['token']
        self.assertEquals('test', token_orig)
<|endoftext|>


<commit_before>from geopar.angle import Angle

"""
ISSUES:

SUGGESTIONS:

NOTES:
1. Triangle should consist of angles of the same dimension

"""

__author__ = 'satbek'

class Triangle:
    """
    INTENT:
    Defines a triangle with 3 angles and 3 vertices labeled by integers, in clockwise order.

    NOTES:
    Triangle vertices will be called 'points' throughout the rest of the program.

    _points contains three points (int instances) in clockwise order.
    _angles contains corresponding three angles (Angle instances) in clockwise order.
    """

    def __init__(self, three_points, three_angles):
        """
        PRE1: three_points consists of three distinct non-negative integers
        PRE2: three_angles consists of three Angle|int|float instances

        NOTES:
        int and float angles in three_angles will be converted to Angle objects.
        """

        # PRE1
        # non-negative
        if not all(list(map(lambda x: x > 0, three_points))):
            raise Exception('Negative point provided.')
        # exactly 3 distinct
        if len(three_points) != 3:
            raise Exception('Wrong number of points provided.')
        elif len(set(three_points)) != 3:
            raise Exception('Wrong number of points provided.')

        # PRE2
        for angle in three_angles:
            if not isinstance(angle, (Angle, int, float)):
                raise Exception('Angle provided is not Angle|int|float.')

        # convert int|float angles to Angle
        three_angles2 = []
        for angle in three_angles:
            if isinstance(angle, (int, float)):
                three_angles2.append(Angle([angle]))
            if isinstance(angle, Angle):
                three_angles2.append(angle)

        self._points = three_points
        self._angles = three_angles2

    def __str__(self):
        """
        Returns string representation of self.
        """

        return_string = 'TRIANGLE -> Vertices: {}, {}, {}; Angles: {}, {}, {}'.format(
            self.get_points()[0], self.get_points()[1], self.get_points()[2],
            self.get_angles()[0], self.get_angles()[1], self.get_angles()[2])

        return return_string

    def __hash__(self):
        """
        Computes and returns hash of self.
        """

        sorted_points = sorted(self._points)
        for_hash = str(sorted_points[0]) + str(hash(self.angle_of_point(sorted_points[0])))
        for_hash += str(sorted_points[1]) + str(hash(self.angle_of_point(sorted_points[1])))
        for_hash += str(sorted_points[2]) + str(hash(self.angle_of_point(sorted_points[2])))
        return hash(for_hash)

    def get_angles(self):
        """
        self._angles is returned
        """

        return self._angles

    def get_points(self):
        """
        self._points is returned
        """

        return self._points

    def angle_of_point(self, a_point):
        """
        INTENT: returns the angle of a_point
        PRE: self._points contains a_point
        POST: angle of a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        return self._angles[self._points.index(a_point)]

    def index_of_point(self, a_point):
        """
        INTENT: returns the position of a_point in self._points
        PRE: self._points contains a_point
        POST: index is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        return self.get_points().index(a_point)

    def point_following(self, a_point):
        """
        INTENT: Returns a point that follows a_point in clockwise order.
        PRE: self._points contains a_point
        POST: a point following a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        index_of_a_point = self._points.index(a_point)
        return self._points[(index_of_a_point + 1) % 3]

    def point_preceding(self, a_point):
        """
        INTENT: Returns a point that precedes a_point in clockwise order.
        PRE: self._points contains a_point
        POST: a point preceding a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        index_of_a_point = self._points.index(a_point)
        return self._points[(index_of_a_point - 1) % 3]

    def count_known(self):
        """
        INTENT: Count known angles in self
        POST: The number of known angles in self is returned
        """

        count = 0
        for angle in self._angles:
            if angle.is_known():
                count += 1
        return count

    def has_point(self, a_point):
        """
        INTENT: Does self have a point a_point?
        POST: True is returned, if a_point is in self._points; False, otherwise
        """

        return a_point in self._points

    def has_all_points(self, three_points):
        return set(self._points) == set(three_points)

    def has_unknown(self):
        """
        INTENT: Does self have unknown angles
        POST: True is returned, if self has an unknown angle; False, otherwise
        """

        return self.count_known() != 3

    def get_angle_points_by_point(self, a_point):
        ind = self.index_of_point(a_point)
        shift = (ind + 2) % 3
        points = self._points[shift:] + self._points[:shift]
        return points

    def set_angle_by_point(self, a_point, an_angle):
        """
        INTENT: Sets an angle of a_point in self to an_angle
        PRE: a_point is in self._points
        POST: self.angle_of_point(a_point) == an_angle
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        self._angles[self.index_of_point(a_point)] = an_angle

    def set_angle_by_index(self, an_index, an_angle):
        """
        INTENT: Sets self._angles[an_index] in self to an_angle
        PRE: an_index is either 0, 1, or 2
        POST: self._angles[an_index] == an_angle
        """

        if an_index not in [0, 1, 2]:
            raise Exception('Bad index.')

        self._angles[an_index] = an_angle

    def complete_unknown_angle(self):
        """
        INTENT: If self has an unknown angle, this method completes it using 180 rule.
        PRE: Two angles in self._angles are known, and one is unknown
        POST: All three angles in self._angles are known
        """

        if self.count_known() == 2:
            s = 0
            for an in self.get_angles():
                if an.is_known():
                    s += an
            s = s.get_coefficients()
            third = 180 - Angle(s)
            for i in range(3):
                if not self._angles[i].is_known():
                    self._angles[i] = third
<commit_msg>a big chunk of code moved out of if<commit_after>from geopar.angle import Angle

"""
ISSUES:

SUGGESTIONS:

NOTES:
1. Triangle should consist of angles of the same dimension

"""

__author__ = 'satbek'

class Triangle:
    """
    INTENT:
    Defines a triangle with 3 angles and 3 vertices labeled by integers, in clockwise order.

    NOTES:
    Triangle vertices will be called 'points' throughout the rest of the program.

    _points contains three points (int instances) in clockwise order.
    _angles contains corresponding three angles (Angle instances) in clockwise order.
    """

    def __init__(self, three_points, three_angles):
        """
        PRE1: three_points consists of three distinct non-negative integers
        PRE2: three_angles consists of three Angle|int|float instances

        NOTES:
        int and float angles in three_angles will be converted to Angle objects.
        """

        # PRE1
        # non-negative
        if not all(list(map(lambda x: x > 0, three_points))):
            raise Exception('Negative point provided.')
        # exactly 3 distinct
        if len(three_points) != 3:
            raise Exception('Wrong number of points provided.')
        elif len(set(three_points)) != 3:
            raise Exception('Wrong number of points provided.')

        # PRE2
        for angle in three_angles:
            if not isinstance(angle, (Angle, int, float)):
                raise Exception('Angle provided is not Angle|int|float.')

        # convert int|float angles to Angle
        three_angles2 = []
        for angle in three_angles:
            if isinstance(angle, (int, float)):
                three_angles2.append(Angle([angle]))
            if isinstance(angle, Angle):
                three_angles2.append(angle)

        self._points = three_points
        self._angles = three_angles2

    def __str__(self):
        """
        Returns string representation of self.
        """

        return_string = 'TRIANGLE -> Vertices: {}, {}, {}; Angles: {}, {}, {}'.format(
            self.get_points()[0], self.get_points()[1], self.get_points()[2],
            self.get_angles()[0], self.get_angles()[1], self.get_angles()[2])

        return return_string

    def __hash__(self):
        """
        Computes and returns hash of self.
        """

        sorted_points = sorted(self._points)
        for_hash = str(sorted_points[0]) + str(hash(self.angle_of_point(sorted_points[0])))
        for_hash += str(sorted_points[1]) + str(hash(self.angle_of_point(sorted_points[1])))
        for_hash += str(sorted_points[2]) + str(hash(self.angle_of_point(sorted_points[2])))
        return hash(for_hash)

    def get_angles(self):
        """
        self._angles is returned
        """

        return self._angles

    def get_points(self):
        """
        self._points is returned
        """

        return self._points

    def angle_of_point(self, a_point):
        """
        INTENT: returns the angle of a_point
        PRE: self._points contains a_point
        POST: angle of a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        return self._angles[self._points.index(a_point)]

    def index_of_point(self, a_point):
        """
        INTENT: returns the position of a_point in self._points
        PRE: self._points contains a_point
        POST: index is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        return self.get_points().index(a_point)

    def point_following(self, a_point):
        """
        INTENT: Returns a point that follows a_point in clockwise order.
        PRE: self._points contains a_point
        POST: a point following a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        index_of_a_point = self._points.index(a_point)
        return self._points[(index_of_a_point + 1) % 3]

    def point_preceding(self, a_point):
        """
        INTENT: Returns a point that precedes a_point in clockwise order.
        PRE: self._points contains a_point
        POST: a point preceding a_point is returned
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        index_of_a_point = self._points.index(a_point)
        return self._points[(index_of_a_point - 1) % 3]

    def count_known(self):
        """
        INTENT: Count known angles in self
        POST: The number of known angles in self is returned
        """

        count = 0
        for angle in self._angles:
            if angle.is_known():
                count += 1
        return count

    def has_point(self, a_point):
        """
        INTENT: Does self have a point a_point?
        POST: True is returned, if a_point is in self._points; False, otherwise
        """

        return a_point in self._points

    def has_all_points(self, three_points):
        return set(self._points) == set(three_points)

    def has_unknown(self):
        """
        INTENT: Does self have unknown angles
        POST: True is returned, if self has an unknown angle; False, otherwise
        """

        return self.count_known() != 3

    def get_angle_points_by_point(self, a_point):
        ind = self.index_of_point(a_point)
        shift = (ind + 2) % 3
        points = self._points[shift:] + self._points[:shift]
        return points

    def set_angle_by_point(self, a_point, an_angle):
        """
        INTENT: Sets an angle of a_point in self to an_angle
        PRE: a_point is in self._points
        POST: self.angle_of_point(a_point) == an_angle
        """

        if a_point not in self._points:
            raise Exception('There is no such point.')

        self._angles[self.index_of_point(a_point)] = an_angle

    def set_angle_by_index(self, an_index, an_angle):
        """
        INTENT: Sets self._angles[an_index] in self to an_angle
        PRE: an_index is either 0, 1, or 2
        POST: self._angles[an_index] == an_angle
        """

        if an_index not in [0, 1, 2]:
            raise Exception('Bad index.')

        self._angles[an_index] = an_angle

    def complete_unknown_angle(self):
        """
        Completes a triangle with one unknown angle.

        PRE: self.count_known() == 2 is True.
        POST: self.count_known() == 3 is True.
        """

        # Ensuring PRE
        if self.count_known() != 2:
            raise Exception('Something went wrong.')

        s = 0
        for an in self.get_angles():
            if an.is_known():
                s += an

        s = s.get_coefficients()
        third = 180 - Angle(s)
        for i in range(3):
            if not self._angles[i].is_known():
                self._angles[i] = third
<|endoftext|>