text:
"""Overview:
  The servicerouter is a replacement for the haproxy-marathon-bridge.
  It reads the Marathon task information and dynamically generates
  haproxy configuration details.

  To gather the task information, the servicerouter needs to know where
  to find Marathon. The service configuration details are stored in Marathon
  environment variables.

  Every service port in Marathon can be configured independently.

Features:
  - Virtual Host aliases for services
  - Soft restart of haproxy
  - SSL Termination
  - (Optional): real-time update from Marathon events

Configuration:
  Service configuration lives in Marathon via environment variables.
  The servicerouter just needs to know where to find marathon.
  To run in listening mode you must also specify the address + port at
  which the servicerouter can be reached by marathon.

Usage:
  $ servicerouter.py --marathon http://marathon1:8080 \
        --haproxy-config /etc/haproxy/haproxy.cfg

  The user that executes servicerouter must have the permission to reload
  haproxy.

Environment Variables:
  HAPROXY_GROUP
    The group of servicerouter instances that point to the service.
    Service routers with the group '*' will collect all groups.

  HAPROXY_{n}_VHOST
    The Marathon HTTP Virtual Host proxy hostname to gather.
    Ex: HAPROXY_0_VHOST = 'marathon.mesosphere.com'

  HAPROXY_{n}_STICKY
    Enable sticky request routing for the service.
    Ex: HAPROXY_0_STICKY = true

  HAPROXY_{n}_REDIRECT_TO_HTTPS
    Redirect HTTP traffic to HTTPS.
    Ex: HAPROXY_0_REDIRECT_TO_HTTPS = true

  HAPROXY_{n}_SSL_CERT
    Enable the given SSL certificate for TLS/SSL traffic.
    Ex: HAPROXY_0_SSL_CERT = '/etc/ssl/certs/marathon.mesosphere.com'

  HAPROXY_{n}_BIND_ADDR
    Bind to the specific address for the service.
    Ex: HAPROXY_0_BIND_ADDR = '10.0.0.42'

  HAPROXY_{n}_PORT
    Bind to the specific port for the service.
    This overrides the servicePort which has to be unique.
    Ex: HAPROXY_0_PORT = 80

  HAPROXY_{n}_MODE
    Set the connection mode to either TCP or HTTP. The default is TCP.
    Ex: HAPROXY_0_MODE = 'http'

Templates:
  The servicerouter searches for configuration files in the templates/
  directory. The templates/ directory contains servicerouter configuration
  settings and example usage. The templates/ directory is located in a relative
  path from where the script is run.

  HAPROXY_HEAD
    The head of the haproxy config. This contains global settings
    and defaults.

  HAPROXY_HTTP_FRONTEND_HEAD
    An HTTP frontend that binds to port *:80 by default and gathers
    all virtual hosts as defined by the HAPROXY_{n}_VHOST variable.

  HAPROXY_HTTP_FRONTEND_APPID_HEAD
    An HTTP frontend that binds to port *:81 by default and gathers
    all apps in http mode.
    To use this frontend to forward to your app, configure the app with
    "HAPROXY_0_MODE=http" then you can access it via a call to the :81 with
    the header "X-Marathon-App-Id" set to the Marathon AppId.
    Note multiple http ports being exposed by the same marathon app are not
    supported. Only the first http port is available via this frontend.

  HAPROXY_HTTPS_FRONTEND_HEAD
    An HTTPS frontend for encrypted connections that binds to port *:443 by
    default and gathers all virtual hosts as defined by the
    HAPROXY_{n}_VHOST variable. You must modify this file to
    include your certificate.

  HAPROXY_BACKEND_REDIRECT_HTTP_TO_HTTPS
    This template is used with backends where the
    HAPROXY_{n}_REDIRECT_TO_HTTPS environment variable is defined.

  HAPROXY_BACKEND_HTTP_OPTIONS
    Sets HTTP headers, for example X-Forwarded-For and X-Forwarded-Proto.

  HAPROXY_BACKEND_HTTP_HEALTHCHECK_OPTIONS
    Sets HTTP health check options, for example timeout check and httpchk GET.
    Parameters of the first health check for this service are exposed as:
      * healthCheckPortIndex
      * healthCheckProtocol
      * healthCheckPath
      * healthCheckTimeoutSeconds
      * healthCheckIntervalSeconds
      * healthCheckIgnoreHttp1xx
      * healthCheckGracePeriodSeconds
      * healthCheckMaxConsecutiveFailures
      * healthCheckFalls is set to healthCheckMaxConsecutiveFailures + 1
    Defaults to empty string.
    Example:
      option  httpchk GET {healthCheckPath}
      timeout check {healthCheckTimeoutSeconds}s

  HAPROXY_BACKEND_TCP_HEALTHCHECK_OPTIONS
    Sets TCP health check options, for example timeout check.
    Parameters of the first health check for this service are exposed as:
      * healthCheckPortIndex
      * healthCheckProtocol
      * healthCheckTimeoutSeconds
      * healthCheckIntervalSeconds
      * healthCheckGracePeriodSeconds
      * healthCheckMaxConsecutiveFailures
      * healthCheckFalls is set to healthCheckMaxConsecutiveFailures + 1
    Defaults to empty string.
    Example:
      timeout check {healthCheckTimeoutSeconds}s

  HAPROXY_BACKEND_STICKY_OPTIONS
    Sets a cookie for services where HAPROXY_{n}_STICKY is true.

  HAPROXY_FRONTEND_HEAD
    Defines the address and port to bind to.

  HAPROXY_BACKEND_HEAD
    Defines the type of load balancing, roundrobin by default,
    and connection mode, TCP or HTTP.

  HAPROXY_HTTP_FRONTEND_ACL
    The ACL that glues a backend to the corresponding virtual host
    of the HAPROXY_HTTP_FRONTEND_HEAD.

  HAPROXY_HTTP_FRONTEND_APPID_ACL
    The ACL that glues a backend to the corresponding app
    of the HAPROXY_HTTP_FRONTEND_APPID_HEAD.

  HAPROXY_HTTPS_FRONTEND_ACL
    The ACL that performs the SNI based hostname matching
    for the HAPROXY_HTTPS_FRONTEND_HEAD.

  HAPROXY_BACKEND_SERVER_OPTIONS
    The options for each physical server added to a backend.

  HAPROXY_BACKEND_SERVER_HTTP_HEALTHCHECK_OPTIONS
    Sets HTTP health check options for a single server, e.g. check inter.
    Parameters of the first health check for this service are exposed as:
      * healthCheckPortIndex
      * healthCheckProtocol
      * healthCheckPath
      * healthCheckTimeoutSeconds
      * healthCheckIntervalSeconds
      * healthCheckIgnoreHttp1xx
      * healthCheckGracePeriodSeconds
      * healthCheckMaxConsecutiveFailures
      * healthCheckFalls is set to healthCheckMaxConsecutiveFailures + 1
    Defaults to empty string.
    Example:
      check inter {healthCheckIntervalSeconds}s fall {healthCheckFalls}

  HAPROXY_BACKEND_SERVER_TCP_HEALTHCHECK_OPTIONS
    Sets TCP health check options for a single server, e.g. check inter.
    Parameters of the first health check for this service are exposed as:
      * healthCheckPortIndex
      * healthCheckProtocol
      * healthCheckTimeoutSeconds
      * healthCheckIntervalSeconds
      * healthCheckGracePeriodSeconds
      * healthCheckMaxConsecutiveFailures
      * healthCheckFalls is set to healthCheckMaxConsecutiveFailures + 1
    Defaults to empty string.
    Example:
      check inter {healthCheckIntervalSeconds}s fall {healthCheckFalls}

  HAPROXY_FRONTEND_BACKEND_GLUE
    This option glues the backend to the frontend.

Operational Notes:
  - When a node in listening mode fails, remove the callback url for that
    node in marathon.
  - If run in listening mode, DNS isn't re-resolved. Restart the process
    periodically to force re-resolution if desired.
"""

from logging.handlers import SysLogHandler
from operator import attrgetter
from shutil import move
from tempfile import mkstemp
from textwrap import dedent
from wsgiref.simple_server import make_server
import argparse
import json
import logging
import os
import os.path
import stat
import re
import requests
import subprocess
import sys
import socket
import time

class ConfigTemplater(object):
    HAPROXY_HEAD = dedent('''\
    global
      daemon
      log 127.0.0.1 local0
      log 127.0.0.1 local1 notice
      maxconn 4096
      tune.ssl.default-dh-param 2048

    defaults
      log               global
      retries           3
      maxconn           2000
      timeout connect   5s
      timeout client    50s
      timeout server    50s

    listen stats
      bind 127.0.0.1:9090
      balance
      mode http
      stats enable
      stats auth admin:admin
    ''')

    HAPROXY_HTTP_FRONTEND_HEAD = dedent('''
    frontend marathon_http_in
      bind *:80
      mode http
    ''')

    HAPROXY_HTTP_FRONTEND_APPID_HEAD = dedent('''
    frontend marathon_http_appid_in
      bind *:81
      mode http
    ''')

    # TODO(lloesche): make certificate path dynamic and allow multiple certs
    HAPROXY_HTTPS_FRONTEND_HEAD = dedent('''
    frontend marathon_https_in
      bind *:443 ssl crt /etc/ssl/mesosphere.com.pem
      mode http
    ''')

    HAPROXY_FRONTEND_HEAD = dedent('''
    frontend {backend}
      bind {bindAddr}:{servicePort}{sslCertOptions}
      mode {mode}
    ''')

    HAPROXY_BACKEND_HEAD = dedent('''
    backend {backend}
      balance roundrobin
      mode {mode}
    ''')

    HAPROXY_BACKEND_REDIRECT_HTTP_TO_HTTPS = '''\
  bind {bindAddr}:80
  redirect scheme https if !{{ ssl_fc }}
'''

    HAPROXY_HTTP_FRONTEND_ACL = '''\
  acl host_{cleanedUpHostname} hdr(host) -i {hostname}
  use_backend {backend} if host_{cleanedUpHostname}
'''

    HAPROXY_HTTP_FRONTEND_APPID_ACL = '''\
  acl app_{cleanedUpAppId} hdr(x-marathon-app-id) -i {appId}
  use_backend {backend} if app_{cleanedUpAppId}
'''

    HAPROXY_HTTPS_FRONTEND_ACL = '''\
  use_backend {backend} if {{ ssl_fc_sni {hostname} }}
'''

    HAPROXY_BACKEND_HTTP_OPTIONS = '''\
  option forwardfor
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
'''

    HAPROXY_BACKEND_HTTP_HEALTHCHECK_OPTIONS = ''
    HAPROXY_BACKEND_TCP_HEALTHCHECK_OPTIONS = ''

    HAPROXY_BACKEND_STICKY_OPTIONS = '''\
  cookie mesosphere_server_id insert indirect nocache
'''

    HAPROXY_BACKEND_SERVER_OPTIONS = '''\
  server {serverName} {host_ipv4}:{port}{cookieOptions}{healthCheckOptions}
'''

    HAPROXY_BACKEND_SERVER_HTTP_HEALTHCHECK_OPTIONS = ''
    HAPROXY_BACKEND_SERVER_TCP_HEALTHCHECK_OPTIONS = ''

    HAPROXY_FRONTEND_BACKEND_GLUE = '''\
  use_backend {backend}
'''

    def __init__(self, directory='templates'):
        self.__template_directory = directory
        self.__load_templates()

    def __load_templates(self):
        '''Loads template files if they exist, othwerwise it sets defaults'''
        variables = [
            'HAPROXY_HEAD',
            'HAPROXY_HTTP_FRONTEND_HEAD',
            'HAPROXY_HTTP_FRONTEND_APPID_HEAD',
            'HAPROXY_HTTPS_FRONTEND_HEAD',
            'HAPROXY_FRONTEND_HEAD',
            'HAPROXY_BACKEND_REDIRECT_HTTP_TO_HTTPS',
            'HAPROXY_BACKEND_HEAD',
            'HAPROXY_HTTP_FRONTEND_ACL',
            'HAPROXY_HTTP_FRONTEND_APPID_ACL',
            'HAPROXY_HTTPS_FRONTEND_ACL',
            'HAPROXY_BACKEND_HTTP_OPTIONS',
            'HAPROXY_BACKEND_HTTP_HEALTHCHECK_OPTIONS',
            'HAPROXY_BACKEND_TCP_HEALTHCHECK_OPTIONS',
            'HAPROXY_BACKEND_STICKY_OPTIONS',
            'HAPROXY_BACKEND_SERVER_OPTIONS',
            'HAPROXY_BACKEND_SERVER_HTTP_HEALTHCHECK_OPTIONS',
            'HAPROXY_BACKEND_SERVER_TCP_HEALTHCHECK_OPTIONS',
            'HAPROXY_FRONTEND_BACKEND_GLUE',
        ]

        for variable in variables:
            try:
                filename = os.path.join(self.__template_directory, variable)
                with open(filename) as f:
                    logger.info('overriding %s from %s', variable, filename)
                    setattr(self, variable, f.read())
            except IOError:
                logger.debug("setting default value for %s", variable)
                try:
                    setattr(self, variable, getattr(self.__class__, variable))
                except AttributeError:
                    logger.exception('default not found, aborting.')
                    raise

    @property
    def haproxy_head(self):
        return self.HAPROXY_HEAD

    @property
    def haproxy_http_frontend_head(self):
        return self.HAPROXY_HTTP_FRONTEND_HEAD

    @property
    def haproxy_http_frontend_appid_head(self):
        return self.HAPROXY_HTTP_FRONTEND_APPID_HEAD

    @property
    def haproxy_https_frontend_head(self):
        return self.HAPROXY_HTTPS_FRONTEND_HEAD

    @property
    def haproxy_frontend_head(self):
        return self.HAPROXY_FRONTEND_HEAD

    @property
    def haproxy_backend_redirect_http_to_https(self):
        return self.HAPROXY_BACKEND_REDIRECT_HTTP_TO_HTTPS

    @property
    def haproxy_backend_head(self):
        return self.HAPROXY_BACKEND_HEAD

    @property
    def haproxy_http_frontend_acl(self):
        return self.HAPROXY_HTTP_FRONTEND_ACL

    @property
    def haproxy_http_frontend_appid_acl(self):
        return self.HAPROXY_HTTP_FRONTEND_APPID_ACL

    @property
    def haproxy_https_frontend_acl(self):
        return self.HAPROXY_HTTPS_FRONTEND_ACL

    @property
    def haproxy_backend_http_options(self):
        return self.HAPROXY_BACKEND_HTTP_OPTIONS

    @property
    def haproxy_backend_http_healthcheck_options(self):
        return self.HAPROXY_BACKEND_HTTP_HEALTHCHECK_OPTIONS

    @property
    def haproxy_backend_tcp_healthcheck_options(self):
        return self.HAPROXY_BACKEND_TCP_HEALTHCHECK_OPTIONS

    @property
    def haproxy_backend_sticky_options(self):
        return self.HAPROXY_BACKEND_STICKY_OPTIONS

    @property
    def haproxy_backend_server_options(self):
        return self.HAPROXY_BACKEND_SERVER_OPTIONS

    @property
    def haproxy_backend_server_http_healthcheck_options(self):
        return self.__blank_prefix_or_empty(
            self.HAPROXY_BACKEND_SERVER_HTTP_HEALTHCHECK_OPTIONS.strip())

    @property
    def haproxy_backend_server_tcp_healthcheck_options(self):
        return self.__blank_prefix_or_empty(
            self.HAPROXY_BACKEND_SERVER_TCP_HEALTHCHECK_OPTIONS.strip())

    @property
    def haproxy_frontend_backend_glue(self):
        return self.HAPROXY_FRONTEND_BACKEND_GLUE

    def __blank_prefix_or_empty(self, s):
        if s:
            return ' ' + s
        else:
            return s

def string_to_bool(s):
    return s.lower() in ["true", "t", "yes", "y"]

def set_hostname(x, y):
    x.hostname = y

def set_sticky(x, y):
    x.sticky = string_to_bool(y)

def set_redirect_http_to_https(x, y):
    x.redirectHttpToHttps = string_to_bool(y)

def set_sslCert(x, y):
    x.sslCert = y

def set_bindAddr(x, y):
    x.bindAddr = y

def set_port(x, y):
    x.servicePort = int(y)

def set_mode(x, y):
    x.mode = y

env_keys = {
    'HAPROXY_{0}_VHOST': set_hostname,
    'HAPROXY_{0}_STICKY': set_sticky,
    'HAPROXY_{0}_REDIRECT_TO_HTTPS': set_redirect_http_to_https,
    'HAPROXY_{0}_SSL_CERT': set_sslCert,
    'HAPROXY_{0}_BIND_ADDR': set_bindAddr,
    'HAPROXY_{0}_PORT': set_port,
    'HAPROXY_{0}_MODE': set_mode
}

logger = logging.getLogger('servicerouter')

class MarathonBackend(object):

    def __init__(self, host, port):
        self.host = host
        self.port = port

    def __hash__(self):
        return hash((self.host, self.port))

    def __repr__(self):
        return "MarathonBackend(%r, %r)" % (self.host, self.port)

class MarathonService(object):

    def __init__(self, appId, servicePort, healthCheck):
        self.appId = appId
        self.servicePort = servicePort
        self.backends = set()
        self.hostname = None
        self.sticky = False
        self.redirectHttpToHttps = False
        self.sslCert = None
        self.bindAddr = '*'
        self.groups = frozenset()
        self.mode = 'tcp'
        self.healthCheck = healthCheck
        if healthCheck:
            if healthCheck['protocol'] == 'HTTP':
                self.mode = 'http'

    def add_backend(self, host, port):
        self.backends.add(MarathonBackend(host, port))

    def __hash__(self):
        return hash(self.servicePort)

    def __eq__(self, other):
        return self.servicePort == other.servicePort

    def __repr__(self):
        return "MarathonService(%r, %r)" % (self.appId, self.servicePort)

class MarathonApp(object):

    def __init__(self, marathon, appId, app):
        self.app = app
        self.groups = frozenset()
        self.appId = appId

        # port -> MarathonService
        self.services = dict()

    def __hash__(self):
        return hash(self.appId)

    def __eq__(self, other):
        return self.appId == other.appId

class Marathon(object):

    def __init__(self, hosts):
        # TODO(cmaloney): Support getting master list from zookeeper
        self.__hosts = hosts

    def api_req_raw(self, method, path, body=None, **kwargs):
        for host in self.__hosts:
            path_str = os.path.join(host, 'v2')

            for path_elem in path:
                path_str = path_str + "/" + path_elem
            response = requests.request(
                method,
                path_str,
                headers={
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                **kwargs
            )

            logger.debug("%s %s", method, response.url)
            if response.status_code == 200:
                break
        if 'message' in response.json():
            response.reason = "%s (%s)" % (
                response.reason,
                response.json()['message'])
        response.raise_for_status()
        return response

    def api_req(self, method, path, **kwargs):
        return self.api_req_raw(method, path, **kwargs).json()

    def create(self, app_json):
        return self.api_req('POST', ['apps'], app_json)

    def get_app(self, appid):
        logger.info('fetching app %s', appid)
        return self.api_req('GET', ['apps', appid])["app"]

    # Lists all running apps.
    def list(self):
        logger.info('fetching apps')
        return self.api_req('GET', ['apps'],
                            params={'embed': 'apps.tasks'})["apps"]

    def tasks(self):
        logger.info('fetching tasks')
        return self.api_req('GET', ['tasks'])["tasks"]

    def add_subscriber(self, callbackUrl):
        return self.api_req(
                'POST',
                ['eventSubscriptions'],
                params={'callbackUrl': callbackUrl})

    def remove_subscriber(self, callbackUrl):
        return self.api_req(
                'DELETE',
                ['eventSubscriptions'],
                params={'callbackUrl': callbackUrl})

def has_group(groups, app_groups):
    # All groups / wildcard match
    if '*' in groups:
        return True

    # empty group only
    if len(groups) == 0 and len(app_groups) == 0:
        return True

    # Contains matching groups
    if (len(frozenset(app_groups) & groups)):
        return True

    return False

ip_cache = dict()

def resolve_ip(host):
    cached_ip = ip_cache.get(host, None)
    if cached_ip:
        return cached_ip
    else:
        try:
            logger.debug("trying to resolve ip address for host %s", host)
            ip = socket.gethostbyname(host)
            ip_cache[host] = ip
            return ip
        except socket.gaierror:
            return None

def config(apps, groups):
    logger.info("generating config")
    templater = ConfigTemplater()
    config = templater.haproxy_head
    groups = frozenset(groups)

    http_frontends = templater.haproxy_http_frontend_head
    https_frontends = templater.haproxy_https_frontend_head
    frontends = str()
    backends = str()
    http_appid_frontends = templater.haproxy_http_frontend_appid_head
    apps_with_http_appid_backend = []

    for app in sorted(apps, key=attrgetter('appId', 'servicePort')):
        # App only applies if we have it's group
        if not has_group(groups, app.groups):
            continue

        logger.debug("configuring app %s", app.appId)
        backend = app.appId[1:].replace('/', '_') + '_' + str(app.servicePort)

        logger.debug("frontend at %s:%d with backend %s",
                     app.bindAddr, app.servicePort, backend)

        # if the app has a hostname set force mode to http
        # otherwise recent versions of haproxy refuse to start
        if app.hostname:
            app.mode = 'http'

        frontend_head = templater.haproxy_frontend_head
        frontends += frontend_head.format(
            bindAddr=app.bindAddr,
            backend=backend,
            servicePort=app.servicePort,
            mode=app.mode,
            sslCertOptions=' ssl crt ' + app.sslCert if app.sslCert else ''
        )

        if app.redirectHttpToHttps:
            logger.debug("rule to redirect http to https traffic")
            haproxy_backend_redirect_http_to_https = \
                templater.haproxy_backend_redirect_http_to_https
            frontends += haproxy_backend_redirect_http_to_https.format(
                bindAddr=app.bindAddr)

        backend_head = templater.haproxy_backend_head
        backends += backend_head.format(
            backend=backend,
            mode=app.mode
        )

        # if a hostname is set we add the app to the vhost section
        # of our haproxy config
        # TODO(lloesche): Check if the hostname is already defined by another
        # service
        if app.hostname:
            logger.debug(
                "adding virtual host for app with hostname %s", app.hostname)
            cleanedUpHostname = re.sub(r'[^a-zA-Z0-9\-]', '_', app.hostname)

            http_frontend_acl = templater.haproxy_http_frontend_acl
            http_frontends += http_frontend_acl.format(
                cleanedUpHostname=cleanedUpHostname,
                hostname=app.hostname,
                appId=app.appId,
                backend=backend
            )

            https_frontend_acl = templater.haproxy_https_frontend_acl
            https_frontends += https_frontend_acl.format(
                cleanedUpHostname=cleanedUpHostname,
                hostname=app.hostname,
                appId=app.appId,
                backend=backend
            )

        # if app mode is http, we add the app to the second http frontend
        # selecting apps by http header X-Marathon-App-Id
        if app.mode == 'http' and \
                app.appId not in apps_with_http_appid_backend:
            logger.debug("adding virtual host for app with id %s", app.appId)
            # remember appids to prevent multiple entries for the same app
            apps_with_http_appid_backend += [app.appId]
            cleanedUpAppId = re.sub(r'[^a-zA-Z0-9\-]', '_', app.appId)

            http_appid_frontend_acl = templater.haproxy_http_frontend_appid_acl
            http_appid_frontends += http_appid_frontend_acl.format(
                cleanedUpAppId=cleanedUpAppId,
                hostname=app.hostname,
                appId=app.appId,
                backend=backend
            )

        if app.mode == 'http':
            backends += templater.haproxy_backend_http_options

        if app.healthCheck:
            health_check_options = None
            if app.mode == 'tcp':
                health_check_options = templater \
                    .haproxy_backend_tcp_healthcheck_options
            elif app.mode == 'http':
                health_check_options = templater \
                    .haproxy_backend_http_healthcheck_options
            if health_check_options:
                backends += health_check_options.format(
                    healthCheck=app.healthCheck,
                    healthCheckPortIndex=app.healthCheck['portIndex'],
                    healthCheckProtocol=app.healthCheck['protocol'],
                    healthCheckPath=app.healthCheck['path'],
                    healthCheckTimeoutSeconds=app.healthCheck[
                        'timeoutSeconds'],
                    healthCheckIntervalSeconds=app.healthCheck[
                        'intervalSeconds'],
                    healthCheckIgnoreHttp1xx=app.healthCheck['ignoreHttp1xx'],
                    healthCheckGracePeriodSeconds=app.healthCheck[
                        'gracePeriodSeconds'],
                    healthCheckMaxConsecutiveFailures=app.healthCheck[
                        'maxConsecutiveFailures'],
                    healthCheckFalls=app.healthCheck[
                        'maxConsecutiveFailures'] + 1
                )

        if app.sticky:
            logger.debug("turning on sticky sessions")
            backends += templater.haproxy_backend_sticky_options

        frontend_backend_glue = templater.haproxy_frontend_backend_glue
        frontends += frontend_backend_glue.format(backend=backend)

        key_func = attrgetter('host', 'port')
        for backendServer in sorted(app.backends, key=key_func):
            logger.debug(
                "backend server at %s:%d",
                backendServer.host,
                backendServer.port)
            serverName = re.sub(
                r'[^a-zA-Z0-9\-]', '_',
                backendServer.host + '_' + str(backendServer.port))

            healthCheckOptions = None
            if app.healthCheck:
                server_health_check_options = None
                if app.mode == 'tcp':
                    server_health_check_options = templater \
                        .haproxy_backend_server_tcp_healthcheck_options
                elif app.mode == 'http':
                    server_health_check_options = templater \
                        .haproxy_backend_server_http_healthcheck_options
                if server_health_check_options:
                    healthCheckOptions = server_health_check_options.format(
                        healthCheck=app.healthCheck,
                        healthCheckPortIndex=app.healthCheck['portIndex'],
                        healthCheckProtocol=app.healthCheck['protocol'],
                        healthCheckPath=app.healthCheck['path'],
                        healthCheckTimeoutSeconds=app.healthCheck[
                            'timeoutSeconds'],
                        healthCheckIntervalSeconds=app.healthCheck[
                            'intervalSeconds'],
                        healthCheckIgnoreHttp1xx=app.healthCheck[
                            'ignoreHttp1xx'],
                        healthCheckGracePeriodSeconds=app.healthCheck[
                            'gracePeriodSeconds'],
                        healthCheckMaxConsecutiveFailures=app.healthCheck[
                            'maxConsecutiveFailures'],
                        healthCheckFalls=app.healthCheck[
                            'maxConsecutiveFailures'] + 1
                    )
            ipv4 = resolve_ip(backendServer.host)

            if ipv4 is not None:
                backend_server_options = templater\
                    .haproxy_backend_server_options
                backends += backend_server_options.format(
                    host=backendServer.host,
                    host_ipv4=ipv4,
                    port=backendServer.port,
                    serverName=serverName,
                    cookieOptions=' check cookie ' +
                    serverName if app.sticky else '',
                    healthCheckOptions=healthCheckOptions
                    if healthCheckOptions else ''
                )
            else:
                logger.warn("Could not resolve ip for host %s, "
                            "ignoring this backend",
                            backendServer.host)

    config += http_frontends
    config += http_appid_frontends
    config += https_frontends
    config += frontends
    config += backends

    return config

def reloadConfig():
    logger.debug("trying to find out how to reload the configuration")
    if os.getenv("HAPROXY_RELOAD_CMD"):
        logger.debug("HAPROXY_RELOAD_CMD is set, using it as command for reload")
        reloadCommand = os.getenv("HAPROXY_RELOAD_CMD").split(" ")
    elif os.path.isfile('/etc/init/haproxy.conf'):
        logger.debug("we seem to be running on an Upstart based system")
        reloadCommand = ['reload', 'haproxy']
    elif (os.path.isfile('/usr/lib/systemd/system/haproxy.service') or
            os.path.isfile('/etc/systemd/system/haproxy.service')):
        logger.debug("we seem to be running on systemd based system")
        reloadCommand = ['systemctl', 'reload', 'haproxy']
    else:
        logger.debug("we seem to be running on a sysvinit based system")
        reloadCommand = ['/etc/init.d/haproxy', 'reload']

    logger.info("reloading using %s", " ".join(reloadCommand))
    try:
        subprocess.check_call(reloadCommand)
    except OSError as ex:
        logger.error("unable to reload config using command %s",
                     " ".join(reloadCommand))
        logger.error("OSError: %s", ex)
    except subprocess.CalledProcessError as ex:
        logger.error("unable to reload config using command %s",
                     " ".join(reloadCommand))
        logger.error("reload returned non-zero: %s", ex)

def writeConfig(config, config_file):
    # Write config to a temporary location
    fd, haproxyTempConfigFile = mkstemp()
    logger.debug("writing config to temp file %s", haproxyTempConfigFile)
    with os.fdopen(fd, 'w') as haproxyTempConfig:
        haproxyTempConfig.write(config)

    # Ensure new config is created with the same
    # permissions the old file had or use defaults
    # if config file doesn't exist yet
    perms = 0o644
    if os.path.isfile(config_file):
        perms = stat.S_IMODE(os.lstat(config_file).st_mode)
    os.chmod(haproxyTempConfigFile, perms)

    # Move into place
    logger.debug("moving temp file %s to %s",
                 haproxyTempConfigFile,
                 config_file)
    move(haproxyTempConfigFile, config_file)

def compareWriteAndReloadConfig(config, config_file):
    # See if the last config on disk matches this, and if so don't reload
    # haproxy
    runningConfig = str()
    try:
        logger.debug("reading running config from %s", config_file)
        with open(config_file, "r") as f:
            runningConfig = f.read()
    except IOError:
        logger.warning("couldn't open config file for reading")

    if runningConfig != config:
        logger.info(
            "running config is different from generated config - reloading")
        writeConfig(config, config_file)
        reloadConfig()

def get_health_check(app, portIndex):
    for check in app['healthChecks']:
        if check['portIndex'] == portIndex:
            return check
    return None

def get_apps(marathon):
    apps = marathon.list()
    logger.debug("got apps %s", map(lambda app: app["id"], apps))

    marathon_apps = []

    for app in apps:
        appId = app['id']

        marathon_app = MarathonApp(marathon, appId, app)
        if 'HAPROXY_GROUP' in marathon_app.app['env']:
                    marathon_app.groups = \
                            marathon_app.app['env']['HAPROXY_GROUP'].split(',')
        marathon_apps.append(marathon_app)

        service_ports = app['ports']
        for i in xrange(len(service_ports)):
            servicePort = service_ports[i]
            service = MarathonService(
                        appId, servicePort, get_health_check(app, i))

            # Load environment variable configuration
            # TODO(cmaloney): Move to labels once those are supported
            # throughout the stack
            for key_unformatted in env_keys:
                key = key_unformatted.format(i)
                if key in marathon_app.app[u'env']:
                    func = env_keys[key_unformatted]
                    func(service, marathon_app.app[u'env'][key])

            marathon_app.services[servicePort] = service

        for task in app['tasks']:
            # Marathon 0.7.6 bug workaround
            if len(task['host']) == 0:
                logger.warning("Ignoring Marathon task without host " +
                               task['id'])
                continue

            task_ports = task['ports']

            # if different versions of app have different number of ports,
            # try to match as many ports as possible
            number_of_defined_ports = min(len(task_ports), len(service_ports))

            for i in xrange(number_of_defined_ports):
                task_port = task_ports[i]
                service_port = service_ports[i]
                service = marathon_app.services.get(service_port, None)
                if service:
                    service.groups = marathon_app.groups
                    service.add_backend(task['host'], task_port)

    # Convert into a list for easier consumption
    apps_list = list()
    for marathon_app in marathon_apps:
        for service in marathon_app.services.values():
            if service.backends:
                apps_list.append(service)
    return apps_list

def regenerate_config(apps, config_file, groups):
    compareWriteAndReloadConfig(config(apps, groups),
                                config_file)

class MarathonEventSubscriber(object):

    def __init__(self, marathon, addr, config_file, groups):
        marathon.add_subscriber(addr)
        self.__marathon = marathon
        # appId -> MarathonApp
        self.__apps = dict()
        self.__config_file = config_file
        self.__groups = groups

        # Fetch the base data
        self.reset_from_tasks()

    def reset_from_tasks(self):
        start_time = time.time()

        self.__apps = get_apps(self.__marathon)
        regenerate_config(self.__apps,
                          self.__config_file,
                          self.__groups)

        logger.debug("updating tasks finished, took %s seconds",
                     time.time() - start_time)

    def handle_event(self, event):
        if event['eventType'] == 'status_update_event':
            # TODO (cmaloney): Handle events more intelligently so we don't
            # unnecessarily hammer the Marathon API.
            self.reset_from_tasks()

def get_arg_parser():
    parser = argparse.ArgumentParser(
        description="Marathon HAProxy Service Router")
    parser.add_argument("--longhelp",
                        help="Print out configuration details",
                        action="store_true"
                        )
    parser.add_argument("--marathon", "-m",
                        nargs="+",
                        help="Marathon endpoint, eg. -m " +
                             "http://marathon1:8080 -m http://marathon2:8080"
                        )
    parser.add_argument("--listening", "-l",
                        help="The HTTP address that Marathon can call this " +
                             "script back at (http://lb1:8080)"
                        )

    default_log_socket = "/dev/log"
    if sys.platform == "darwin":
        default_log_socket = "/var/run/syslog"

    parser.add_argument("--syslog-socket",
                        help="Socket to write syslog messages to. "
                        "Use '/dev/null' to disable logging to syslog",
                        default=default_log_socket
                        )
    parser.add_argument("--log-format",
                        help="Set log message format",
                        default="%(name)s: %(message)s"
                        )
    parser.add_argument("--haproxy-config",
                        help="Location of haproxy configuration",
                        default="/etc/haproxy/haproxy.cfg"
                        )
    parser.add_argument("--group",
                        help="Only generate config for apps which list the "
                        "specified names. Defaults to apps without groups. "
                        "Use '*' to match all groups",
                        action="append",
                        default=list())

    return parser

def run_server(marathon, callback_url, config_file, groups):
    subscriber = MarathonEventSubscriber(marathon,
                                         callback_url,
                                         config_file,
                                         groups)

    # TODO(cmaloney): Switch to a sane http server
    # TODO(cmaloney): Good exception catching, etc
    def wsgi_app(env, start_response):
        length = int(env['CONTENT_LENGTH'])
        data = env['wsgi.input'].read(length)
        subscriber.handle_event(json.loads(data))
        # TODO(cmaloney): Make this have a simple useful webui for debugging /
        # monitoring
        start_response('200 OK', [('Content-Type', 'text/html')])

        return "Got it\n"

    try:
        port = int(callback_url.split(':')[-1])
    except ValueError:
        port = 8000  # no port or invalid port specified
    logger.info("Serving on port {0}...".format(port))
    httpd = make_server('', port, wsgi_app)
    httpd.serve_forever()

def clear_callbacks(marathon, callback_url):
    logger.info("Cleanup, removing subscription to {0}".format(callback_url))
    marathon.remove_subscriber(callback_url)

def setup_logging(syslog_socket, log_format):
    logger.setLevel(logging.DEBUG)

    formatter = logging.Formatter(log_format)

    consoleHandler = logging.StreamHandler()
    consoleHandler.setFormatter(formatter)
    logger.addHandler(consoleHandler)

    if args.syslog_socket != '/dev/null':
        syslogHandler = SysLogHandler(args.syslog_socket)
        syslogHandler.setFormatter(formatter)
        logger.addHandler(syslogHandler)

if __name__ == '__main__':
    # Process arguments
    arg_parser = get_arg_parser()
    args = arg_parser.parse_args()

    # Print the long help text if flag is set
    if args.longhelp:
        print __doc__
        sys.exit()
    # otherwise make sure that a Marathon URL was specified
    else:
        if args.marathon is None:
            arg_parser.error('argument --marathon/-m is required')

    # Setup logging
    setup_logging(args.syslog_socket, args.log_format)

    # Marathon API connector
    marathon = Marathon(args.marathon)

    # If in listening mode, spawn a webserver waiting for events. Otherwise
    # just write the config.
    if args.listening:
        try:
            run_server(marathon, args.listening, args.haproxy_config,
                       args.group)
        finally:
            clear_callbacks(marathon, args.listening)
    else:
        # Generate base config
        regenerate_config(get_apps(marathon), args.haproxy_config, args.group)

redpajama_set_name: RedPajamaGithub


Hello Ladies, my name is Jo and I am your local independent sales consultant for Helen É Cosmetics. I live by the coast in Ramsgate, Kent but I am able to travel to wherever you are in Kent. Please do not hesitate to contact me if you would like more information on Helen É Cosmetics, whether that's hosting a party and thereby getting free cosmetics or learning more about becoming a consultant.
Make staying in the new going out! Grab your girlfriends and female family members for a fun night in. Free mini make-overs for every guest and It's a great chance to try before you buy in the comfort of your own home. Party hostesses earn 15% of total party sales over £100, plus VIP hostesses get to purchase a selection of products at special prices. During certain promotional periods you may even be entitled to free gifts, subject to total party sales so why wouldn't you want to party with me and Helen É Cosmetics?
I can come to your workplace and demonstrate the products or if you are holding a ladies pamper evening I can bring my products along and set up a stall. I am also available to help raise funds for your school or organisation.
We also have a wonderful selection of bridal cosmetics. Why not have a hen party with a difference? I can show you how to apply stunning bridal make-up that will last throughout your special day.


This slideshow documents our research of Worthing's promenade, the images can also can be seen in a free, public exhibition on Worthing Pier.
to use their images in the exhibition. Also huge gratitude to our volunteers, who have spent many hours exploring the archives and documenting their research.


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Single cell analysis package: Class Members</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>

<link href="search/search.css" rel="stylesheet" type="text/css"/>

<link href="doxygen.css" rel="stylesheet" type="text/css" />

Single cell analysis package

Here is a list of all class members with links to the classes they belong to:

__init__()
: sc-analyses.settings

cell_sets
: sc-analyses.settings

parameters
: sc-analyses.settings

pcs
: sc-analyses.settings

read_cell_sets()
: sc-analyses.settings

result_filename
: sc-analyses.settings

run_mode
: sc-analyses.settings

sets
: sc-analyses.settings

<address class="footer">
Generated by

 1.8.13
</address>


The IUPUC campus is accredited by the Higher Learning Commission of the North Central Association of Colleges and Schools. The IUPUI Bachelor of Science in Mechanical Engineering program at IUPUC is an ABET-accredited program through the IUPUI School of Engineering and Technology.
The mechanical engineering program seeks input, feedback, and expertise from a variety of industry experts. Learn more about the membership of the Industrial Advisory Board.


I joined Rural Directions back in 2014 and have been lucky enough to be able to return to the role of Recruitment & HR Administrator after spending the last 2 years looking after my son.
I come from a strong farming background having grown up on our family farm in Puketitiri. I love visiting the farm with my young family and enjoying the adventures it has to offer.
I love to help people and enjoy the many different aspects of working in a Recruitment & HR role. Employers and Job Seekers are equally important and I like being part of the process where both parties come away happy.
I have worked in various administration roles over the last 12 years and always take great pride in assisting my fellow team members.
What Happens Out Of Work?
I love to spend time with my family on the weekends and find having a 2 year old keeps me very busy! We enjoy exploring all that Hawke's Bay has to offer.
Great customer service is vital in any business; I believe everybody should be treated with respect and importance.


HomeWhy Do PHP Developers Think MVC Is An Application Architecture?
Actually ADR is just an MVA. And most of backend php frameworks (Laravel, Symfony) uses Model-View-Adapter pattern to separate data presentation (HTTP in most of the cases) from application.
Actually ADR is just an MVA.
MVA is one of the patterns I failed to note in the ADR essay, in the section comparing ADR to pre-existing patterns. I've been meaning to add it to the essay (along with a lot of other things).
The Adapter holds a pointer both to the Model and to the View and directly calls methods on both. At the same time, it attaches itself as a listener both to the Model and to the View in order to receive events. It receives property change events from the Model and action events (checkbox ticked, text entered, etc.) from the View, and then routes appropriate changes to the other side. The Adapter is entirely responsible for keeping the Model and the View in sync; the Model and View are both relatively dumb structures, knowing nothing about the other.
If that description is accurate, it sounds like an in-memory GUI system, not a client-server or request-response environment. Also note that the Action in ADR (which would be the Adapter in MVA) is not responsible for "keeping the Model and View in sync" via event listeners, since there are no event listeners in ADR.
I think one of the other problems that confuses people is that the "M" in MVC is not the same as the "M" in ORM, even though they are both for "Model". I think this is what makes a lot of people think they need to put all their code in the controller, because they think the model part of MVC is just for their ORM classes.
I personally don't care whether people call MVC an architectural pattern or an interface pattern or a foobar pattern – it is still a software pattern.
In my own framework I started with the 3-Tier Architecture with its separate Presentation, Business and Data Access layers but because I split my Presentation layer components into two which followed the description of the View and Controller I discovered later that I had accidentally implemented the MVC pattern, with my Business layer providing all the Model classes.
In this implementation all business knowledge – data validation, business rules, task-specific behaviour – exists in and ONLY in the Business/Model layer. I have actually turned the Views, Controllers and DAOs into nothing but services which are built into the framework as reusable components. This means that application developers need only concern themselves with the components in the Application/Business layer.
The statement is true, but it fails to make an important distinction between types of buildings. I hope that imperfect analogy it gets my point across; that is, that having a common vocabulary to describe things is a good thing in its own right, and that using terms too loosely leads to misunderstanding and reduced comprehension.
Your analogy is flawed as it is much easier to describe the differences between a skyscraper, warehouse and mud hut than it is to describe the differences between an interface pattern and an architectural pattern.
If you cannot adequately describe the difference, then is there a difference?
Oh, I agree the analogy is imperfect (indeed, I said so above). And I say there are adequate descriptions of the differences (or, if you like, the distinctions) between, say, the ADR pattern and the "real original" MVC. Whether or not one chooses to recognize them, though, is another matter.
My point is that the description of the differences has to be enough for a newbie to understand. For example, there are some people who seem to think that SRP (Single Responsibility Principle) is different from SoC (Separation of Concerns) simply because they have separate pages in Wikipedia.
So what exactly is the difference between an architecture pattern and an interface pattern?
Probably part of the argument some would have with using or not using MVC to refer to web application architecture is defining what "application" means.
MVC really does originate from the SmallTalk GUI world, and from other windowing systems (GUIs) such as SunView, XView and NeWS (all Sun Microsystems products), and subsequently Apple, X Windows and Microsoft Windows. In that world, MVC shines, as it's critical to keep GUI widget states in sync with user input. Event loops rule.
But the GUI is not an application. It's merely used as the avenue by which the user interacts with the application.
I think MVC is fine for building most things it's used to build, but the bigger issue (which relates to what you're saying), is that it should be "fat models, skinny controllers", whereas the default behaviour, unless it explicitly advised against, is "skinny models, fat controllers".
As you said, controllers really should just be for the back and forward communication, business rules themselves should exist in the models. One problem here is a lot of MVC frameworks out of the box don't distinguish between a model as a row in the database, and a model as the table itself–and all the business rules around it.
But it's pretty easy to solve a lot of the time by adding a manager layer, which sits between the controllers and the models (models as a row entities).
Typically you'll have one manager class for each major model, and the manager is mostly a bunch of static methods (it shouldn't need much state), for getting and setting models in line with your business rules.
Agree with most of what you wrote, just that I consider your "Manager class" to be yet another model. Non persistent to database, but persistent throu hardcoding. Basically models of the business rules that connect the models of the data. It is really sad that MVC frameworks restricted people's idea of those M, V and C concepts to specific classes.


10-5 down at halftime, Liquid needed some big performances to gain a foothold in their match against Tyloo. Fortunately for the American side, their opponents weren't expecting to find Nicholas "nitr0" Cannella tucked away in the back corner of Cobblestone's A bombsite. After two of his allies fell, nitr0 revealed his inner 007, hitting a series of deft USP headshots to keep Team Liquid in the round. Pistol rounds in CS:GO can often seem messy and chaotic, with terrorists swarming over bombsites in a hail of gunfire. Composed and collected, nitr0's well-placed headshots were the perfect antidote to a cacophony of glocks.


11/5/2018 · Entry, TP & SL (FREE) Trading Journals. Forex Factory. Home Forums Trades News Calendar Market Brokers Login Entry trade EA & OCO 1 reply. order entry & modification methods 0 replies. Fight with others or myself Forex Factory® is a brand of Fair Economy, Inc.
8/28/2015 · For instance, if the TP mentioned in the brokers MT4 account is 100 pips and the TP on the EA is set 80%, then the TP would actually be 80 pips and as such the EA will calculate dynamic TP and SL levels depending on the TP and SL mentioned on the MT4 terminal for each currency pair.
Unload the EA and put SL and TP lower (20 - 40 pips) on the opening position, or close all of the opening position even if its negative, and start to load the EA again according to the major trend when I see the major trend is clear.
If your trade has real SL/TP then Stealth EA will create hidden SL/TP which will be 80% of the real SL/TP size. You can adjust that size too. For example, if real SL is 50 pips and TP is 100 pips the hidden SL will be 40 pips and hidden TP will be 80 pips.
Automatic TP and SL MT4 EA free download special Forex trading robot by Taniforex in Hindi and Urdu. No need for Manuel stop loss and take profit just add in setting and click on auto trading button.
5/31/2016 · Stop loss and take profit is very important in forex trading. This video showing how to use this. Skip navigation How to use TP and SL in forex trading Forex learning with Hadi Kashif.
Ea Forex Hidden TP SL. February 15, 2019 Written by Trader Forex "Have you skilled an absolute deal (positive deal that's nevertheless flow over TP) nevertheless in the future turn into a dropping deal? In the event the option is usually without a doubt, you have to pick the following EA.
Pada halaman ini saya ingin berbagi koleksi robot forex (EA). semua koleksi robot Forex ini bisa anda download secara gratis. untuk mengetahui performa robot forex ini, sebaiknya di Test dahulu pada Account Demo. selama news belum rilis maka SL dan TP akan di modif terus.. nah ketika news dirilis SL dan TP tidka akan di modif..


Company - About Sundial Limited, Inc.
Sundial Limited, Inc. is a family owned business specializing in Professional Automotive Aftermarket Products and Services. Our corporate headquarters and main warehouse is in Tampa, Florida, and we have been servicing dealerships, car washes and details shops since 1985. Sundial currently conducts business via three main departments: Dealership Services, Reverse Osmosis Water Systems, and Wholesale Chemical Sales. Sundial's President, Robert Procida, has been involved in the Automotive Industry since the early 1970's in numerous capacities ranging from General Manager of an Automotive Dealership to Factory Authorized Representative for numerous OEM's.
Over the past two plus decades, Sundial has been involved in all manner of dealer services to include staffing and managing aftermarket departments and dealership detail shops. Presently, Sundial manages staffs and operates the detail shop and lot vehicle cleaning services for the nation's largest single point RV dealership, Lazy Days. Sundial has been a vendor partner with Lazy Days for over fourteen years. Through this relationship and area of business, Sundial remains on the cutting edge of vehicle care chemicals, products and processes. Sundial leverages this knowledge and experience for its most valuable asset, its customers. Click Here to Contact Sundial.
If your business involves the sale or maintenance of automobiles, recreational vehicles, motorcycles, ATV's, or watercraft, Sundial has products and services to benefit you and your customers.


So, What's the Deal with Voting at Grand Convention?
Will you serve as a Voting Delegate at Grand Convention this summer in Hollywood? Have you ever wondered more about how and what voting occurs at Grand Convention? Well, let's answer your questions! Convention is an incredible time of learning, fun, and sisterhood but also a time to conduct the business of the Sorority as we prepare for the future.
Grand Convention is held every two years during odd-numbered years. International Officers, past Grand Council members, Chapter Presidents, and one delegate from each Chapter Advisory Board, Alumnae Association, and House Corporation Board in good standing and in attendance at Convention serve as Voting Delegates during the Convention business meetings. These delegates elect the members of Grand Council, who serve for the next biennium, and vote on amendments to the sorority's Bylaws and proposed Resolutions. All Alpha Delta Pi members are invited to attend Convention, but only the voting delegates (mentioned above) may vote.
A process known as "credentialing" is required for delegates voting on behalf of a Chapter Advisory Board, Alumnae Association, or House Corporation Board. A memo will be sent to these delegates in early May by the Convention Marshal with specific instructions on getting credentialed. This process is quite simple, but it does require the completion of an affidavit form to be notarized confirming that the individual is indeed in good standing and eligible to vote on behalf of that particular entity. Credentialing is not required for International Officers, past Grand Council members, or Chapter Presidents.
All voting delegates should have received a memo from the Bylaws and Resolutions Committee and the Nominating Committee on Thursday, April 13th which included proposed amendments to the Bylaws of Alpha Delta Pi Sorority and proposed resolutions as well as nominations for election to Grand Council of Alpha Delta Pi. Voting delegates are highly encouraged to take time prior to Grand Convention to study the materials and share the information with other sisters so that our officer selection and bylaws review process continues to have the benefit of a well-informed electorate that enhances the efficiency and quality of the process. Hard copies of these materials will not be provided on site at Convention, so print them in advance if you'd like a hard copy! You can find all proposed amendments and Grand Council candidate profile sheets on the website.
All Convention attendees will have an opportunity to learn more about each Grand Council candidate prior to elections at a Town Hall "Meet the Candidates" meeting where the candidates will answer questions posed by the membership. A Bylaws Review session will be held on the first day of Convention to provide attendees an opportunity to ask questions about the amendment process and individual amendments. The Bylaws and Resolutions Committee and a certified parliamentarian lead this session. The parliamentarian is available for individual questions at the beginning of each day. Questions can also be asked during the business meeting as each amendment and resolution is considered and discussed.
Voting delegates are expected to attend all business meetings during Convention.
During the meetings, voting delegates will sit in assigned seats with non-voting Convention attendees seated in the back.
All attendees must abide by the Convention rules, which shall be read and adopted at the start of the first business meeting. The Convention Marshal ensures all are complying with these rules.
The voting delegates should listen carefully to all discussion and then vote as she feels is best for the future of the sorority, based on her Chapter/Alumnae Association/House Corporation's wishes, as well as what she learns at Convention.
The delegates should report the result of the elections, Bylaws amendments and resolutions to her Chapter/Alumnae Association/House Corporation and ensure all members understand how the changes will affect each individual or entity.
So, that's the voting process in a nutshell! It's a big job and an important responsibility. Come prepared to Grand Convention and you'll do a fantastic job representing our sisterhood!


text:
Q: Remove link before another link I got some problems at that website . When I try to submit my links is : yyy.com . It will auto get http://xyzz.com/http://yyy.com . I try to use ../../ and ; %00 but it can't .
I can't edit code or anything . I only can submit text or link . Thanks you !

A: start your link like this:
http://

redpajama_set_name: RedPajamaStackExchange


text:
Q: jquery calendar datepicker does not work with my include php I met some trouble while using input type dates, also I decided for reasons of compatibility to change all input type date by type of text using class datepicker.
When I'm on index.php everything works fine.
When I'm on an other page for example index.php?p=home. Even if it displays the same page as index.php no calendar does appear.
Here is the code I use for changing the input.
<body onmousemove="resetTimer()" onload="startTimer();startTime();<?php if(isset($_GET['p']) AND $_GET['p']=='monitoring'){echo 'ajax();' ;}; ?>changefield()">
<!-- Script DATE  -->
<script>
    $(function() {
        $("input[type=date]").replaceWith("<input type='text' class='datepicker'/>");
        $( ".datepicker" ).datepicker({
            changeMonth: true,
            changeYear: true,
            showWeek: true,
            beforeShowDay: '',
            showAnim: "show"
        });
    });
</script>

I really do not know how to find an issue to this problem.
Receive all my utmost Respect.
Kind Regards.
SP.

A: Your code should work...
jsfiddle
maybe you don't include the jquery-ui script ?

A: You have a typo for starters:
A`ND $_GET['p']=='monitoring'


Specialist foot pedals designed for hands-free dictation.
Hands-free dictation made simpler with the use of foot pedals.
This ergonomic foot pedal has been specifically designed by G2 Speech to meet the demanding pathology environment. The pedal is fully operable with the feet. This allows the user to have both hands free for macroscopic examination. The pedal is waterproof and easy to use.
Facilitates all necessary dictation functionalities.


text:
WELCOME BACK WOODLAND!
Drop off time begins at 7:35 am, Bell rings at 7:50 am. Pickup is at 3:25 pm.
For general school information, please Click here to email!
For enrollment information, please Click here to email!
We look forward to seeing everyone Tuesday, September 6 for our first day of school!
Waldorf Education in a Public Setting
Policies, Notices, & Reports
Life at WCS
Our School Gallery
Rob Everett
(Dragonfly Class)
Rob Everett joined Woodland Charter School as the Class Teacher for the Applegate River Class in July, 2016, having worked at East Bay Waldorf School previously as a Spanish Teacher for four years. Rob has a master's in Education from University of the Pacific, a B.A. in Latin American Studies from UCLA where he graduated with honors, and Waldorf certification from Gradalis. Rob worked for years in youth development with under-served populations in Southern California, San Francisco, Sonoma County and Portland, Oregon; in outdoor education as a guide for sea-kayaking, rafting and backpacking; and as a Program Director for a non-profit running outdoor adventures for people living with HIV.
Woodland Charter School, tuition-free and open to all students, is part of a worldwide movement to make Waldorf educational philosophy more accessible by bringing it to the public school system.
2022-2023 WCS Calendar
301 Murphy Creek Rd,
office@woodlandcharterschool.org
Copyright 2019 Woodland Charter School | All Rights Reserved | Designed by Idyllwild

redpajama_set_name: RedPajamaCommonCrawl


text:
Board member resignation at Biomarin raises questions, among them a possible buyout (BMRN)
(first reported at footnoted.org)
Biomarin (BMRN) released some back-and-forth between the company and resigning board member Joseph Klein.
In his resignation letter, Klein claims his efforts were unappreciated, especially in regards to internal audit investigations and dealings with management.
The market is sending shares higher today on buyout speculation, but what caught my interest was the disagreements over depreciation timetables.
There exists disagreement between the Board and me on my view of a number of issues as I learned from colleagues on the board. The following are some examples:
Disagreement over How and When I ask questions as Chairman of the Audit Committee. Specific examples cited were (a) question on revenue recognition of a shipment to a Japanese distributor was asked in the presence of the external auditor and the entire finance team; and (b) question on extension of lives for fixed asset depreciation was asked in the presence of the external auditor and the entire finance team. These questions were viewed as "inappropriate" and "micromanaging the audit committee process."
The company reports Depreciation of about $5.8million per quarter. If this had to be increased, then it would reduce GAAP earnings per share. Earnings for this quarter are expected to be zero, and next quarter the estimate is one cent. Any boost to Depreciation would put both of these estimates into the red, which (to a cynic!) could be reason enough for a management to keep Depreciation inappropriately low...
Judging from this letter, Klein is looking out for shareholders by keeping management accountable (keeping separate the chairman and CEO positions), as well as watching out for inappropriate poison pills (anti-takeover measures).
Disagreement over How to Conduct an Ongoing Investigation of a Serious Matter. While I still do not believe there has been any wrongdoing by the company and an investigation of an alleged violation is ongoing, there were some disagreements about how to conduct an independent investigation and, in my opinion, management has influenced both the direction and conduct of the investigation. My suggestions about the investigation process were viewed as "micromanaging the audit committee process."
Disagreement over How to Modify the Company's Poison Pill. When asked, I was in favor of removing the poison pill, but then compromised my position by suggesting we establish an automatic sunset provision, which would force regular evaluation of the Poison Pill to determine if it was in the best interest of the shareholders.
Disagreement with the CEO on How and When the CEO should present to our entire Board a serious, reasonable offer by a third party to acquire the company. I continue to believe that the CEO should present any serious offer that he has received to acquire the company to the full Board so that the full Board can determine what is in the best interests of our shareholders. In my opinion, these discussions should be by the entire Board in a duly-noticed board meeting, and not in selective one-on-one telephone conversations or emails.
Disagreement with the CEO over his Desire to Combine the Chairman and CEO Roles. I continue to believe that BioMarin's existing practice of having a Chairman that is separate from the CEO represents best practice in corporate governance and is in the best interest of our shareholders.
Below are a few portions of the company's response:
Disagreement Regarding How and When Mr. Klein Asked Questions as Chairman of the Audit Committee
While members of the Board have raised the issue of the appropriateness of the manner and timing of certain questions previously asked by Mr. Klein, these comments were made solely in the context of Mr. Klein raising these issues and asking these questions when the directors were in meetings where junior personnel of the Company were in attendance. The Board requested that Mr. Klein refrain from asking questions or raising sensitive issues at these meetings and that he instead raise them first in meetings with senior management or other directors or in executive session with the independent auditors. None of the other Board members took issue with the substance of the questions, but rather the appropriateness of asking such questions in the presence of certain junior personnel. The other directors believe that these were legitimate requests to make and that Mr. Klein, as the Chairman of the Audit Committee, should understand that he should follow the proper procedure and channels for discussing issues among the Board. On several occasions, dating back months before March 2010, Mr. Klein acknowledged that some of his comments and questions were made in an inappropriate context and that he should be mindful of the problems that such behavior could cause. However, in connection with deliberating on Mr. Klein's nomination, the Board found at the March 15, 2010 meeting that this conduct had not been remedied appropriately over the past year and was continuing to interfere with constructive Board meetings.
Disagreement Regarding How to Conduct an Ongoing Investigation Regarding a Serious Matter
The Company disagrees with Mr. Klein's characterization of the ongoing preliminary investigation of a matter by the Audit Committee. The Audit Committee believes it has fulfilled and is continuing to fulfill all of its obligations in handling this preliminary investigation and has taken its responsibilities regarding the potential matter seriously. Although the preliminary investigation is ongoing, the Audit Committee has not to date developed any evidence that a violation of law has occurred. In the course of an investigation not related to the matter referenced in the Resignation Letter, the Company discovered an email that contained a statement that the Audit Committee believed required serious inquiry to determine the meaning of such statement as it related to the fact that a third party agent of the Company may have engaged in potential misconduct. In seeking to understand the nature of the
context in which any allegation of potential misconduct may have occurred, the Audit Committee (with the participation and affirmative vote of Mr. Klein) determined to first conduct a preliminary investigation with the supervision of outside counsel to evaluate whether the circumstances surrounding the email warranted a full investigation. Mr. Klein participated in every significant decision about the conduct of the preliminary investigation and noted his agreement with each of these decisions. The Audit Committee and the Board are still evaluating the information and have not yet made a determination as to whether or not to initiate a full investigation into the matter. The Company is taking the matter seriously and believes that the current direction and conduct of the preliminary investigation is appropriate based on the information available at this time. Moreover, the Board disputes Mr. Klein's premature characterization of the work to date of the Audit Committee as a full and formal investigation or that a serious matter to be investigated has occurred.
Disagreement Regarding How to Modify the Company's Poison Pill
The Board disputes Mr. Klein's characterization that a discussion among Board members regarding whether a stockholder rights plan should be adopted and if so, what provisions should be contained in the plan, constitutes a disagreement with the Board that forms the basis of his resignation. The Board believes that discussions prior to adoption as to different provisions to be contained in a stockholder rights plan is common among directors. The existing stockholder rights plan was approved in February 2009 by the Board by a vote of 7-0. Mr. Klein attended a prior meeting where the plan was discussed, but, although he received appropriate notice of the meeting, was unable to attend the meeting when the plan was approved due to a scheduling conflict. Moreover, the Board cannot reconcile how the changes to the Company's stockholder rights plan could be deemed to be a disagreement that ultimately caused Mr. Klein to resign since the Board made the decision in February 2009 and Mr. Klein continued to serve as a director for over a year following the adoption of the Company's existing stockholder rights plan.
Disagreement with the CEO Regarding How and When the CEO Should Present Reasonable Offers by a Third Party to Acquire the Company
The Company disputes Mr. Klein's assertion that Mr. Bienaimé, the Company's Chief Executive Officer, received a bona fide offer from a third party and failed to share this offer with the Board for consideration. The Company has never received any such offer while Mr. Bienaimé has been Chief Executive Officer and the Company has not engaged in a sale process or the evaluation of similar strategic alternatives as the Board believes that the best course of action to maximize long-term stockholder value is to execute on the Company's long-term business plan as an independent entity. The Board and management of the Company well understand and acknowledge their obligations under Delaware law regarding third party offers.
Disagreement with the CEO over his Desire to Combine the Chairman and CEO Roles
The Company disputes Mr. Klein's characterization of the issue of whether to combine the Chairman of the Board and Chief Executive Officer roles as a disagreement with the Chief Executive Officer or the Board. As part of its regular review of the roles and positions held by the directors of the Company, including the position of Chairman of the Board, memberships on the committees of the Board, and the scope of responsibility for the Chief Executive Officer, the Corporate Governance and Nominating Committee (including Mr. Klein) has discussed whether the Chief Executive Officer can also hold the position of Chairman of the Board. The members of the Corporate Governance and Nominating Committee have to date unanimously determined that the current Board governance structure separating the Chairman of the Board and Chief Executive Officer roles continues to be appropriate at this time. The matter was never raised to the full Board and the Chief Executive Officer was not involved in the discussion at any Corporate Governance and Nominating Committee meeting. The Board does not believe that its position is contrary to Mr. Klein's view that the offices of Chief Executive Officer and Chairman of the Board should be held by different persons, so the Board is unable to reconcile how Mr. Klein's view forms a valid basis for his resignation.


We installed my new Recluse Core EXP 3.0 into my 2017 KTM 250 XC-W this evening (the bike has 8 hours on it). We followed the instructions to the letter. When it came to choosing which friction plates to use with the clutch plates, we need to use one (1) of the thinner ones to get it into spec (truthfully we were a hair over spec, otherwise we were under and outside of the range by a greater amount than we were over). Installed the rest of the system, Slave, etc. Fired up the bike and found our 1/8' of an inch movement in the clutch at a mid throttle blip. Put the bike in gear and let our the clutch in first gear. The bike was kinda lurchy, and jumping trying to roll forward... I could hold it back with my legs, but it wanted to go on it's own. We adjusted the slave, and were only able to make it either jump and lurch forward a little less, and engage when rolling on the throttle, OR back it off enough that the bike didn't want to roll out without throttle, but when giving it gas it wouldn't roll forward.... we couldn't find a sweet spot where it wouldn't want to pull forward on it's own, and engage when on the gas. Now, if I put it in 2nd gear I can find that sweet spot, and it behaved as I expected it to.
Is the term for this "dragging"??
So is this lurching not normal? When you're in 1st gear, clutch out at a stand still your bike doesn't want to lurch forward? Not even a little bit?
The backing off the adjustment should make the issue you described worse and the bike should pull as normal without the AC. I would review the initial slave setup and get the bike to or close to normal operating temp. Mine does drag a little too much when cold but is great when the bike is warmed up.
1st gear is really low, so just the drag from oil between plates is enough to want to propel the bike.
What oil are you running?
Something else we just realized... the black ring that holds the clutch pack in place (the ring that has the " I, II, and III" marked on it) was installed in the II position... not the III position like indicated (not sure why we did that?). Could that have an effect on things?
Yes. Use the position prescribed in the Rekluse install instructions. Rekluse also recommends a specific oil to run.


text:
ManagementToday
35 Women Under 35
Britain's Most Admired Companies
Reputation Matters
BSkyB is no more as Sky completes £7bn European takeovers
The 'British' and 'Broadcasting' have been exorcised from Rupert Murdoch's new pay TV leviathan.
by Rachel Savage
BSkyB is dead. All hail Sky. Rupert Murdoch's newly-enlarged pay TV empire is dropping the 'British' and 'Broadcasting' from its name after completing the £7bn double acquisition of Sky Deutschland and Sky Italia.
The company is also changing its stock market ticket from BSY to SKY, subject to shareholder approval at its AGM next week, to reflect the spreading of its tentacles across the continent and the shift from traditional TV broadcasting to watching online and services like broadband.
The enlarged entity is staying listed in London, with Jeremy Darroch, the boss of the British arm, taking charge of the whole thing. Deutschland and Italia chief execs Brian Sullivan and Andrea Zappa, both ex-BSkyBers will stay at the helm of their respective enclaves.
Of course, the whole deal is Murdoch merely shifting one part of his empire to the other, with the cash originally intended to fund his aborted $80bn (£50.7bn) move for Time Warner. Sky bought the 57% of Sky Deutschland and whole of Sky Italia owned by 21st Century Fox for €3.6bn (£2.8bn) and £2.45bn respectively. It snaffled up a further 33% of the German business from minority shareholders, most of that for €6.75 a share. And Sky is still 39% owned by - wait for it - Fox.
'It's not about the UK taking over, it is about bringing the three Skys together,' Darroch told the Telegraph. A likely story, given 25,000 of the enlarged company's employees are in the UK. Moreover, the British part's annual revenues of £7.6bn are more than three times that of Sky Italia and almost six times Sky Deutschland's. But MT is nonetheless sure the media megatron will be one big happy Murdoch family.
Email: mtsupport@haymarket.com
Up to 4 free articles a month
Get 30 days free access
Sign up for a 30 day free trial and get:
Full access to managementtoday.co.uk
Exclusive event discounts
Management Today's print magazine
Growing businesses
Future business
Any other business
Get our bulletins in your inbox
RegisterFind out more about our daily and weekly bulletins


text:
Mets right-hander Pedro Martinez, making his first start of the season, whiffs Reds hurler Aaron Harang to become the 15th major league pitcher to record 3,000 career strikeouts. The three-time Cy Young winner has missed most of the season recovering from rotator cuff surgery.
Sep 3, 2007 | This Day In Baseball |
On September 3, 2007 — Mets right-hander Pedro Martinez, making his first start of the season, whiffs Reds hurler Aaron Harang to become the 15th major league pitcher to record 3,000 career strikeouts. The three-time Cy Young winner has missed most of the season recovering from rotator cuff surgery.
Subscribe to This Day In Baseball
Get our latest Posts in your in box
Support This Day In Baseball on Patreon
Baseball Reference September 3
National Pastime
Retro Sheet
SABR Games Project
Replay The Game
Previous2007 – In a 5 – 3 win by the Orix Buffaloes, Tuffy Rhodes and Greg LaRocca both make history. Rhodes cracks his 400th home run, the 14th player and first foreigner in Nippon Pro Baseball history to reach that mark. LaRocca is plunked for the 23rd time this year to set a new Pacific League record.
Next2007 – Francisco Cordero saves his 40th game. This sets a new Milwaukee Brewers record for a season, topping the mark shared by Danny Kolb and Derrick Turnbow.
In the last game of the season, Pensacola Blue Wahoos shortstop Ray Chang plays all nine positions, fielding a different one in each of the first nine innings, including tossing a clean ninth frame. The 32 year-old popular infielder also enjoys a 3-for-4 day at the plate, scoring a run and stealing a base in the Reds Double-A affiliate's 4-2 loss against the Mobile BayBears.
The Mariners and Red Sox finalized their trade that brings Casey Kotchman to Seattle in exchange for outfielder Bill Hall, a player to be named, and cash. The M's acquisition of the 26 year-old slick-fielding first baseman signals the departure of free-agent slugger Russell Branyan, who suffered from a disc issue in his back late in the season last year.
1959 – The Pirates take a doubleheader form the Dodgers, beating Don Drysdale in both games. As a starter, Drysdale loses the opener, then relieves in game 2. In the 10th inning, with runners on first and third and two out, Drysdale hands out an intentional pass to get to Dick Groat, who singles in the winning run.
The Boston Doves and Philadelphia Phillies combine for a major-league record fewest at-bats by two teams in a nine-inning game: 48 (25 for the Doves, 23 for the Phils). Boston wins, 3 – 0. The mark will be tied next year and topped in the American League in 1964.


text:
Con O'Callaghan: 'Gavin drives our winning culture'
Jake O'Donnell
02:13 2 Nov 2019
All-Star Con O'Callaghan says the Dublin squad are delighted that Jim Gavin is set to stay on as manager of the five-in-a-row winning team.
Gavin had remained tight-lipped on his future ever since clinching a sixth All-Ireland title as manager, fuelling speculation that he was ready to step away from the Dublin inter-county side.
O'Callaghan spoke to Off The Ball's Will O'Callaghan after receiving his second All-Star in Dublin on Friday night and noted the importance of Gavin to the Dubs' success.
"What he has put in place it's not just a one or two-year thing that he has done," the 23-year old explained.
"He's been there six or seven years now and that culture – he doesn't like to admit it – but he's driving the whole thing from behind the scenes, so we are obviously delighted he's staying around."
However, the Cuala clubman added that Gavin's success is also a product of the team that he has built around him at Dublin.
"It's not just him, there is a brilliant background staff with Dec Darcy and Jason [Sherlock] and even Shane O'Hanlon.
"There are so many people, again you wouldn't see them in the media or on matchday but their contribution is massive to the team. Yeah, he has a really great group behind him as well."
"He doesn't like to admit it, but he's driving the whole thing from behind the scenes."
Dub All-Star Con O'Callaghan has been speaking to @willocallaghan about the importance of Jim Gavin staying on as manager and the influence of FOTY Stephen Cluxton🔵 pic.twitter.com/4WgxlDNuZw
— Off The Ball (@offtheball) November 2, 2019
While O'Callaghan had been one of the standout players of Dublin's historic campaign, it was Stephen Cluxton who was awarded Footballer of The Year, an award that O'Callaghan said was well-deserved for the veteran captain.
"I think he made his debut 18 years ago I was only five or whatever and even to be able to watch him. Even when Dublin weren't half as strong as they are now he was still incredible. The level of consistency he brings to training, to matches, his analysis: it's incredible. So, it's well deserved."
All-Stars Con O'callaghan Dublin GAA Jim Gavin
Callanan and Cluxton win Hurler and Footballer of the Year awards
20:20 1 Nov 2019 4 min read
All-Stars who didn't make the final
13:06 30 Aug 2019 4 min read
'Three of us won an All-Star and we were living together' | Paul Flynn on college football


text:
Corner Store Cinema
Can't make it to the theatre? Try the checkout counter instead.
What is Corner Store Cinema?
Lonely Hearts (2006) review- A sleepy lead performance from Travolta drags down an otherwise solid film noir
Kyle Darbyson	Blog, Reviews	 February 7, 2019 4 Minutes
As an industry, Hollywood is collectively guilty of many story-telling sins, like the tendency to over-romanticize important people, places, and things.
From botched biopics to anachronistic period pieces, the American film business has shown time and time again that it will go to great lengths to prune away the more unseemly elements of historical fact in favour of presenting a digestible narrative for general audiences.
Even violent criminals will sometimes get this treatment, since films like Bonnie and Clyde (1967) are still considered classics to this day despite being riddled with inaccuracies.
However, my general rule of thumb is that these white lies are forgivable as long the filmmaking behind them is solid, which is why Lonely Hearts (2006) works as a detective story despite the creative liberties its writer/director takes with the source material.
This movie's plot follows the exploits of the "Lonely Hearts Killers," a real-life pair of serial murderers who, from 1947 to 1949, lured as many as 20 women to their deaths through answering their personals ads.
While Jared Leto and Salma Hayek are saddled with portraying Raymond Fernandez and Martha Beck (the killers), John Travolta also stars as a hardboiled detective tasked with tracking the couple down. Of course, like any good film noir, this case is never as simple as it seems and Travolta's ability to bring the killers to justice is always being complicated by his own personal demons.
Lonely Hearts actually serves as a great example of why I'm not so anal about historical accuracy in film, since one its strongest elements is a blatant fabrication on behalf of the filmmakers.
Hayek's performance as the Martha Beck is completely unnerving, terrifying, and full of surprises, especially when you realize that she is the architect behind a lot of the killings.
In fact, she's so good that I didn't even care that the real-life Beck was an overweight, homely white woman, who would have never been able to slip into the skimpy cocktail dresses that Hayek fills out so nicely in this film.
While Leto is a little more willing to look like Raymond Fernandez (receding hairline and all), he's also able to mix devilish charm with crippling insecurity, which makes him the perfect bait to attract a parade of desperate, lonely women.
And even though the two are playing remorseless serial killers, Leto and Hayek still manage to develop some compelling chemistry similar to other famous outlaw couples in popular culture, like Sid Vicious and Nancy Spungen or (more fittingly) the Joker and Harley Quinn.
Now, are the filmmakers guilty of making us sympathize with a pair of degenerates who caused a lot of pain and suffering in real life? Maybe. But the movie's unflinching look at the brutality these two inflicted on their victims also doesn't let us forget that their relationship is rooted in fear and jealousy rather than love and trust.
However, the same level of praise can't be drummed up for Travolta's performance, since he largely sleepwalks his way through his lead role as a heartbroken detective without any real edge or enthusiasm.
He doesn't bring anything new to this well-worn character archetype, and can't even be bothered to delivery his lines properly a lot of the time.
In one scene, Travolta yells "Don't ever mention my wife again. It's none of your fucking business!" to a superior officer with all the squeaky bravado of a teenager going through puberty.
It also doesn't help that his partner is played by James Gandolfini, who acts circles around Travolta in virtually every scene they're in together.
This weak lead performance really takes the shine away from some of the film's finer qualities, since director Todd Robinson actually put a lot of work into creating a immersive atmosphere by littering the movie with tasteful tributes to classic film noir.
Not only is the soundtrack suitably jazzy and retro, but the grizzled voice-over narration by Gandolfini does a great job of setting the scene for a post-WWII America that is riddled with crime.
As the film's sole screenwriter, Robinson also sneaks in some nice character development for Travolta's character, whose quest to find meaningful intimacy mirrors Fernandez and Beck's homicidal love story.
It's too bad that Travolta's half-baked acting sticks out like a sore thumb, especially when everybody else in front of the camera (and behind it) is firing on all cylinders.
And while the filmmakers definitely play fast and loose with their "based on a true story" hook, Lonely Hearts still manages to retain the dysfunction and creepiness of its real-life subjects, which makes it a compelling watch for anyone who is a fan of serial killer dramas.
Just try not to get distracted by Travolta's bad acting, or his tough-guy toupee.
Corner store companion:
Hersey's Kisses (because if you're a movie nerd like me, chances are these are the only kisses you'll be getting on Valentine's Day).
Fun facts:
-Original release date:
April 30, 2006 (Tribeca Film Festival)
April 17, 2007 (limited release)
-Budget: $18 million (estimated)
-Box office gross: $2,517,423 (worldwide)
-Director Todd Robinson is the grandson of Elmer Robinson, the real-life detective (played by Travolta in this film) who investigated the Lonely Hearts murders in the late 1940s.
-Despite not being the same race as their real-life counterparts, both Leto and Hayek underwent slight cosmetic alterations to get into their roles. While Leto had to shave the front of his head to match Raymond Fernandez's hairline, Hayek wore contact lenses to replicate Martha Beck's blue eyes.
-The story of the "Lonely Hearts Killers" has been portrayed on film a total of four times. Besides Lonely Hearts, the story has been re-told in Mexican with Deep Crimson (1996), in French with Alleluia (2014) and in black and white with the American cult classic The Honeymoon Killers (1970).
Lonely Hearts Killers
Martha Beck
Raymond Fernandez
Published by Kyle Darbyson
This is my first time setting up a website, so give me a break, ok?	View all posts by Kyle Darbyson
Previous Post Lady Frankenstein (1971) review-This exploitation film is poorly stitched together, just like the monster itself
Next Post Another Midnight Run (1994) review-Flagrant false advertising


text:
10 must-visit covered bridges in Pennsylvania
Jim Cheney | Special to PennLive
10 Covered Bridges Near Harrisburg Worth Visiting
Did you know that Pennsylvania is home to more covered bridges than any other state? The roughly 200 historic covered bridges can be found all over Pennsylvania. And, while Lancaster County has the most, at 29, there are historic covered bridges to be found in more than half of the state's counties.
With so many covered bridges to choose from, how do you decide which ones to visit? To help, I've narrowed the list down to 10 covered bridges within two hours of the Harrisburg area that are a step above the rest. In my opinion, these bridges are the best of the best and are worth the drive to see.
Don't Edit
Academia Covered Bridge - Juniata County
Academia Covered Bridge stands out as not only one of the most beautiful bridges in the state, but also as the longest covered bridge remaining in Pa. The 270-foot-long bridge was built in 1903 and has been recently rehabilitated.
Today, the bridge is open to pedestrians and features several historical signs nearby. There is also a guestbook in the middle of the bridge for visitors to sign. The area surrounding the bridge is quite well-maintained and makes for a great visit.
Jim Cheney
East and West Paden Covered Bridges - Columbia County
Located in Columbia County off of Route 487, the dual bridges of East Paden and West Paden are two completely different structures that are often called the Twin Bridges. This is the only set of twin bridges in the United States. Despite being built using different architectural styles in 1850, the bridges work together to span the Huntington Creek.
West Paden is the longer of the two, at 115 feet, and was rebuilt after it was damaged by a flood in 2006. East Paden is 75 feet long and has only undergone minor repairs.
(Photo used courtesy of the Theodore Burr Covered Bridge Society of Pa.)
Sachs Covered Bridge - Adams County
Sachs Covered Bridge is not only of the most beautiful bridges in the state, but it's also the most historic. Built in 1854, the bridge spans 100 feet over Marsh Creek along the edges of Gettysburg National Battlefield.
During the Battle of Gettysburg, this bridge was used by both Union and Confederate forces, including during the Confederate retreat. The area around the bridge was the site of a hospital during the battle and was later the location of a triple hanging. Because of these events, it is a favorite of ghost hunters, and there are many reports of strange occurrences at this bridge.
Hassenplug Covered Bridge - Union County
Located near Mifflinburg, Hassenplug Covered Bridge is the oldest still-existing covered bridge in Pennsylvania. Built in 1825, the bridge is only a few months newer than the oldest bridge in the country. It spans 80 feet over Buffalo Creek.
The bridge is located in a nice wooded area just outside of town. A walking trail runs alongside the creek and provides a nice opportunity to explore the surrounding forests.
Rusty Glessner Photography
Packsaddle Covered Bridge - Somerset County
There are many beautiful covered bridges in the state, but few are more scenic than Packsaddle Covered Bridge in eastern Somerset County. What makes this bridge so special, in addition to the beautiful scenery around it, is the waterfall that runs underneath it. In fact, this is the only covered bridge in the state with a natural waterfall below it.
The bridge and waterfall are along Brush Creek. The bridge is 48 feet long and was originally built in 1870. There are very few covered bridges in Pennsylvania more beautiful than Packsaddle.
(Photo used courtesy of Rusty Glessner Photography)
Henninger Farm Covered Bridge - Dauphin County
There are two covered bridges remaining in Dauphin County, but the most scenic is located in a remote area in the northern part of the county, near Elizabethville. Henninger Farm Covered Bridge was originally built in 1850, and heavily reconstructed after an arson fire in 2000.
The bridge is no longer in use, but sits in a nicely landscaped area next to the road. The bridge still crosses 72 feet over Wisconisco Creek
Thomas Mill Covered Bridge - Philadelphia
Located in the Wissahickon Gorge area of Philadelphia, Thomas Mill Covered Bridge feels very removed from the city. However, it does still sit within the city limits, making it the only covered bridge remaining in a major American city.
Thomas Mill Covered Bridge crosses the Wissahickon Creek and was built in 1855. The bridge is 86 feet long. While there are many covered bridges in the state that are only accessible to those on foot, Thomas Mill is one of the few that requires a reasonable amount of hiking to reach. In fact, the closest parking area is roughly a 10 minute walk from this very scenic bridge.
Hall's Mill Covered Bridge - Bedford County
I visited Hall's Mill Covered Bridge on a bit of a whim while visiting other sites in Bedford County, but I'm very glad I made the trip. There is little doubt in my mind that Hall's Mill is one of the most scenic bridges in the entire state of Pennsylvania.
Hall's Mill Covered Bridge is set in a very rural part of the county and crosses 91 feet over Yellow Creek. It was built in 1872, but has clearly been refurbished the last few years. The open sides and white color make this a very unique looking bridge and well-worth visiting.
Bowmansdale Covered Bridge - Cumberland County
I may be a bit biased, having seen Bowmansdale Covered Bridge many times over my four years as a student at Messiah College, but I think it's one of the most beautiful in the state. Located over the Yellow Breeches, the bridge spans the border between Cumberland and York Counties, and has a unique setting amongst the buildings of the Mechanicsburg college. Bowmansdale also has the distinction of being one of the closest covered bridges to downtown Harrisburg.
The bridge was built in 1867 and is 112 feet long. It was originally located in Bowmansdale, but was moved to the college campus in the early 1970s.
Colemanville Covered Bridge - Lancaster County
Located in southwestern Lancaster County, near the borough of Pequea, is Colemanville Covered Bridge. Stretching high over the Pequea Creek, this bridge is quite striking. While there are certainly many more covered bridges in Lancaster County worth visiting, Colemanville stands out to me as being the most beautiful.
Colemanville Covered Bridge is 170 feet long and was originally built in 1856. It was completely rebuilt in 1992 and raised six feet so that it wouldn't be damaged by floods.
Finding the covered bridges
Use this map to find the covered bridges mentioned in this article.
Photo by John Martinec.
Learn more about the great places to visit in Pa.
Jim Cheney is the writer behind UncoveringPA, Pennsylvania's most read travel blog. He has traveled to nearly every county in Pennsylvania, and to many countries in North America, Europe, and Asia. He lives in Harrisburg, Pa.
Read more of his Travels with Jim columns, including his in-depth look at how a cave in western Pa. changed the course of human history as we know it. You can get to know Jim and why he loves to travel in Pa. in his introductory column.


text:
Q: Serving static files with NGINX for UNICORN served app I've just set up a Sinatra app running on Unicorn and served through a socket by NGINX.
I'm trying to get NGINX to serve my static assets with this in my nginx config:
upstream unicorn {
  server unix:/tmp/unicorn.app.sock fail_timeout=0;
}

server {
  listen 80 default;
  server_name localhost;
  root /home/ubuntu/app;

  location ^~ /public/ {
    root /home/ubuntu/app;
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

But my unicorn logs are still showing that it is serving the files
[03/Oct/2014 19:25:05] "GET /javascript/map.js HTTP/1.0" 304 - 0.0016
[03/Oct/2014 19:25:05] "GET /javascript/geopo.js HTTP/1.0" 304 - 0.0030
[03/Oct/2014 19:25:05] "GET /images/logo.png HTTP/1.0" 304 - 0.0022

etc.
What am I missing?

A: You'll want to explicitly tell the web server to load those files via a location directive.
Here's an example for what I use with Unicorn to have the web server load assets:
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
  root /home/ubuntu/app/public;
  expires max;
  add_header Cache-Control public;
  log_not_found off;
}