<commit_before># Copyright (C) 2018 OpenMotics BV
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
""""
The platform_utils module contains various classes helping with Hardware, System and Platform abstraction
"""
from __future__ import absolute_import
import logging
import os
import subprocess
import sys
import constants

if False:  # MYPY
    from typing import Union, Dict

logger = logging.getLogger('openmotics')

class Hardware(object):
    """
    Abstracts the hardware related functions
    """
    class BoardType(object):
        BB = 'BB'
        BBB = 'BBB'
        BBGW = 'BBGW'
        ESAFE = 'ESAFE'

    BoardTypes = [BoardType.BB, BoardType.BBB, BoardType.BBGW]

    class GPIO_DIRECTION(object):
        IN = 'in'
        OUT = 'out'

    GPIO_BASE_PATH = '/sys/class/gpio'
    GPIO_EXPORT_PATH = '{0}/export'.format(GPIO_BASE_PATH)
    GPIO_DIRECTION_PATH = '{0}/gpio{{0}}/direction'.format(GPIO_BASE_PATH)
    GPIO_VALUE_PATH = '{0}/gpio{{0}}/value'.format(GPIO_BASE_PATH)

    class GPIO(object):
        RS232_MODE = 77
        P1_DATA_ENABLE = 113
        P1_CABLE_CONNECTED = 115

    # eMMC registers
    EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B = 269
    EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A = 268
    EXT_CSD_PRE_EOL_INFO = 267

    @staticmethod
    def read_mmc_ext_csd():
        registers = {
            'life_time_est_typ_b': Hardware.EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B,
            'life_time_est_typ_a': Hardware.EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A,
            'eol_info': Hardware.EXT_CSD_PRE_EOL_INFO,
        }
        with open('/sys/kernel/debug/mmc1/mmc1:0001/ext_csd') as fd:
            ecsd = fd.read()

        ecsd_info = {}
        # NOTE: this only works for fields with length 1
        for reg, i in registers.items():
            pos = i * 2
            ecsd_info[reg] = int(ecsd[pos:pos + 2], 16)
        return ecsd_info

    @staticmethod
    def get_board_type():
        try:
            with open('/proc/device-tree/model', 'r') as mfh:
                board_type = mfh.read().strip('\x00').replace(' ', '_')
                if board_type in ['TI_AM335x_BeagleBone', 'TI_AM335x_BeagleBone_Black']:
                    return Hardware.BoardType.BBB
                if board_type in ['TI_AM335x_BeagleBone_Green_Wireless']:
                    return Hardware.BoardType.BBGW
                if board_type in ['TI_AM335x_esafe_Custom']:
                    return Hardware.BoardType.ESAFE
        except IOError:
            pass
        try:
            with open('/proc/meminfo', 'r') as memfh:
                mem_total = memfh.readline()
                if '254228 kB' in mem_total:
                    return Hardware.BoardType.BB
                if '510716 kB' in mem_total:
                    return Hardware.BoardType.BBB
        except IOError:
            pass
        logger.warning('could not detect board type, unknown')
        return  # Unknown

    @staticmethod
    def get_main_interface():
        board_type = Hardware.get_board_type()
        if board_type in [Hardware.BoardType.BB, Hardware.BoardType.BBB, Hardware.BoardType.ESAFE]:
            return 'eth0'
        if board_type == Hardware.BoardType.BBGW:
            return 'wlan0'
        logger.warning('Could not detect local interface. Fallback: lo')
        return 'lo'

    @staticmethod
    def get_mac_address():  # type: () -> Union[str, None]
        """ Get the main interface mac address """
        interface = Hardware.get_main_interface()
        try:
            # This works both on Angstrom and Debian
            with open('/sys/class/net/{0}/address'.format(interface)) as mac_address:
                return mac_address.read().strip().upper()
        except Exception:
            return None

    @staticmethod
    def set_gpio_direction(gpio_pin, direction):  # type: (int, str) -> None
        try:
            with open(Hardware.GPIO_EXPORT_PATH, 'w') as gpio:
                gpio.write(str(gpio_pin))
        except Exception:
            pass  # This raises every now and then if the pin was already exported
        with open(Hardware.GPIO_DIRECTION_PATH.format(gpio_pin), 'w') as gpio:
            gpio.write(direction)

    @staticmethod
    def set_gpio(gpio_pin, value):  # type: (int, bool) -> None
        Hardware.set_gpio_direction(gpio_pin=gpio_pin,
                                    direction=Hardware.GPIO_DIRECTION.OUT)
        with open(Hardware.GPIO_VALUE_PATH.format(gpio_pin), 'w') as gpio:
            gpio.write('1' if value else '0')

    @staticmethod
    def enable_extension_rs485_port():
        current_platform = Platform.get_platform()
        if current_platform not in Platform.CoreTypes:
            raise RuntimeError('Platform {0} does not support the extension RS485 port')
        Hardware.set_gpio(Hardware.GPIO.RS232_MODE, False)

class System(object):
    """
    Abstracts the system related functions
    """

    SYSTEMD_UNIT_MAP = {'openmotics': 'openmotics-api.service',
                        'vpn_service': 'openmotics-vpn.service'}
    # runit action map to make sure the executable will be stopped,
    # otherwise runit will return timeout, but not have killed the app
    RUNIT_ACTION_MAP = {'status': 'status',
                        'stop': 'force-stop',
                        'restart': 'force-restart'}

    class OS(object):
        ANGSTROM = 'angstrom'
        DEBIAN = 'debian'
        BUILDROOT = 'buildroot'

    @staticmethod
    def restart_service(service):
        # type: (str) -> None
        System.run_service_action('restart', service)

    @staticmethod
    def run_service_action(action, service):
        # type: (str, str) -> subprocess.Popen
        unit_name = System.SYSTEMD_UNIT_MAP.get(service, service)
        is_systemd = False
        is_supervisor = False
        is_runit = False
        try:
            subprocess.check_output(['systemctl', 'is-enabled', unit_name])
            is_systemd = True
        except subprocess.CalledProcessError:
            is_systemd = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_systemd = False

        try:
            subprocess.check_output(['supervisorctl', 'status', service])
            is_supervisor = True
        except subprocess.CalledProcessError:
            is_supervisor = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_supervisor = False

        try:
            runit_path = constants.get_runit_service_folder()
            subprocess.check_output(['sv', 'status', os.path.join(runit_path, service)])
            is_runit = True
        except subprocess.CalledProcessError:
            is_runit = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_runit = False

        if is_systemd:
            return subprocess.Popen(['systemctl', action, '--no-pager', unit_name],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        elif is_supervisor:
            return subprocess.Popen(['supervisorctl', action, service],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        elif is_runit:
            runit_path = constants.get_runit_service_folder()
            service_str = os.path.join(runit_path, service)
            return subprocess.Popen(['sv', action, service_str],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        else:
            raise RuntimeError('Could not find the appropriate service manager to run the service action command')

    @staticmethod
    def get_operating_system():
        # type: () -> Dict[str, str]
        operating_system = {}
        try:
            with open('/etc/os-release', 'r') as osfh:
                lines = osfh.readlines()
                for line in lines:
                    k, v = line.strip().split('=')
                    operating_system[k] = v
            operating_system['ID'] = operating_system['ID'].lower()
        except IOError:
            logger.warning('could not detect operating system, unknown')
        return operating_system

    @staticmethod
    def get_ip_address():
        """ Get the local ip address. """
        interface = Hardware.get_main_interface()
        operating_system = System.get_operating_system()
        try:
            lines = subprocess.check_output('ifconfig {0}'.format(interface), shell=True)
            # In python3, lines is a bytes array variable, not a string. -> decoding it into a string
            if not isinstance(lines, str):
                lines = lines.decode('utf-8')
            if operating_system['ID'] == System.OS.ANGSTROM:
                return lines.split('\n')[1].strip().split(' ')[1].split(':')[1]
            elif operating_system['ID'] == System.OS.DEBIAN:
                return lines.split('\n')[1].strip().split(' ')[1]
            elif operating_system['ID'] == System.OS.BUILDROOT:
                return lines.split('\n')[1].strip().split(' ')[1].replace('addr:','')  # The buildroot OS prefixes addresses with 'addr'
            else:
                return
        except Exception:
            return

    @staticmethod
    def get_vpn_service():
        return 'openvpn.service' if System.get_operating_system().get('ID') == System.OS.ANGSTROM else 'openvpn-client@omcloud'

    @staticmethod
    def _use_pyopenssl():
        return System.get_operating_system().get('ID') == System.OS.ANGSTROM

    @staticmethod
    def get_ssl_socket(sock, private_key_filename, certificate_filename):
        if System._use_pyopenssl():
            from OpenSSL import SSL
            context = SSL.Context(SSL.SSLv23_METHOD)
            context.use_privatekey_file(private_key_filename)
            context.use_certificate_file(certificate_filename)
            return SSL.Connection(context, sock)
        import ssl
        return ssl.wrap_socket(sock,
                               keyfile=private_key_filename,
                               certfile=certificate_filename,
                               ssl_version=ssl.PROTOCOL_SSLv23,
                               do_handshake_on_connect=False,
                               suppress_ragged_eofs=False)

    @staticmethod
    def setup_cherrypy_ssl(https_server):
        if System._use_pyopenssl():
            https_server.ssl_module = 'pyopenssl'
        else:
            import ssl
            https_server.ssl_module = 'builtin'
            if sys.version_info[:3] < (3, 6, 0):
                https_server.ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

    @staticmethod
    def handle_socket_exception(connection, exception, logger):
        if System._use_pyopenssl():
            import select
            from OpenSSL import SSL
            if isinstance(exception, SSL.SysCallError):
                if exception[0] == 11:  # Temporarily unavailable
                    # This should be ok, just wait for more data to arrive
                    return True  # continue
                if exception[0] == -1:  # Unexpected EOF
                    logger.info('Got (unexpected) EOF, aborting due to lost connection')
                    return False  # break
            elif isinstance(exception, SSL.WantReadError):
                # This should be ok, just wait for more data to arrive
                select.select([connection], [], [], 1.0)
                return True  # continue
        else:
            import select
            import ssl
            if isinstance(exception, ssl.SSLEOFError):
                logger.info('Got SSLEOFError, aborting due to lost connection')
                return False  # break
            elif isinstance(exception, ssl.SSLError):
                if 'The read operation timed out' in str(exception):
                    # Got read timeout, just wait for data to arrive
                    return True  # continue
        raise exception

    @staticmethod
    def import_libs():
        operating_system = System.get_operating_system().get('ID')
        # check if running in python 2 mode, otherwise packages should be included in the build (PyInstaller)
        if sys.version_info.major == 2:
            import site
            path = '/opt/openmotics/python-deps/lib/python2.7/site-packages'
            if os.path.exists(path):
                site.addsitedir(path)
                sys.path.remove(path)
                sys.path.insert(0, path)
            path = '/opt/openmotics/python-deps/lib/python2.7/dist-packages'
            if os.path.exists(path):
                site.addsitedir(path)
                sys.path.remove(path)
                sys.path.insert(0, path)

        # Patching where/if required
        if operating_system == System.OS.ANGSTROM:
            from pkg_resources import resource_filename, resource_stream, Requirement
            resource_stream(Requirement.parse('requests'), 'requests/cacert.pem')
            os.environ['REQUESTS_CA_BUNDLE'] = resource_filename(Requirement.parse('requests'), 'requests/cacert.pem')

class Platform(object):
    """
    Abstracts the platform related functions
    """

    class Type(object):
        DUMMY = 'DUMMY'
        CLASSIC = 'CLASSIC'
        CORE_PLUS = 'CORE_PLUS'
        CORE = 'CORE'
        ESAFE = 'ESAFE'

    AnyTypes = [Type.DUMMY]
    ClassicTypes = [Type.CLASSIC]
    CoreTypes = [Type.CORE, Type.CORE_PLUS]
    EsafeTypes = [Type.ESAFE]
    Types = AnyTypes + ClassicTypes + CoreTypes + EsafeTypes

    @staticmethod
    def get_platform():
        # type: () -> str
        from six.moves.configparser import ConfigParser
        config = ConfigParser()
        config.read(constants.get_config_file())

        if config.has_option('OpenMotics', 'platform'):
            platform = config.get('OpenMotics', 'platform')
            if platform in Platform.Types:
                return platform
        return Platform.Type.CLASSIC

    @staticmethod
    def has_master_hardware():
        # type: () -> bool
        if Platform.get_platform() in [Platform.Type.DUMMY, Platform.Type.ESAFE]:
            return False
        return True

    @staticmethod
    def http_port():
        # type: () -> int
        try:
            from six.moves.configparser import ConfigParser
            config = ConfigParser()
            config.read(constants.get_config_file())
            http_port = int(config.get('OpenMotics', 'http_port'))
            if http_port is None:
                http_port = 80  # default http port
            return http_port
        except Exception:
            return 80

    @staticmethod
    def https_port():
        # type: () -> int
        try:
            from six.moves.configparser import ConfigParser
            config = ConfigParser()
            config.read(constants.get_config_file())
            https_port = int(config.get('OpenMotics', 'https_port'))
            if https_port is None:
                https_port = 433  # default https port
            return https_port
        except Exception:
            return 433
<commit_msg>Remove the dist-packages folder from imports<commit_after># Copyright (C) 2018 OpenMotics BV
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
""""
The platform_utils module contains various classes helping with Hardware, System and Platform abstraction
"""
from __future__ import absolute_import
import logging
import os
import subprocess
import sys
import constants

if False:  # MYPY
    from typing import Union, Dict

logger = logging.getLogger('openmotics')

class Hardware(object):
    """
    Abstracts the hardware related functions
    """
    class BoardType(object):
        BB = 'BB'
        BBB = 'BBB'
        BBGW = 'BBGW'
        ESAFE = 'ESAFE'

    BoardTypes = [BoardType.BB, BoardType.BBB, BoardType.BBGW]

    class GPIO_DIRECTION(object):
        IN = 'in'
        OUT = 'out'

    GPIO_BASE_PATH = '/sys/class/gpio'
    GPIO_EXPORT_PATH = '{0}/export'.format(GPIO_BASE_PATH)
    GPIO_DIRECTION_PATH = '{0}/gpio{{0}}/direction'.format(GPIO_BASE_PATH)
    GPIO_VALUE_PATH = '{0}/gpio{{0}}/value'.format(GPIO_BASE_PATH)

    class GPIO(object):
        RS232_MODE = 77
        P1_DATA_ENABLE = 113
        P1_CABLE_CONNECTED = 115

    # eMMC registers
    EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B = 269
    EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A = 268
    EXT_CSD_PRE_EOL_INFO = 267

    @staticmethod
    def read_mmc_ext_csd():
        registers = {
            'life_time_est_typ_b': Hardware.EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B,
            'life_time_est_typ_a': Hardware.EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A,
            'eol_info': Hardware.EXT_CSD_PRE_EOL_INFO,
        }
        with open('/sys/kernel/debug/mmc1/mmc1:0001/ext_csd') as fd:
            ecsd = fd.read()

        ecsd_info = {}
        # NOTE: this only works for fields with length 1
        for reg, i in registers.items():
            pos = i * 2
            ecsd_info[reg] = int(ecsd[pos:pos + 2], 16)
        return ecsd_info

    @staticmethod
    def get_board_type():
        try:
            with open('/proc/device-tree/model', 'r') as mfh:
                board_type = mfh.read().strip('\x00').replace(' ', '_')
                if board_type in ['TI_AM335x_BeagleBone', 'TI_AM335x_BeagleBone_Black']:
                    return Hardware.BoardType.BBB
                if board_type in ['TI_AM335x_BeagleBone_Green_Wireless']:
                    return Hardware.BoardType.BBGW
                if board_type in ['TI_AM335x_esafe_Custom']:
                    return Hardware.BoardType.ESAFE
        except IOError:
            pass
        try:
            with open('/proc/meminfo', 'r') as memfh:
                mem_total = memfh.readline()
                if '254228 kB' in mem_total:
                    return Hardware.BoardType.BB
                if '510716 kB' in mem_total:
                    return Hardware.BoardType.BBB
        except IOError:
            pass
        logger.warning('could not detect board type, unknown')
        return  # Unknown

    @staticmethod
    def get_main_interface():
        board_type = Hardware.get_board_type()
        if board_type in [Hardware.BoardType.BB, Hardware.BoardType.BBB, Hardware.BoardType.ESAFE]:
            return 'eth0'
        if board_type == Hardware.BoardType.BBGW:
            return 'wlan0'
        logger.warning('Could not detect local interface. Fallback: lo')
        return 'lo'

    @staticmethod
    def get_mac_address():  # type: () -> Union[str, None]
        """ Get the main interface mac address """
        interface = Hardware.get_main_interface()
        try:
            # This works both on Angstrom and Debian
            with open('/sys/class/net/{0}/address'.format(interface)) as mac_address:
                return mac_address.read().strip().upper()
        except Exception:
            return None

    @staticmethod
    def set_gpio_direction(gpio_pin, direction):  # type: (int, str) -> None
        try:
            with open(Hardware.GPIO_EXPORT_PATH, 'w') as gpio:
                gpio.write(str(gpio_pin))
        except Exception:
            pass  # This raises every now and then if the pin was already exported
        with open(Hardware.GPIO_DIRECTION_PATH.format(gpio_pin), 'w') as gpio:
            gpio.write(direction)

    @staticmethod
    def set_gpio(gpio_pin, value):  # type: (int, bool) -> None
        Hardware.set_gpio_direction(gpio_pin=gpio_pin,
                                    direction=Hardware.GPIO_DIRECTION.OUT)
        with open(Hardware.GPIO_VALUE_PATH.format(gpio_pin), 'w') as gpio:
            gpio.write('1' if value else '0')

    @staticmethod
    def enable_extension_rs485_port():
        current_platform = Platform.get_platform()
        if current_platform not in Platform.CoreTypes:
            raise RuntimeError('Platform {0} does not support the extension RS485 port')
        Hardware.set_gpio(Hardware.GPIO.RS232_MODE, False)

class System(object):
    """
    Abstracts the system related functions
    """

    SYSTEMD_UNIT_MAP = {'openmotics': 'openmotics-api.service',
                        'vpn_service': 'openmotics-vpn.service'}
    # runit action map to make sure the executable will be stopped,
    # otherwise runit will return timeout, but not have killed the app
    RUNIT_ACTION_MAP = {'status': 'status',
                        'stop': 'force-stop',
                        'restart': 'force-restart'}

    class OS(object):
        ANGSTROM = 'angstrom'
        DEBIAN = 'debian'
        BUILDROOT = 'buildroot'

    @staticmethod
    def restart_service(service):
        # type: (str) -> None
        System.run_service_action('restart', service)

    @staticmethod
    def run_service_action(action, service):
        # type: (str, str) -> subprocess.Popen
        unit_name = System.SYSTEMD_UNIT_MAP.get(service, service)
        is_systemd = False
        is_supervisor = False
        is_runit = False
        try:
            subprocess.check_output(['systemctl', 'is-enabled', unit_name])
            is_systemd = True
        except subprocess.CalledProcessError:
            is_systemd = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_systemd = False

        try:
            subprocess.check_output(['supervisorctl', 'status', service])
            is_supervisor = True
        except subprocess.CalledProcessError:
            is_supervisor = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_supervisor = False

        try:
            runit_path = constants.get_runit_service_folder()
            subprocess.check_output(['sv', 'status', os.path.join(runit_path, service)])
            is_runit = True
        except subprocess.CalledProcessError:
            is_runit = False
        except Exception:  # Python 3 error (FileNotFoundErr) but is not known in python 2...
            is_runit = False

        if is_systemd:
            return subprocess.Popen(['systemctl', action, '--no-pager', unit_name],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        elif is_supervisor:
            return subprocess.Popen(['supervisorctl', action, service],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        elif is_runit:
            runit_path = constants.get_runit_service_folder()
            service_str = os.path.join(runit_path, service)
            return subprocess.Popen(['sv', action, service_str],
                                    stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                    close_fds=True)
        else:
            raise RuntimeError('Could not find the appropriate service manager to run the service action command')

    @staticmethod
    def get_operating_system():
        # type: () -> Dict[str, str]
        operating_system = {}
        try:
            with open('/etc/os-release', 'r') as osfh:
                lines = osfh.readlines()
                for line in lines:
                    k, v = line.strip().split('=')
                    operating_system[k] = v
            operating_system['ID'] = operating_system['ID'].lower()
        except IOError:
            logger.warning('could not detect operating system, unknown')
        return operating_system

    @staticmethod
    def get_ip_address():
        """ Get the local ip address. """
        interface = Hardware.get_main_interface()
        operating_system = System.get_operating_system()
        try:
            lines = subprocess.check_output('ifconfig {0}'.format(interface), shell=True)
            # In python3, lines is a bytes array variable, not a string. -> decoding it into a string
            if not isinstance(lines, str):
                lines = lines.decode('utf-8')
            if operating_system['ID'] == System.OS.ANGSTROM:
                return lines.split('\n')[1].strip().split(' ')[1].split(':')[1]
            elif operating_system['ID'] == System.OS.DEBIAN:
                return lines.split('\n')[1].strip().split(' ')[1]
            elif operating_system['ID'] == System.OS.BUILDROOT:
                return lines.split('\n')[1].strip().split(' ')[1].replace('addr:','')  # The buildroot OS prefixes addresses with 'addr'
            else:
                return
        except Exception:
            return

    @staticmethod
    def get_vpn_service():
        return 'openvpn.service' if System.get_operating_system().get('ID') == System.OS.ANGSTROM else 'openvpn-client@omcloud'

    @staticmethod
    def _use_pyopenssl():
        return System.get_operating_system().get('ID') == System.OS.ANGSTROM

    @staticmethod
    def get_ssl_socket(sock, private_key_filename, certificate_filename):
        if System._use_pyopenssl():
            from OpenSSL import SSL
            context = SSL.Context(SSL.SSLv23_METHOD)
            context.use_privatekey_file(private_key_filename)
            context.use_certificate_file(certificate_filename)
            return SSL.Connection(context, sock)
        import ssl
        return ssl.wrap_socket(sock,
                               keyfile=private_key_filename,
                               certfile=certificate_filename,
                               ssl_version=ssl.PROTOCOL_SSLv23,
                               do_handshake_on_connect=False,
                               suppress_ragged_eofs=False)

    @staticmethod
    def setup_cherrypy_ssl(https_server):
        if System._use_pyopenssl():
            https_server.ssl_module = 'pyopenssl'
        else:
            import ssl
            https_server.ssl_module = 'builtin'
            if sys.version_info[:3] < (3, 6, 0):
                https_server.ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

    @staticmethod
    def handle_socket_exception(connection, exception, logger):
        if System._use_pyopenssl():
            import select
            from OpenSSL import SSL
            if isinstance(exception, SSL.SysCallError):
                if exception[0] == 11:  # Temporarily unavailable
                    # This should be ok, just wait for more data to arrive
                    return True  # continue
                if exception[0] == -1:  # Unexpected EOF
                    logger.info('Got (unexpected) EOF, aborting due to lost connection')
                    return False  # break
            elif isinstance(exception, SSL.WantReadError):
                # This should be ok, just wait for more data to arrive
                select.select([connection], [], [], 1.0)
                return True  # continue
        else:
            import select
            import ssl
            if isinstance(exception, ssl.SSLEOFError):
                logger.info('Got SSLEOFError, aborting due to lost connection')
                return False  # break
            elif isinstance(exception, ssl.SSLError):
                if 'The read operation timed out' in str(exception):
                    # Got read timeout, just wait for data to arrive
                    return True  # continue
        raise exception

    @staticmethod
    def import_libs():
        operating_system = System.get_operating_system().get('ID')
        # check if running in python 2 mode, otherwise packages should be included in the build (PyInstaller)
        if sys.version_info.major == 2:
            import site
            path = '/opt/openmotics/python-deps/lib/python2.7/site-packages'
            if os.path.exists(path):
                site.addsitedir(path)
                sys.path.remove(path)
                sys.path.insert(0, path)

        # Patching where/if required
        if operating_system == System.OS.ANGSTROM:
            from pkg_resources import resource_filename, resource_stream, Requirement
            resource_stream(Requirement.parse('requests'), 'requests/cacert.pem')
            os.environ['REQUESTS_CA_BUNDLE'] = resource_filename(Requirement.parse('requests'), 'requests/cacert.pem')

class Platform(object):
    """
    Abstracts the platform related functions
    """

    class Type(object):
        DUMMY = 'DUMMY'
        CLASSIC = 'CLASSIC'
        CORE_PLUS = 'CORE_PLUS'
        CORE = 'CORE'
        ESAFE = 'ESAFE'

    AnyTypes = [Type.DUMMY]
    ClassicTypes = [Type.CLASSIC]
    CoreTypes = [Type.CORE, Type.CORE_PLUS]
    EsafeTypes = [Type.ESAFE]
    Types = AnyTypes + ClassicTypes + CoreTypes + EsafeTypes

    @staticmethod
    def get_platform():
        # type: () -> str
        from six.moves.configparser import ConfigParser
        config = ConfigParser()
        config.read(constants.get_config_file())

        if config.has_option('OpenMotics', 'platform'):
            platform = config.get('OpenMotics', 'platform')
            if platform in Platform.Types:
                return platform
        return Platform.Type.CLASSIC

    @staticmethod
    def has_master_hardware():
        # type: () -> bool
        if Platform.get_platform() in [Platform.Type.DUMMY, Platform.Type.ESAFE]:
            return False
        return True

    @staticmethod
    def http_port():
        # type: () -> int
        try:
            from six.moves.configparser import ConfigParser
            config = ConfigParser()
            config.read(constants.get_config_file())
            http_port = int(config.get('OpenMotics', 'http_port'))
            if http_port is None:
                http_port = 80  # default http port
            return http_port
        except Exception:
            return 80

    @staticmethod
    def https_port():
        # type: () -> int
        try:
            from six.moves.configparser import ConfigParser
            config = ConfigParser()
            config.read(constants.get_config_file())
            https_port = int(config.get('OpenMotics', 'https_port'))
            if https_port is None:
                https_port = 433  # default https port
            return https_port
        except Exception:
            return 433
<|endoftext|>


<commit_before>"""
URL mappings for muckrock project
"""

# pylint: disable-msg=W0611
# these are called dynmically
from django.conf.urls.defaults import handler404, handler500
# pylint: enable-msg=W0611
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
from django.contrib.auth.decorators import login_required
from django.views.generic.simple import direct_to_template
from django.contrib.sitemaps.views import sitemap

from haystack.views import basic_search

import muckrock.accounts.urls, muckrock.foia.urls, muckrock.news.urls
import muckrock.settings
from muckrock.news.sitemap import ArticleSitemap
from muckrock.foia.sitemap import FoiaSitemap

import os

admin.autodiscover()

sitemaps = {'FOIA': FoiaSitemap, 'News': ArticleSitemap}

urlpatterns = patterns('',
    url(r'^$', direct_to_template, {'template': 'beta_home.html'}, name='index'),
    url(r'^accounts/', include(muckrock.accounts.urls)),
    url(r'^foia/', include(muckrock.foia.urls)),
    url(r'^news/', include(muckrock.news.urls)),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^search/$', login_required(basic_search)),
    url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='sitemap')
)

if muckrock.settings.DEBUG:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', 'django.views.static.serve',
            {'document_root': os.path.join(muckrock.settings.SITE_ROOT, 'static')}),
        (r'^user_media/(?P<path>.*)$', 'django.views.static.serve',
            {'document_root': os.path.join(muckrock.settings.SITE_ROOT, 'user_media')}),
    )
<commit_msg>fix urls.py (got messed up somehow)<commit_after>"""
URL mappings for muckrock project
"""

# pylint: disable-msg=W0611
# these are called dynmically
from django.conf.urls.defaults import handler404, handler500
# pylint: enable-msg=W0611
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
from django.views.generic.date_based import archive_index
from django.contrib.sitemaps.views import sitemap

import haystack.urls

import muckrock.accounts.urls, muckrock.foia.urls, muckrock.news.urls
import muckrock.settings
from muckrock.news.models import Article
from muckrock.news.sitemap import ArticleSitemap
from muckrock.foia.sitemap import FoiaSitemap

import os

admin.autodiscover()

article_args = {'queryset': Article.objects.get_published(), 'date_field': 'pub_date',
                'allow_empty': True, 'num_latest': 5}
sitemaps = {'FOIA': FoiaSitemap, 'News': ArticleSitemap}

urlpatterns = patterns('',
    url(r'^$', archive_index, article_args, name='index'),
    url(r'^accounts/', include(muckrock.accounts.urls)),
    url(r'^foia/', include(muckrock.foia.urls)),
    url(r'^news/', include(muckrock.news.urls)),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^search/', include(haystack.urls)),
    url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='sitemap')
)

if muckrock.settings.DEBUG:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', 'django.views.static.serve',
            {'document_root': os.path.join(muckrock.settings.SITE_ROOT, 'static')}),
        (r'^user_media/(?P<path>.*)$', 'django.views.static.serve',
            {'document_root': os.path.join(muckrock.settings.SITE_ROOT, 'user_media')}),
    )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
""" Compiled regular expressions for extracting dates, times, acronyms, etc

>>> CRE_ACRONYM.findall('National science Foundation (NSF)')
[('', '', '', '', 'National science Foundation', 'N', 's', 'F', 'NSF')]
>>> re.findall(RE_URL_SIMPLE, '* Sublime Text 3 (https://www.sublimetext.com/3) is great!')[0][0]
'https://www.sublimetext.com/3'
>>> re.findall(RE_URL_SIMPLE, 'Google github totalgood [github.com/totalgood]!')[0][0]
'github.com/totalgood'
"""
from nlpia.constants import logging, DATA_PATH
import re
import os
import copy

from pugnlp.regexes import *  # noqa

logger = logging.getLogger(__name__)

RE_ACRONYM2 = r'((\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16})[ ]\((\2\3)\)'
RE_ACRONYM3 = r'((\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16})[ ]\((\6\7\8)\)'
CRE_ACRONYM = re.compile(RE_ACRONYM2 + '|' + RE_ACRONYM3, re.IGNORECASE)

RE_URL_SIMPLE = r'(((http|ftp|https)://)?([^/:(\["\'`)\]\s]+' \
    r'[.])(com|org|edu|gov|net|mil|uk|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|io|me)([^"\'`)\]\s]*))'
CRE_URL_SIMPLE = re.compile(RE_URL_SIMPLE)

"""
>>> CRE_SLUG_DELIMITTER.sub('-', 'thisSlug-should|beHypenatedInLots_OfPlaces')
'this-Slug-should-be-Hypenated-In-Lots-Of-Places'
"""
CRE_SLUG_DELIMITTER = re.compile(r'[^a-zA-Z]+|(?<=[a-z])(?=[A-Z])')

CRE_FILENAME_EXT = re.compile(r'([.][^a-zA-Z0-9]{1,8})$')
"""
>>> CRE_FILENAME_EXT.match('long.asciidoc.ext.ps4.123').group()
''
>>> CRE_FILENAME_EXT.sub('', 'this/path/has/a/file.html')
'this/path/has/a/file'
"""

# ? \(\): ()
# \': '"'"'
# \s: [:space:]
# RE_URL_BASH_ESCAPE = '((http|ftp|https)://)?[^/:\(\[\"'"'"'\`\)\] \t\n]+[.](com|org|edu|gov|net|mil|uk|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|io|me)[^\"'"'"'\`\)\] \t\n]*'  # noqa

def to_tsv():
    """ Save all regular expressions to a tsv file so they can be more easily copy/pasted in Sublime """
    with open(os.path.join(DATA_PATH, 'regexes.tsv'), mode='wt') as fout:
        vars = copy.copy(tuple(globals().items()))
        for k, v in vars:
            if k.lower().startswith('cre_'):
                fout.write(k[4:] + '\t' + v.pattern + '\n')
            elif k.lower().startswith('re_'):
                fout.write(k[3:] + '\t' + v.pattern + '\n')
<commit_msg>fix regexes and test<commit_after># -*- coding: utf-8 -*-
""" Compiled regular expressions for extracting dates, times, acronyms, etc

>>> CRE_ACRONYM.findall('National science Foundation (NSF)')
[('', '', '', '', 'National science Foundation', 'N', 's', 'F', 'NSF')]
>>> re.findall(RE_URL_SIMPLE, '* Sublime Text 3 (https://www.sublimetext.com/3) is great!')[0][0]
'https://www.sublimetext.com/3'
>>> re.findall(RE_URL_SIMPLE, 'Google github totalgood [github.com/totalgood]!')[0][0]
'github.com/totalgood'
"""
from nlpia.constants import logging, DATA_PATH
import re
import os
import copy

from pugnlp.regexes import *  # noqa

logger = logging.getLogger(__name__)

RE_ACRONYM2 = r'((\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16})[ ]\((\2\3)\)'
RE_ACRONYM3 = r'((\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16}[ ](\w)[\w0-9]{2,16})[ ]\((\6\7\8)\)'
CRE_ACRONYM = re.compile(RE_ACRONYM2 + '|' + RE_ACRONYM3, re.IGNORECASE)

RE_URL_SIMPLE = r'(((http|ftp|https)://)?([^/:(\["\'`)\]\s]+' \
    r'[.])(com|org|edu|gov|net|mil|uk|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|io|me)([^"\'`)\]\s]*))'
CRE_URL_SIMPLE = re.compile(RE_URL_SIMPLE)

"""
>>> CRE_SLUG_DELIMITTER.sub('-', 'thisSlug-should|beHypenatedInLots_OfPlaces')
'this-Slug-should-be-Hypenated-In-Lots-Of-Places'
"""
CRE_SLUG_DELIMITTER = re.compile(r'[^a-zA-Z]+|(?<=[a-z])(?=[A-Z])')

CRE_FILENAME_EXT = re.compile(r'(?<=[.a-zA-Z0-9_])([.][a-zA-Z0-9]{1,8}){1,5}$')
"""
>>> CRE_FILENAME_EXT.search('.bashrc.asciidoc.ext.ps4.123').group()
''
>>> CRE_FILENAME_EXT.sub('', 'this/path/has/a/file.html')
'this/path/has/a/file'
>>> CRE_FILENAME_EXT.search('.bashrc..asciidoc.ext.ps4.123').group()
'.asciidoc.ext.ps4.123'
>>> CRE_FILENAME_EXT.search('.bashrc..asciidoc..ext.ps4.123').group()
'.ext.ps4.123'
"""

# ? \(\): ()
# \': '"'"'
# \s: [:space:]
# RE_URL_BASH_ESCAPE = '((http|ftp|https)://)?[^/:\(\[\"'"'"'\`\)\] \t\n]+[.](com|org|edu|gov|net|mil|uk|ca|de|jp|fr|au|us|ru|ch|it|nl|se|no|es|io|me)[^\"'"'"'\`\)\] \t\n]*'  # noqa

def to_tsv():
    """ Save all regular expressions to a tsv file so they can be more easily copy/pasted in Sublime """
    with open(os.path.join(DATA_PATH, 'regexes.tsv'), mode='wt') as fout:
        vars = copy.copy(tuple(globals().items()))
        for k, v in vars:
            if k.lower().startswith('cre_'):
                fout.write(k[4:] + '\t' + v.pattern + '\n')
            elif k.lower().startswith('re_'):
                fout.write(k[3:] + '\t' + v.pattern + '\n')
<|endoftext|>


<commit_before>"""LogicAdapter for notes.

Syntax:
    take note <name>
    <note text>
    end note
"""
from chatterbot.logic import LogicAdapter
from chatterbot.conversation import Statement
from chatterbot import utils
from note_store import NoteStore

def remove_start(original,remove):
    if original.startswith(remove):
        return original[len(remove):].strip()
    else:
        return original

class NotesAdapter(LogicAdapter):
    START_NOTE='take note'
    END_NOTE='end note'

    def __init__(self,**kwargs):
        super(NotesAdapter, self).__init__(**kwargs)
        self.taking_note=False
        notes_store=kwargs.get('notes_store','note_store.DictNoteStore')
        utils.validate_adapter_class(notes_store, NoteStore)
        self.store=utils.initialize_class(notes_store, **kwargs)

    def can_process(self, statement):
        return self.taking_note or statement.text.startswith(self.START_NOTE)
    def process(self, statement):
        response=self.process_statement(statement)
        if isinstance(response,Statement):
            response.confidence=1
            return response
        else:
            return Statement(response)

    def process_statement(self,statement):
        if not self.taking_note:
            return self.start_note(statement)
        if statement.text.startswith(self.END_NOTE):
            return self.store_note(statement)
        self.current_note['content'].append(statement.text)
        return Statement('line added')

    def start_note(self, statement):
        self.taking_note=True
        note_name=remove_start(statement.text,self.START_NOTE)
        if not note_name:
            note_name=self.store.unique_name()
        found=self.store.find(note_name)
        if found:
            self.current_note=found
            return Statement(found["content"][-1])
        else:
            self.current_note={'name':note_name,'content':[]}
            return Statement("New note: {}".format(note_name))
    def store_note(self,statement):
        result=self.store.store(self.current_note)
        if not result:
            self.current_note=None
            self.taking_note=False
            return Statement("Note stored")
        else:
            return Statement("Storing failed with {}. Try again.".format(result))
<commit_msg>Added chatbot<commit_after>"""LogicAdapter for notes.

Syntax:
    take note <name>
    <note text>
    end note
"""
from chatterbot.logic import LogicAdapter
from chatterbot.conversation import Statement
from chatterbot import utils
from note_store import NoteStore

def remove_start(original,remove):
    if original.startswith(remove):
        return original[len(remove):].strip()
    else:
        return original

class NotesAdapter(LogicAdapter):
    START_NOTE='take note'
    END_NOTE='end note'

    def __init__(self, chatbot, **kwargs):
        super(NotesAdapter, self).__init__(**kwargs)
        self.taking_note=False
        notes_store=kwargs.get('notes_store','note_store.DictNoteStore')
        utils.validate_adapter_class(notes_store, NoteStore)
        self.store=utils.initialize_class(notes_store, **kwargs)

    def can_process(self, statement):
        return self.taking_note or statement.text.startswith(self.START_NOTE)
    def process(self, statement):
        response=self.process_statement(statement)
        if isinstance(response,Statement):
            response.confidence=1
            return response
        else:
            return Statement(response)

    def process_statement(self,statement):
        if not self.taking_note:
            return self.start_note(statement)
        if statement.text.startswith(self.END_NOTE):
            return self.store_note(statement)
        self.current_note['content'].append(statement.text)
        return Statement('line added')

    def start_note(self, statement):
        self.taking_note=True
        note_name=remove_start(statement.text,self.START_NOTE)
        if not note_name:
            note_name=self.store.unique_name()
        found=self.store.find(note_name)
        if found:
            self.current_note=found
            return Statement(found["content"][-1])
        else:
            self.current_note={'name':note_name,'content':[]}
            return Statement("New note: {}".format(note_name))
    def store_note(self,statement):
        result=self.store.store(self.current_note)
        if not result:
            self.current_note=None
            self.taking_note=False
            return Statement("Note stored")
        else:
            return Statement("Storing failed with {}. Try again.".format(result))
<|endoftext|>


<commit_before># encoding: utf-8
#
# Nome..: Neviim Jads
# Versão: 0.1
#
# Depos de estar estudando os fundamentos de redeneural a mais de dois anos, creio que esta na hora
# de escrever minha primeira implementação do zero de uma rede Perceptron, vamos ver o que sai...
#
# Descritivo, do como se dara a evolução da escrida deste codigo, teoria e pratica aplicada.
#
# Uma rede perseptron é a base mais simples de se começãr a entender a mecanica de funcionamento de
# uma rede neural artificial, como este codigo é a base para ver o funcionamento na pratica de uma
# base teorica que no inicio sempre é muito complicado se entender, conforme for evoluindo no descritivo
# teorico do como fui entendendo cada atapa do processo vou colocar as referencias teoricas que me foram
# esclarecendo alguns pontos de duvidas do entendimento, ficando assim uma fonde de referencia para pesquisar
# caso algo do que esto fazendo venha não ser compreendido ou não faça sentido do porque esta sendo utilizado.
#
# https://github.com/neviim/Perceptron.git
#
# Rede Neural Artificial
#
#   referencias:
#       http://www.teses.usp.br/teses/disponiveis/18/18153/tde-29042009-102601/publico/Fabriciu.pdf

'''
    Matemática da coisa:

                pa = somatoria(i=1 até ne) (wi * xi) - theta

        (pa)    -> potencial de ativação {diferença do valor entre o combinador linear somatória, e limiar de ativação.
        (ne)    -> numero de entradas.
        (xi)    -> numero das entradas da rede.
        (wi)    -> peso sináptico associado a i-ésima entrada.
        (theta) -> limiar de ativação com representação de theta sendo o valor de (-1)

        - Com o resultado de (pa), passa por parametro para a função de ativação (f) obtendo assim o resultado de (y)

                y = f(pa)

        (f)     -> proposito desta função é limitar a saída do neuronio dentro de um internalo de valores aceitaveis.
        (y)     -> resultado final gerado do neurônio mediante ao conjunto de sinais de entrada determinado.

        - Estas são as definições internas do precessamento interno gerado por um Perceptron.

    Definindo estrutura funcional interna:

        - De acordo com p proble a ser mapeado pode-se definir o numero de sinais de entrada a uma rede perceptron.

        - Sinais de entrada sera representado por (x1, x2, ...), inicialmente composta somente por um neurônio e
          uma saida resultante em (y).

        - Cada entradas (x1, x2, ...) representa o comportamento do processo a ser mapeado, individualmente cada
          entrada sera ponderada polos pesos sinápticos representados por (w1, w2, ...) com o proposito de obter
          um valor de relevancia a importancia de cada um representa.

    Funções de ativação:

        - referencias:
            http://www.telecom.uff.br/~jmarcos/disciplinas/RedesNeurais/Aula02.pdf
            http://www.carolina.unir.br/downloads/1721_aula9_perceptron.pdf
            http://www.maxwell.vrac.puc-rio.br/3509/3509_3.PDF

        - Ha varias funções de ativação que pode ser utilizadas, mais para cada caso no geral precisa ser efetuado
          testes e verificação por resultado obtido, e verificar qual o melhor se adequara aos propósitos do
          resultado que se esta buscando alcançar.

        - As funções que mais tenho encontradas nas literaturas que vejo, são as:

            degrau
            degrau bipolar

            praticamento funções bem simples de ser aplicada.

                degrau, tambem conhecida como função de Theshold:

                    f(pa) = 1, se pa >= 0
                    f(pa) = 0, se pa <  0

                degrau pipolar, tambem conhecida por função sinal:

                    f(pa) =  1, se pa >= 0
                    f(pa) = -1, se pa <  0

        - Já as entradas (xi) podem assumir qualquer valor numéricos

        - Normalmente se itiliza um perceptron para classificação de padrões, isso porque a saida só podera assumir
          dois valores, tipo, 0 ou 1, verdadeito ou falso, exemplo sobre o proposito pratico para o qual no momento
          esto fazendo isso, quero obter uma classificação sobre uma base de dados dada como aprendisado para a rede
          neural um resultado de que:

                Em um periodo predeterminado a definir (uma hora) uma lampada fica por mais tempo ligada ou desligada?
                EM que horas do dia normalmente a temperatura utrapassa determinado graus acema da valor X estipulado?

                Exemplos basicos para se ter uma referencia aplicada do contesto abordado aqui, podendo ser
                representado por momento A e momento B.

                    Fazendo um paralelo:

                        A função degrau ficaria:

                                quando a saida for  0 estaria no momento A
                                quanto a saida for  1 estaria no momento B

                        A função degrau bipolar:

                                quanto a saida for -1 estaria no momento A
                                quando a saida for  1 estaria no momento B

                        estas duas funçoes geram resultantes que podem ser atribuidos as estas caracteristicas
                        representativas destas necessidades esperadas.

                    A formula para a função grau pipolar (sinal) é considerado somente duas entradas, sendo elas.

                        y =  1, se w1 * x1 + w2 * x2 - theta >= 0
                        y = -1, se w1 * x1 + w2 * x2 - theta <  0

                        neste caso o percepton se comporta como um classificador, por esta definição obteremos quando
                        a saida for:

                            -1 que esta no momento A
                             1 que esta no momento B

    Aprendizado, para este caso utilizaremos a regra de HEBB.

        - referencias encontradas em:
            https://pt.wikipedia.org/wiki/Teoria_hebbiana
            http://www2.ica.ele.puc-rio.br/Downloads/30/ICA-Aula-2b-Perceptron.pdf
            https://pt.wikipedia.org/wiki/Sinapse

        - Se a saida gerada for igual a desejada os pesos sinápticos e limiares receberão o incremento, sendo
          proporcionalmete aos valores de entrada, contrario a isso sera decrementados.
          Este processo sera repetido em loop de forma sequencial para as amostras até se obter a saida do perceptron
          iqual a saida desejada de cada amostra.

          O limiar é uma variavem que é sjustada para auxiliar o treinamento do perceptron, ela pode ser implementada
          dentro do vetor de pesos sínapticos.

                        w = (formula para gerar o vetor com o limiar e os pesos sinápticos)

                             Verificar como é montada esta formula!!!!

'''

__autor__ = "Neviim Jads"

class Perceptron:

    def __init__(self):
        pass

    def treinar(self):
        pass

    def testar(self):
        pass

    def degrau(self):
        pass

    def sinal(self):
        pass

if __name__ == '__main__':
   pass<commit_msg>Metodo Perceptron e teste esta ecrito, mais falta aperfeiçoar a aprendizagem.<commit_after># encoding: utf-8
#
# Nome..: Neviim Jads
# Versão: 0.1
#
# Depos de estar estudando os fundamentos de redeneural a mais de dois anos, creio que esta na hora
# de escrever minha primeira implementação do zero de uma rede Perceptron, vamos ver o que sai...
#
# Descritivo, do como se dara a evolução da escrida deste codigo, teoria e pratica aplicada.
#
# Uma rede perseptron é a base mais simples de se começãr a entender a mecanica de funcionamento de
# uma rede neural artificial, como este codigo é a base para ver o funcionamento na pratica de uma
# base teorica que no inicio sempre é muito complicado se entender, conforme for evoluindo no descritivo
# teorico do como fui entendendo cada atapa do processo vou colocar as referencias teoricas que me foram
# esclarecendo alguns pontos de duvidas do entendimento, ficando assim uma fonde de referencia para pesquisar
# caso algo do que esto fazendo venha não ser compreendido ou não faça sentido do porque esta sendo utilizado.
#
# https://github.com/neviim/Perceptron.git
#
# Rede Neural Artificial
#
#   referencias:
#       http://www.teses.usp.br/teses/disponiveis/18/18153/tde-29042009-102601/publico/Fabriciu.pdf

'''
    Matemática da coisa:

        pa = somatoria(i=1 até ne) (wi * xi) - theta

        (pa)    -> potencial de ativação {diferença do valor entre o combinador linear somatória, e limiar de ativação.
        (ne)    -> numero de entradas.
        (xi)    -> numero das entradas da rede.
        (wi)    -> peso sináptico associado a i-ésima entrada.
        (theta) -> limiar de ativação com representação de theta sendo o valor de (-1)

        - Com o resultado de (pa), passa por parametro para a função de ativação (f) obtendo assim o resultado de (y)

                y = f(pa)

        (f)     -> proposito desta função é limitar a saída do neuronio dentro de um internalo de valores aceitaveis.
        (y)     -> resultado final gerado do neurônio mediante ao conjunto de sinais de entrada determinado.

        - Estas são as definições internas do precessamento interno gerado por um Perceptron.

    Definindo estrutura funcional interna:

        - De acordo com p proble a ser mapeado pode-se definir o numero de sinais de entrada a uma rede perceptron.

        - Sinais de entrada sera representado por (x1, x2, ...), inicialmente composta somente por um neurônio e
          uma saida resultante em (y).

        - Cada entradas (x1, x2, ...) representa o comportamento do processo a ser mapeado, individualmente cada
          entrada sera ponderada polos pesos sinápticos representados por (w1, w2, ...) com o proposito de obter
          um valor de relevancia a importancia de cada um representa.

    Funções de ativação:

        - referencias:
            http://www.telecom.uff.br/~jmarcos/disciplinas/RedesNeurais/Aula02.pdf
            http://www.carolina.unir.br/downloads/1721_aula9_perceptron.pdf
            http://www.maxwell.vrac.puc-rio.br/3509/3509_3.PDF

        - Ha varias funções de ativação que pode ser utilizadas, mais para cada caso no geral precisa ser efetuado
          testes e verificação por resultado obtido, e verificar qual o melhor se adequara aos propósitos do
          resultado que se esta buscando alcançar.

        - As funções que mais tenho encontradas nas literaturas que vejo, são as:

            degrau
            degrau bipolar

            praticamento funções bem simples de ser aplicada.

                degrau, tambem conhecida como função de Theshold:

                    f(pa) = 1, se pa >= 0
                    f(pa) = 0, se pa <  0

                degrau pipolar, tambem conhecida por função sinal:

                    f(pa) =  1, se pa >= 0
                    f(pa) = -1, se pa <  0

        - Já as entradas (xi) podem assumir qualquer valor numéricos

        - Normalmente se itiliza um perceptron para classificação de padrões, isso porque a saida só podera assumir
          dois valores, tipo, 0 ou 1, verdadeito ou falso, exemplo sobre o proposito pratico para o qual no momento
          esto fazendo isso, quero obter uma classificação sobre uma base de dados dada como aprendisado para a rede
          neural um resultado de que:

                Em um periodo predeterminado a definir (uma hora) uma lampada fica por mais tempo ligada ou desligada?
                Em que horas do dia normalmente a temperatura utrapassa determinado graus acema da valor X estipulado?

                Exemplos basicos para se ter uma referencia aplicada do contesto abordado aqui, podendo ser
                representado por momento A e momento B.

                    Fazendo um paralelo:

                        A função degrau ficaria:

                                quando a saida for  0 estaria no momento A
                                quanto a saida for  1 estaria no momento B

                        A função degrau bipolar:

                                quanto a saida for -1 estaria no momento A
                                quando a saida for  1 estaria no momento B

                        estas duas funçoes geram resultantes que podem ser atribuidos as estas caracteristicas
                        representativas destas necessidades esperadas.

                    A formula para a função grau pipolar (sinal) é considerado somente duas entradas, sendo elas.

                        y =  1, se w1 * x1 + w2 * x2 - theta >= 0
                        y = -1, se w1 * x1 + w2 * x2 - theta <  0

                        neste caso o percepton se comporta como um classificador, por esta definição obteremos quando
                        a saida for:

                            -1 que esta no momento A
                             1 que esta no momento B

    Aprendizado, para este caso utilizaremos a regra de HEBB.

        - referencias encontradas em:
            https://pt.wikipedia.org/wiki/Teoria_hebbiana
            http://www2.ica.ele.puc-rio.br/Downloads/30/ICA-Aula-2b-Perceptron.pdf
            https://pt.wikipedia.org/wiki/Sinapse

        - Se a saida gerada for igual a desejada os pesos sinápticos e limiares receberão o incremento, sendo
          proporcionalmete aos valores de entrada, contrario a isso sera decrementados.
          Este processo sera repetido em loop de forma sequencial para as entradas até se obter a saida do perceptron
          iqual a saida desejada de cada amostra.

          O limiar é uma variavem que é sjustada para auxiliar o treinamento do perceptron, ela pode ser implementada
          dentro do vetor de pesos sínapticos.

                        w = (formula para gerar o vetor com o limiar e os pesos sinápticos)

                             Verificar como é montada esta formula!!!!

                             ... terminar de escrever esta etapa.

'''

# variaveis de identidade
__autor__ = "Neviim Jads"
__versao__ = 0.1

# defini os import
import random
import copy

''' Classe RedeNeural - perceptron
    ------------------------------

            * Variaveis recebida por parametro:

                saidas_esperadas       - Matrix
                entradas               - Lista
                limiar = -1            - Inteiro
                epocas = 1000          - Inteiro
                aprendizado = 0.1      - Flout

----------------- '''
class RedeNeural:

    def __init__(self, entradas, saidas_esperadas, aprendizado=0.1, limiar=-1, epocas=10000):

        # variaveis de uso publico desta class
        self.pesos = []                             # vetor dos pesos
        self.epocas = epocas                        # número de épocas
        self.limiar = limiar                        # limiar
        self.entradas = entradas                    # todas as entradas
        self.aprendizado = aprendizado              # taxa de aprendizado (entre 0 e 1)
        self.num_entradas = len(entradas)           # numero de elementos de entradas
        self.num_elemento = len(entradas[0])        # numero de elementos de cada entrada
        self.saidas_esperadas = saidas_esperadas    # saídas respectivas de cada entrada

    # metodo para teinar a rede
    def treinar_a_rede(self):

        # adiciona -1 para cada entrada
        for amostra in self.entradas:
            amostra.insert(0, -1)

        # inicia o vetor de pesos com valores aleatórios pequenos *
        for i in range(self.num_elemento):
            self.pesos.append(random.random())

        # insere o limiar no vetor de pesos
        self.pesos.insert(0, self.limiar)

        # inicia o contador de épocas
        num_epocas = 0

        # loop, até se atingir o fim do trenamento
        while True:

            # inicialmente erro inexiste
            erro = False

            # para todas as entradas de treinamento
            for i in range(self.num_entradas):

                pa = 0 # potencial de ativação

                # pa = somatoria(i=1 até ne) (wi * xi) - theta
                for item in range(self.num_elemento + 1):
                    pa += self.pesos[item] * self.entradas[i][item]

                # obtém a saída da rede utilizando a função de ativação
                y = self.degrau_bipolar(pa)

                # verifica se a saída da rede é diferente da saída desejada
                if y != self.saidas_esperadas[i]:

                    # calcula o erro: subtração entre a saída desejada e a saída da rede
                    erro_aux = self.saidas_esperadas[i] - y

                    # faz o ajuste dos pesos para cada elemento da amostra
                    for j in range(self.num_elemento + 1):
                        self.pesos[j] = (self.pesos[j] + (self.aprendizado * erro_aux * self.entradas[i][j]))

                    # True = ainda existe erro
                    erro = True

            # incrementa o número de épocas
            num_epocas += 1

            # critério de parada é pelo número de épocas ou se não existir erro
            if num_epocas > self.epocas or not erro:
                break # sai do while

    # metodo a formula para a função degrau
    def degrau(self, pa):
        return 1 if pa >= 0 else 0

    # metodo a formula para a função degrau pipolar (sinal)
    def degrau_bipolar(self, pa):
        return 1 if pa >= 0 else -1

    # metodo para testar a rede
    def teste_da_rede(self, entradas, estado1, estado2):

        # insere o (-1), peso inicial de ajuste.
        entradas.insert(0, -1)

        # usa o vetor de pesos ajustado durante o treinamento da rede
        pa = 0
        for item in range(self.num_elemento + 1):
            pa += self.pesos[item] * entradas[item]

        # calcula a saída da rede
        y = self.degrau_bipolar(pa)
        print pa

        # verifica a qual estado pertence a resposta
        if y == -1:
            print('A lampada sera %s' % estado1)
        else:
            print('A lampada sera %s' % estado2)

# inicio de processamento
if __name__ == '__main__':

    # saida esperada para cada item da entrada
    saidas_esperadas = [1, -1, -1, 1]

    # referencia de lista de entradas para a rede perceptron que serão
    # utilizadas nos testes de validação da aprendizagem.

    # entrada que sera aprendica.
    entradas =            [[0.2315, 1,  0.0],    # hora: 23:15:10, dia: 1, status: acender
                           [0.0610, 2, -0.1],    # hora: 06:10:20, dia: 2, status: apagar
                           [0.1220, 3, -0.1],    # hora: 12:20:30, dia: 3, status: apagar
                           [0.1830, 4,  0.0]]    # hora: 18:30:40, dia: 4, status: acender

    # entradas a serem testadas na rede pos aprendizato, simula leitura do estado atual da lampada
    entradas_diferentes = [[0.2315, 1, -0.1],    #
                           [0.0610, 2,  0.0],    #
                           [0.1220, 3,  0.0],    #
                           [0.1830, 4, -0.1]]    #

    # copia identica as entradas que serão aprendidas pela rede.
    entradas_identicas = copy.deepcopy(entradas)

    # cria uma rede perceptron
    rede_perceptron = RedeNeural(entradas=entradas, saidas_esperadas=saidas_esperadas, aprendizado=0.1, epocas=20000)

    # realiza o treinamento da redeNeural
    rede_perceptron.treinar_a_rede()

    # === Testes...

    # testa de validação na rede pos ser treinada com os mesmos itens de entrada do trenamento
    print "#"
    print "Testa mesmas estradas do trenamento."
    for testa_item in entradas_identicas:
        print(testa_item)
        rede_perceptron.teste_da_rede(testa_item, 'apagada.', 'acesa.')
        print

    print ""
    print "#"
    print "Testa outras entradas diferente do trenamento."
    for testa_item in entradas_diferentes:
        print(testa_item)
        rede_perceptron.teste_da_rede(testa_item, 'apagada.', 'acesa.')
        print<|endoftext|>


<commit_before># Main Oracle file
from oracle_communication import OracleCommunication
from db_connection import OracleDb, TaskQueue, UsedAddress
from oracle_protocol import RESPONSE, SUBJECT
from condition_evaluator.evaluator import Evaluator

from bitcoind_client.bitcoinclient import BitcoinClient

import time
import logging
import json

class Oracle:
  def __init__(self):
    self.communication = OracleCommunication()
    self.db = OracleDb()
    self.btc = BitcoinClient()
    self.evaluator = Evaluator()

    self.operations = {
      'TransactionRequest': self.add_transaction,
    }

  def condition_valid(self, condition):
    return self.evaluator.valid(condition)

  def transaction_valid(self, transaction):
    return self.btc.is_valid_transaction()

  def add_transaction(self, message):
    body = json.loads(message.message)

    condition = body['condition']
    reply_address = body['origin_address']
    # Future reference - add parsing condition. Now assumed true
    if not self.condition_valid(condition):
      self.communication.response_to_address(
          origin_address,
          SUBJECT.INVALID_CONDITION,
          RESPONSE.INVALID_CONDITION)
      return

    transaction = body['raw_transaction']
    if self.transaction_valid(transaction):
      self.communication.response_to_address(
          origin_address,
          SUBJECT.INVALID_TRANSACTION,
          RESPONSE.INVALID_TRANSACTION)
      return

    if self.btc.transaction_already_signed(transaction):
      return

    inputs_outputs = self.btc.get_inputs_outputs(transaction)
    multisig_address = self.btc.get_multisig_sender_address(transaction)

    used_address_db = UsedAddress(self.db)
    used_address = used_address_db.get_address(multisig_address)
    if used_address:
      #DANGER! SHOULD BE TESTED AND PREPARED OMG!
      #checking equality should be done key by key, json object does not preserve order, json list does
      if used_address["json_in_out"] != inputs_outputs:
        self.communication.response_to_address(
            origin_address,
            SUBJECT.ADDRESS_DUPLICATE,
            RESPONSE.ADDRESS_DUPLICATE)
        return
    else:
      used_address_db.save({
          "multisig_address": multisig_address,
          "json_in_out": inputs_outputs,
      })

    check_time = int(body['check_time'])
    task_queue = TaskQueue(self.db).save({
        "origin_address": body['origin_address'],
        "json_data": message.message,
        "done": 0,
        "next_check": check_time
    })
    self.communication.response_to_address(
        origin_address,
        SUBJECT.CONFIRMED,
        RESPONSE.CONFIRMED)

  def handle_request(self, request):
    operation, message = request
    fun = self.operations[operation]
    fun(message)

    # Save object to database for future reference
    db_class = self.db.operations[operation]
    if db_class:
      db_class(self.db).save(message)

  def sign_transaction(self, transaction):
    signed_transaction = self.btc.sign_transaction()
    return signed_transaction

  def check_condition(self, condition):
    return self.evaluator.evaluate(condition)

  def handle_task(self, task):
    body = json.loads(task["json_data"])
    condition = body["condition"]
    transaction = body["raw_transaction"]
    if not self.check_condition(condition):
      self.db.TaskQueue().done(task)
      return
    signed_transaction = self.sign_transaction(transaction)
    body["raw_transaction"] = signed_transaction

    self.communication.broadcast_signed_transaction(json.dumps(body))
    self.db.TaskQueue().done(task)

  def run(self):
    while True:
      # Proceed all requests
      requests = self.communication.get_new_requests()
      logging.debug("{0} new requests".format(len(requests)))
      for request in requests:
        self.handle_request(request)
        self.communication.mark_request_done(request)

      task = self.db.get_oldest_task()
      self.handle_task(task)

      time.sleep(1)<commit_msg>task_queue in oracle<commit_after># Main Oracle file
from oracle_communication import OracleCommunication
from db_connection import OracleDb, TaskQueue, UsedAddress
from oracle_protocol import RESPONSE, SUBJECT
from condition_evaluator.evaluator import Evaluator

from bitcoind_client.bitcoinclient import BitcoinClient

import time
import logging
import json

class Oracle:
  def __init__(self):
    self.communication = OracleCommunication()
    self.db = OracleDb()
    self.btc = BitcoinClient()
    self.evaluator = Evaluator()

    self.task_queue = TaskQueue(self.db)

    self.operations = {
      'TransactionRequest': self.add_transaction,
    }

  def condition_valid(self, condition):
    return self.evaluator.valid(condition)

  def transaction_valid(self, transaction):
    return self.btc.is_valid_transaction()

  def add_transaction(self, message):
    body = json.loads(message.message)

    condition = body['condition']
    reply_address = body['origin_address']
    # Future reference - add parsing condition. Now assumed true
    if not self.condition_valid(condition):
      self.communication.response_to_address(
          origin_address,
          SUBJECT.INVALID_CONDITION,
          RESPONSE.INVALID_CONDITION)
      return

    transaction = body['raw_transaction']
    if self.transaction_valid(transaction):
      self.communication.response_to_address(
          origin_address,
          SUBJECT.INVALID_TRANSACTION,
          RESPONSE.INVALID_TRANSACTION)
      return

    if self.btc.transaction_already_signed(transaction):
      return

    inputs_outputs = self.btc.get_inputs_outputs(transaction)
    multisig_address = self.btc.get_multisig_sender_address(transaction)

    used_address_db = UsedAddress(self.db)
    used_address = used_address_db.get_address(multisig_address)
    if used_address:
      #DANGER! SHOULD BE TESTED AND PREPARED OMG!
      #checking equality should be done key by key, json object does not preserve order, json list does
      if used_address["json_in_out"] != inputs_outputs:
        self.communication.response_to_address(
            origin_address,
            SUBJECT.ADDRESS_DUPLICATE,
            RESPONSE.ADDRESS_DUPLICATE)
        return
    else:
      used_address_db.save({
          "multisig_address": multisig_address,
          "json_in_out": inputs_outputs,
      })

    check_time = int(body['check_time'])
    task_queue = TaskQueue(self.db).save({
        "origin_address": body['origin_address'],
        "json_data": message.message,
        "done": 0,
        "next_check": check_time
    })
    self.communication.response_to_address(
        origin_address,
        SUBJECT.CONFIRMED,
        RESPONSE.CONFIRMED)

  def handle_request(self, request):
    operation, message = request
    fun = self.operations[operation]
    fun(message)

    # Save object to database for future reference
    db_class = self.db.operations[operation]
    if db_class:
      db_class(self.db).save(message)

  def sign_transaction(self, transaction):
    signed_transaction = self.btc.sign_transaction()
    return signed_transaction

  def check_condition(self, condition):
    return self.evaluator.evaluate(condition)

  def handle_task(self, task):
    body = json.loads(task["json_data"])
    condition = body["condition"]
    transaction = body["raw_transaction"]
    if not self.check_condition(condition):
      self.task_queue.done(task)
      return
    signed_transaction = self.sign_transaction(transaction)
    body["raw_transaction"] = signed_transaction

    self.communication.broadcast_signed_transaction(json.dumps(body))
    self.task_queue.done(task)

  def run(self):
    while True:
      # Proceed all requests
      requests = self.communication.get_new_requests()
      logging.debug("{0} new requests".format(len(requests)))
      for request in requests:
        self.handle_request(request)
        self.communication.mark_request_done(request)

      task = self.task_queue.get_oldest_task()
      self.handle_task(task)

      time.sleep(1)<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Render 3D and 4D Polytopes using Python and POV-Ray
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Usage:
  1. Make sure the free raytracer POV-Ray is installed on your
     computer and can be found in system environment variables.

  2. Run python main.py and wait for amazing things to happen!
"""
import subprocess
import models

# use higher supersampling level (e.g. 5) and smaller antialiasing level
# (e.g. 0.001) to get betweer images
POVRAY_EXE = "povray"
IMAGE_SIZE = 600
IMAGE_QUALITY_LEVEL = 11  # between 0-11
SUPER_SAMPLING_LEVEL = 5  # between 1-9
ANTIALIASING_LEVEL = 0.001

POV_COMMAND = "cd povray && " + \
              POVRAY_EXE + \
              " +I{}" + \
              " +W{}".format(IMAGE_SIZE) + \
              " +H{}".format(IMAGE_SIZE) + \
              " +Q{}".format(IMAGE_QUALITY_LEVEL) + \
              " +A{}".format(ANTIALIASING_LEVEL) + \
              " +R{}".format(SUPER_SAMPLING_LEVEL) + \
              " +O{}"

def _render_model(P, input_file, output_file):
    P.build_geometry()
    P.export_pov()
    print("rendering {} with {} vertices, {} edges, {} faces".format(output_file,
                                                                     P.num_vertices,
                                                                     P.num_edges,
                                                                     P.num_faces))
    command = POV_COMMAND.format(input_file, output_file)
    process = subprocess.Popen(command,
                               shell=True,
                               stderr=subprocess.PIPE,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE)

    out, err = process.communicate()
    if process.returncode:
        print(type(err), err)
        raise IOError("POVRay rendering failed with the following error: " + err.decode("ascii"))

def render_polyhedra(coxeter_diagram,
                     trunc_type,
                     render_file="polyhedra.pov",
                     description=None,
                     snub=False):
    if snub:
        P = models.Snub(coxeter_diagram, trunc_type)
    else:
        P = models.Polyhedra(coxeter_diagram, trunc_type)

    if not description:
        description = render_file[:-4]

    _render_model(P, render_file, description)

def render_polychora(coxeter_diagram,
                     trunc_type,
                     render_file,
                     description=None):
    if not description:
        description = render_file[:-4]

    P = models.Polychora(coxeter_diagram, trunc_type)
    _render_model(P, render_file, description)

if __name__ == "__main__":
    # platonic solids
    """
    render_polyhedra((3, 2, 3), (1, 0, 0), description="tetrahedron")
    render_polyhedra((4, 2, 3), (1, 0, 0), description="cube")
    render_polyhedra((3, 2, 4), (1, 0, 0), description="octahedron")
    render_polyhedra((5, 2, 3), (1, 0, 0), description="dodecahedron")
    """
    render_polyhedra((3, 2, 5), (1, 0, 0), description="icosahedron")

    # archimedean solids
    """
    render_polyhedra((3, 2, 3), (1, 1, 0), description="truncated-tetrahedron")
    render_polyhedra((4, 2, 3), (1, 1, 0), description="truncated-cube")
    render_polyhedra((3, 2, 4), (1, 1, 0), description="truncated-octahedron")
    render_polyhedra((5, 2, 3), (1, 1, 0), description="truncated-dodecahedron")
    render_polyhedra((3, 2, 5), (1, 1, 0), description="truncated-icosahedron")
    render_polyhedra((4, 2, 3), (0, 1, 0), description="cuboctahedron")
    render_polyhedra((5, 2, 3), (0, 1, 0), description="icosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 0, 1), description="rhombicuboctahedron")
    render_polyhedra((5, 2, 3), (1, 0, 1), description="rhombicosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 1, 1), description="truncated-cuboctahedron")
    """
    render_polyhedra((5, 2, 3), (1, 1, 1), description="truncated-icosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 1, 1), description="snub-cube", snub=True)
    render_polyhedra((5, 2, 3), (1, 1, 1), description="snub-dodecahedron", snub=True)

    # prism and antiprism
    render_polyhedra((7, 2, 2), (1, 0, 1), description="7-prism")
    render_polyhedra((8, 2, 2), (1, 1, 1), description="8-antiprism", snub=True)

    # regular polychora
    render_polychora((3, 2, 2, 3, 2, 3), (1, 0, 0, 0), "5-cell-1000.pov", "5-cell")
    """
    render_polychora((4, 2, 2, 3, 2, 3), (1, 0, 0, 0), "8-cell-1000.pov", "8-cell")
    render_polychora((3, 2, 2, 3, 2, 4), (1, 0, 0, 0), "16-cell-1000.pov", "16-cell")
    render_polychora((3, 2, 2, 4, 2, 3), (1, 0, 0, 0), "24-cell-1000.pov", "24-cell")
    render_polychora((5, 2, 2, 3, 2, 3), (1, 0, 0, 0), "120-cell-1000.pov", "120-cell")
    """
    render_polychora((3, 2, 2, 3, 2, 5), (1, 0, 0, 0), "600-cell-1000.pov", "600-cell")
    # some truncated polychora
    # for more examples see the .pov files in the povray directory
    """
    render_polychora((3, 2, 2, 3, 2, 3), (1, 1, 1, 0), "5-cell-1110.pov", "cantitruncated-5-cell")
    render_polychora((4, 2, 2, 3, 2, 3), (1, 1, 0, 0), "8-cell-1100.pov", "truncated-8-cell")
    render_polychora((3, 2, 2, 3, 2, 4), (1, 0, 0, 1), "16-cell-1001.pov", "runcinated-16-cell")
    render_polychora((3, 2, 2, 4, 2, 3), (1, 1, 1, 0), "24-cell-1110.pov", "cantitruncated-24-cell")
    """
    render_polychora((3, 2, 2, 3, 2, 5), (1, 1, 0, 0), "600-cell-1100.pov", "truncated-600-cell")

    # 4d prism and duoprism
    render_polychora((6, 2, 2, 2, 2, 8), (1, 0, 1.6, 0), "duoprism.pov", "6-8-duoprism")
    render_polychora((5, 2, 2, 3, 2, 2), (1, 1, 0, 1), "prism.pov", "5-3-prism")
<commit_msg>improve comments<commit_after># -*- coding: utf-8 -*-
"""
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Render 3D and 4D Polytopes using Python and POV-Ray
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Usage:
  1. Make sure the free raytracer POV-Ray is installed on your
     computer and can be found in system environment variables.

  2. Run python main.py and wait for amazing things to happen!
"""
import subprocess
import models

# use higher supersampling level and smaller
# antialiasing level to get better images
POVRAY_EXE = "povray"
IMAGE_SIZE = 600
IMAGE_QUALITY_LEVEL = 11  # between 0-11
SUPER_SAMPLING_LEVEL = 5  # between 1-9
ANTIALIASING_LEVEL = 0.001

POV_COMMAND = "cd povray && " + \
              POVRAY_EXE + \
              " +I{}" + \
              " +W{}".format(IMAGE_SIZE) + \
              " +H{}".format(IMAGE_SIZE) + \
              " +Q{}".format(IMAGE_QUALITY_LEVEL) + \
              " +A{}".format(ANTIALIASING_LEVEL) + \
              " +R{}".format(SUPER_SAMPLING_LEVEL) + \
              " +O{}"

def _render_model(P, input_file, output_file):
    """
    P: a polyhedra/polychora that has been initialized.

    input_file: the POV-Ray scene decription file to render.

    output_file: output image file.
    """
    P.build_geometry()
    P.export_pov()
    print("rendering {} with {} vertices, {} edges, {} faces".format(output_file,
                                                                     P.num_vertices,
                                                                     P.num_edges,
                                                                     P.num_faces))
    command = POV_COMMAND.format(input_file, output_file)
    process = subprocess.Popen(command,
                               shell=True,
                               stderr=subprocess.PIPE,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE)

    out, err = process.communicate()
    if process.returncode:
        print(type(err), err)
        raise IOError("POVRay rendering failed with the following error: " + err.decode("ascii"))

def render_polyhedra(coxeter_diagram,
                     trunc_type,
                     render_file="polyhedra.pov",
                     description=None,
                     snub=False):
    """
    The main entrance for rendering 3d polyhedra.
    """
    if snub:
        P = models.Snub(coxeter_diagram, trunc_type)
    else:
        P = models.Polyhedra(coxeter_diagram, trunc_type)

    if not description:
        description = render_file[:-4]

    _render_model(P, render_file, description)

def render_polychora(coxeter_diagram,
                     trunc_type,
                     render_file,
                     description=None):
    """
    The main entrance for rendering 4d polychora.
    """
    if not description:
        description = render_file[:-4]

    P = models.Polychora(coxeter_diagram, trunc_type)
    _render_model(P, render_file, description)

if __name__ == "__main__":
    # platonic solids
    """
    render_polyhedra((3, 2, 3), (1, 0, 0), description="tetrahedron")
    render_polyhedra((4, 2, 3), (1, 0, 0), description="cube")
    render_polyhedra((3, 2, 4), (1, 0, 0), description="octahedron")
    render_polyhedra((5, 2, 3), (1, 0, 0), description="dodecahedron")
    """
    render_polyhedra((3, 2, 5), (1, 0, 0), description="icosahedron")

    # archimedean solids
    """
    render_polyhedra((3, 2, 3), (1, 1, 0), description="truncated-tetrahedron")
    render_polyhedra((4, 2, 3), (1, 1, 0), description="truncated-cube")
    render_polyhedra((3, 2, 4), (1, 1, 0), description="truncated-octahedron")
    render_polyhedra((5, 2, 3), (1, 1, 0), description="truncated-dodecahedron")
    render_polyhedra((3, 2, 5), (1, 1, 0), description="truncated-icosahedron")
    render_polyhedra((4, 2, 3), (0, 1, 0), description="cuboctahedron")
    render_polyhedra((5, 2, 3), (0, 1, 0), description="icosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 0, 1), description="rhombicuboctahedron")
    render_polyhedra((5, 2, 3), (1, 0, 1), description="rhombicosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 1, 1), description="truncated-cuboctahedron")
    """
    render_polyhedra((5, 2, 3), (1, 1, 1), description="truncated-icosidodecahedron")
    render_polyhedra((4, 2, 3), (1, 1, 1), description="snub-cube", snub=True)
    render_polyhedra((5, 2, 3), (1, 1, 1), description="snub-dodecahedron", snub=True)

    # prism and antiprism
    render_polyhedra((7, 2, 2), (1, 0, 1), description="7-prism")
    render_polyhedra((8, 2, 2), (1, 1, 1), description="8-antiprism", snub=True)

    # regular polychora
    render_polychora((3, 2, 2, 3, 2, 3), (1, 0, 0, 0), "5-cell-1000.pov", "5-cell")
    """
    render_polychora((4, 2, 2, 3, 2, 3), (1, 0, 0, 0), "8-cell-1000.pov", "8-cell")
    render_polychora((3, 2, 2, 3, 2, 4), (1, 0, 0, 0), "16-cell-1000.pov", "16-cell")
    render_polychora((3, 2, 2, 4, 2, 3), (1, 0, 0, 0), "24-cell-1000.pov", "24-cell")
    render_polychora((5, 2, 2, 3, 2, 3), (1, 0, 0, 0), "120-cell-1000.pov", "120-cell")
    """
    render_polychora((3, 2, 2, 3, 2, 5), (1, 0, 0, 0), "600-cell-1000.pov", "600-cell")
    # some truncated polychora
    # for more examples see the .pov files in the povray directory
    """
    render_polychora((3, 2, 2, 3, 2, 3), (1, 1, 1, 0), "5-cell-1110.pov", "cantitruncated-5-cell")
    render_polychora((4, 2, 2, 3, 2, 3), (1, 1, 0, 0), "8-cell-1100.pov", "truncated-8-cell")
    render_polychora((3, 2, 2, 3, 2, 4), (1, 0, 0, 1), "16-cell-1001.pov", "runcinated-16-cell")
    render_polychora((3, 2, 2, 4, 2, 3), (1, 1, 1, 0), "24-cell-1110.pov", "cantitruncated-24-cell")
    """
    render_polychora((3, 2, 2, 3, 2, 5), (1, 1, 0, 0), "600-cell-1100.pov", "truncated-600-cell")

    # 4d prism and duoprism
    render_polychora((6, 2, 2, 2, 2, 8), (1, 0, 1.6, 0), "duoprism.pov", "6-8-duoprism")
    render_polychora((5, 2, 2, 3, 2, 2), (1, 1, 0, 1), "prism.pov", "5-3-prism")
<|endoftext|>


<commit_before>"""
The `petl` module.

"""

#0.16.1
#0.16.2
#0.17
#0.17.1
#0.18
#0.18.1
#0.19
#0.20
#0.21
#0.21.1
#0.21.2
#0.22
__version__ = VERSION = '0.22.1'

from petl.util import header, fieldnames, data, records, rowcount, look, see, \
    itervalues, values, iterdata, valuecounter, valuecounts, \
    valueset, isunique, lookup, lookupone, recordlookup, recordlookupone, \
    typecounter, typecounts, typeset, parsecounter, parsecounts, \
    stats, rowlengths, DuplicateKeyError, datetimeparser, dateparser, timeparser, boolparser, \
    expr, limits, strjoin, valuecount, lookall, dataslice, parsenumber, \
    stringpatterns, stringpatterncounter, randomtable, dummytable, \
    diffheaders, diffvalues, columns, facetcolumns, heapqmergesorted, \
    shortlistmergesorted, progress, clock, isordered, rowgroupby, nrows, \
    nthword, lookstr, listoflists, tupleoftuples, listoftuples, tupleoflists, \
    lol, tot, tol, lot, iternamedtuples, namedtuples, iterrecords, dicts, \
    iterdicts, dictlookup, dictlookupone, cache

from petl.io import fromcsv, frompickle, fromsqlite3, tocsv, topickle, \
    tosqlite3, fromdb, \
    appendcsv, appendpickle, appendsqlite3, todb, appenddb, fromtext, \
    totext, appendtext, fromxml, fromjson, fromdicts, tojson, \
    fromtsv, totsv, appendtsv, tojsonarrays, tohtml, fromucsv, toucsv, appenducsv, fromutsv, toutsv, appendutsv, \
    FileSource, GzipSource, BZ2Source, URLSource, StdinSource, StdoutSource, StringSource, PopenSource, ZipSource, \
    fromutext, toutext, appendutext, touhtml

from petl.transform import rename, cut, cat, convert, fieldconvert, addfield, rowslice, \
    head, tail, sort, melt, recast, duplicates, conflicts, \
    mergereduce, select, complement, diff, capture, \
    split, fieldmap, facet, selecteq, rowreduce, merge, aggregate, recordreduce, \
    rowmap, recordmap, rowmapmany, recordmapmany, setheader, pushheader, skip, \
    extendheader, unpack, join, leftjoin, rightjoin, outerjoin, crossjoin, \
    antijoin, rangeaggregate, rangecounts, selectop, selectne, selectgt, \
    selectge, selectlt, selectle, rangefacet, selectrangeopenleft, \
    selectrangeopenright, selectrangeopen, selectrangeclosed, rangerowreduce, \
    rangerecordreduce, selectin, selectnotin, selectre, rowselect, recordselect, \
    fieldselect, rowlenselect, selectis, selectisnot, selectisinstance, transpose, \
    intersection, pivot, recordcomplement, recorddiff, cutout, skipcomments, \
    convertall, convertnumbers, hashjoin, hashleftjoin, hashrightjoin, \
    hashantijoin, hashcomplement, hashintersection, replace, replaceall, \
    resub, flatten, unflatten, mergesort, annex, unpackdict, unique, \
    fold, mergeduplicates, addrownumbers, selectcontains, search, sub, \
    addcolumn, lookupjoin, hashlookupjoin, filldown, fillright, fillleft, \
    multirangeaggregate, unjoin, rowgroupmap, distinct, groupcountdistinctvalues, \
    groupselectfirst, groupselectmax, groupselectmin, coalesce

def lenstats(table, field):
    """
    Convenience function to report statistics on value lengths under the given
    field. E.g.::

        >>> from petl import lenstats
        >>> table1 = [['foo', 'bar'],
        ...           [1, 'a'],
        ...           [2, 'aaa'],
        ...           [3, 'aa'],
        ...           [4, 'aaa'],
        ...           [5, 'aaaaaaaaaaa']]
        >>> lenstats(table1, 'bar')
        {'count': 5, 'errors': 0, 'min': 1.0, 'max': 11.0, 'sum': 20.0, 'mean': 4.0}

    """

    return stats(convert(table, field, lambda v: len(v)), field)

# convenience aliases
eq = selecteq
ne = selectne
lt = selectlt
gt = selectgt
le = selectle
ge = selectge
<commit_msg>increment version<commit_after>"""
The `petl` module.

"""

#0.16.1
#0.16.2
#0.17
#0.17.1
#0.18
#0.18.1
#0.19
#0.20
#0.21
#0.21.1
#0.21.2
#0.22
#0.22.1
__version__ = VERSION = '0.23-SNAPSHOT'

from petl.util import header, fieldnames, data, records, rowcount, look, see, \
    itervalues, values, iterdata, valuecounter, valuecounts, \
    valueset, isunique, lookup, lookupone, recordlookup, recordlookupone, \
    typecounter, typecounts, typeset, parsecounter, parsecounts, \
    stats, rowlengths, DuplicateKeyError, datetimeparser, dateparser, timeparser, boolparser, \
    expr, limits, strjoin, valuecount, lookall, dataslice, parsenumber, \
    stringpatterns, stringpatterncounter, randomtable, dummytable, \
    diffheaders, diffvalues, columns, facetcolumns, heapqmergesorted, \
    shortlistmergesorted, progress, clock, isordered, rowgroupby, nrows, \
    nthword, lookstr, listoflists, tupleoftuples, listoftuples, tupleoflists, \
    lol, tot, tol, lot, iternamedtuples, namedtuples, iterrecords, dicts, \
    iterdicts, dictlookup, dictlookupone, cache

from petl.io import fromcsv, frompickle, fromsqlite3, tocsv, topickle, \
    tosqlite3, fromdb, \
    appendcsv, appendpickle, appendsqlite3, todb, appenddb, fromtext, \
    totext, appendtext, fromxml, fromjson, fromdicts, tojson, \
    fromtsv, totsv, appendtsv, tojsonarrays, tohtml, fromucsv, toucsv, appenducsv, fromutsv, toutsv, appendutsv, \
    FileSource, GzipSource, BZ2Source, URLSource, StdinSource, StdoutSource, StringSource, PopenSource, ZipSource, \
    fromutext, toutext, appendutext, touhtml

from petl.transform import rename, cut, cat, convert, fieldconvert, addfield, rowslice, \
    head, tail, sort, melt, recast, duplicates, conflicts, \
    mergereduce, select, complement, diff, capture, \
    split, fieldmap, facet, selecteq, rowreduce, merge, aggregate, recordreduce, \
    rowmap, recordmap, rowmapmany, recordmapmany, setheader, pushheader, skip, \
    extendheader, unpack, join, leftjoin, rightjoin, outerjoin, crossjoin, \
    antijoin, rangeaggregate, rangecounts, selectop, selectne, selectgt, \
    selectge, selectlt, selectle, rangefacet, selectrangeopenleft, \
    selectrangeopenright, selectrangeopen, selectrangeclosed, rangerowreduce, \
    rangerecordreduce, selectin, selectnotin, selectre, rowselect, recordselect, \
    fieldselect, rowlenselect, selectis, selectisnot, selectisinstance, transpose, \
    intersection, pivot, recordcomplement, recorddiff, cutout, skipcomments, \
    convertall, convertnumbers, hashjoin, hashleftjoin, hashrightjoin, \
    hashantijoin, hashcomplement, hashintersection, replace, replaceall, \
    resub, flatten, unflatten, mergesort, annex, unpackdict, unique, \
    fold, mergeduplicates, addrownumbers, selectcontains, search, sub, \
    addcolumn, lookupjoin, hashlookupjoin, filldown, fillright, fillleft, \
    multirangeaggregate, unjoin, rowgroupmap, distinct, groupcountdistinctvalues, \
    groupselectfirst, groupselectmax, groupselectmin, coalesce

def lenstats(table, field):
    """
    Convenience function to report statistics on value lengths under the given
    field. E.g.::

        >>> from petl import lenstats
        >>> table1 = [['foo', 'bar'],
        ...           [1, 'a'],
        ...           [2, 'aaa'],
        ...           [3, 'aa'],
        ...           [4, 'aaa'],
        ...           [5, 'aaaaaaaaaaa']]
        >>> lenstats(table1, 'bar')
        {'count': 5, 'errors': 0, 'min': 1.0, 'max': 11.0, 'sum': 20.0, 'mean': 4.0}

    """

    return stats(convert(table, field, lambda v: len(v)), field)

# convenience aliases
eq = selecteq
ne = selectne
lt = selectlt
gt = selectgt
le = selectle
ge = selectge
<|endoftext|>