text:
import os
import json
import struct
import base64
import time
import copy
import logging
import ast

# third-party packages
import flatdict

import SolDefines
import openhdlc as hdlc
import hr_parser

# =========================== defines =========================================

OAP_PORT = 0xF0B9

# =========================== logging =========================================

log = logging.getLogger(__name__)

# =========================== helpers =========================================

# =========================== classes =========================================

class SolDuplicateOapNotificationException(Exception):
    pass

def version():
    import __version__
    return [int(v) for v in __version__.__version__.split('.')]

# ==== "chain" of communication from the Dust manager to the server

def dust_to_json(dust_notif, mac_manager=None, timestamp=None):
    """
    Convert a single Dust serial API notification into a list of JSON SOL Object.

    :param dict dust_notif: The Dust serial API notification as
        a json object created by the JsonServer application
    :param list mac_manager: A list of byte containing the MAC address of the manager
    :param int timestamp: the Unix epoch of the message creation in seconds (UTC)
    :return: A list of SOL Object in JSON format
    :rtype: list
    """

    notif_list  = _split_dust_notif(dust_notif)
    sol_jsonl   = []

    for d_n in notif_list:
        # get sol_mac
        if d_n['name'] in ['notifData', 'notifIpData']:
            sol_mac = d_n['fields']['macAddress']
        elif d_n['name'] in ['hr', 'oap']:
            sol_mac = d_n['mac']
        else:
            sol_mac = mac_manager

        # get sol_type and sol_value
        try:
            sol_type, sol_ts, sol_value = _dust_notif_to_sol_json(d_n)
        except SolDuplicateOapNotificationException:
            continue

        # get sol_ts
        if   sol_ts:
            pass # _dust_notif_to_sol_json() returned the ts (sol object with EPOCH ts)
        elif timestamp is None:
            sol_ts = int(time.time())  # timestamp in seconds
        else:
            sol_ts = timestamp

        # create JSON Object
        sol_json = {
            "mac":          sol_mac,
            "timestamp":    sol_ts,
            "type":         sol_type,
            "value":        sol_value,
        }
        sol_jsonl.append(sol_json)

    return sol_jsonl

def json_to_bin(sol_json):
    """
    Convert a JSON SOL Object into a single binary SOL Object.

    :param dict sol_json: a JSON SOL Object
    :return: A single binary SOL Object
    :rtype: list
    """

    sol_bin = []

    # header
    h     = 0
    h    |= SolDefines.SOL_HDR_V        << SolDefines.SOL_HDR_V_OFFSET
    h    |= SolDefines.SOL_HDR_T_SINGLE << SolDefines.SOL_HDR_T_OFFSET
    h    |= SolDefines.SOL_HDR_M_8BMAC  << SolDefines.SOL_HDR_M_OFFSET
    h    |= SolDefines.SOL_HDR_S_EPOCH  << SolDefines.SOL_HDR_S_OFFSET
    h    |= SolDefines.SOL_HDR_Y_1B     << SolDefines.SOL_HDR_Y_OFFSET
    h    |= SolDefines.SOL_HDR_L_ELIDED << SolDefines.SOL_HDR_L_OFFSET
    sol_bin        += [h]

    # mac
    if isinstance(sol_json['mac'], basestring):
        sol_bin += _format_mac_string_to_bytes(sol_json['mac'])
    else:
        sol_bin += sol_json['mac']

    # timestamp
    sol_bin        += _num_to_list(sol_json['timestamp'], 4)

    # type
    sol_bin        += _num_to_list(sol_json['type'], 1)

    # value
    if   sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRNEIGHBORS:
        sol_bin    += _get_sol_binary_value_dust_hr_neighbors(
            sol_json['value']
        )
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRDISCOVERED:
        sol_bin    += _get_sol_binary_value_dust_hr_discovered(
            sol_json['value']
        )
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HREXTENDED:
        sol_bin    += _get_sol_binary_value_dust_hr_extended(
            sol_json['value']
        )
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_SNAPSHOT:
        sol_bin    += _get_sol_binary_value_snapshot(
            sol_json['value']
        )
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_SNAPSHOT_2:
        sol_bin    += [ord(c) for c in str(sol_json['value'])]
    else:
        sol_bin    += _fields_to_binary_with_structure(
            sol_json['type'],
            sol_json['value']
        )

    return sol_bin

def bin_to_http(sol_binl):
    """
    Convert a list of binary SOL objects (compound or not)
    into a JSON string to be sent as HTTP payload to the server.

    :param list sol_binl: a list of binary SOL Objects
    :return: A JSON string to be sent to the server over HTTP.
    :rtype: string
    """

    try:
        return_val = {
            "v": SolDefines.SOL_HDR_V,
            "o": [base64.b64encode(s) for s in ("".join(chr(b) for b in sol_bin) for sol_bin in sol_binl)]
        }
    except:
        print sol_binl
        raise

    return_val = json.dumps(return_val)

    return return_val

def http_to_bin(sol_http):
    """
    Convert the JSON string contained in an HTTP request
    into a list of binary SOL objects (compound or not).

    :param string sol_http: JSON string contained in an HTTP request
    :return: list of binary SOL objects (compound or not)
    :rtype: list
    """

    sol_http = json.loads(sol_http)

    assert sol_http['v'] == SolDefines.SOL_HDR_V
    sol_binl = [[ord(b) for b in base64.b64decode(o)] for o in sol_http['o']]

    return sol_binl

def bin_to_json(sol_bin, mac=None):
    """
    Convert a binary SOL object into a JSON SOL Object.

    :param list sol_bin: binary SOL object
    :param list mac: A list of byte containing the MAC address of the that created the object
    :return: JSON SOL Objects
    :rtpe: list
    """

    sol_json = {}

    # header

    h     = sol_bin[0]
    h_V   = (h >> SolDefines.SOL_HDR_V_OFFSET) & 0x03
    assert h_V == SolDefines.SOL_HDR_V
    h_H   = (h >> SolDefines.SOL_HDR_T_OFFSET) & 0x01
    assert h_H == SolDefines.SOL_HDR_T_SINGLE
    h_M   = (h >> SolDefines.SOL_HDR_M_OFFSET) & 0x01
    h_S   = (h >> SolDefines.SOL_HDR_S_OFFSET) & 0x01
    h_Y   = (h >> SolDefines.SOL_HDR_Y_OFFSET) & 0x01
    h_L   = (h >> SolDefines.SOL_HDR_L_OFFSET) & 0x03

    sol_bin = sol_bin[1:]

    # mac

    if h_M == SolDefines.SOL_HDR_M_NOMAC:
        assert mac is not None
        sol_json['mac']  = _format_buffer(mac)
    else:
        assert len(sol_bin) >= 8
        sol_json['mac']  = _format_buffer(sol_bin[:8])
        sol_bin          = sol_bin[8:]

    # timestamp

    assert h_S == SolDefines.SOL_HDR_S_EPOCH
    assert len(sol_bin) >= 4
    sol_json['timestamp'] = _list_to_num(sol_bin[:4])
    sol_bin = sol_bin[4:]

    # type

    assert h_Y == SolDefines.SOL_HDR_Y_1B
    sol_json['type'] = sol_bin[0]
    sol_bin = sol_bin[1:]

    # length

    if h_L == SolDefines.SOL_HDR_L_WK:
        sol_item              = SolDefines.solStructure(sol_json['type'])
        obj_size              = struct.calcsize(sol_item['structure'])
    elif h_L == SolDefines.SOL_HDR_L_1B:
        sol_json['length']    = sol_bin[0]
        obj_size              = sol_bin[0]
        sol_bin               = sol_bin[1:]
    elif h_L == SolDefines.SOL_HDR_L_2B:
        sol_json['length']    = sol_bin[:2]
        obj_size              = sol_bin[:2]
        sol_bin               = sol_bin[2:]
    elif h_L == SolDefines.SOL_HDR_L_ELIDED:
        obj_size              = len(sol_bin)

    # value
    assert len(sol_bin) == obj_size
    if   sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRNEIGHBORS:
        sol_json['value'] = hr_parser.parseHr(
            [hr_parser.HR_ID_NEIGHBORS, len(sol_bin)]+sol_bin,
        )['Neighbors']
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRDISCOVERED:
        sol_json['value'] = hr_parser.parseHr(
            [hr_parser.HR_ID_DISCOVERED, len(sol_bin)]+sol_bin,
        )['Discovered']
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HREXTENDED:
        sol_json['value'] = hr_parser.parseHr(
            [hr_parser.HR_ID_EXTENDED, len(sol_bin)]+sol_bin,
        )['Extended']
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_SNAPSHOT:
        sol_json['value'] = _binary_to_fields_snapshot(sol_bin)
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_SNAPSHOT_2:
        value_str = "".join([chr(b) for b in sol_bin])
        value_eval = ast.literal_eval(value_str)
        sol_json['value'] = json.loads(json.dumps(value_eval))
    else:
        sol_json['value'] = _binary_to_fields_with_structure(
            sol_json['type'],
            sol_bin,
        )

    return sol_json

def json_to_influxdb(sol_json, tags):
    """
    Convert a JSON SOL object into a InfluxDB point

    :param dict sol_json: JSON SOL object
    :param dict tags: A dictionary of tags
    :return: InfluxDB point
    :rtpe: list
    """
    # tags
    obj_tags = copy.deepcopy(tags)

    # fields
    if   sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRNEIGHBORS:
        fields = {}
        for n in sol_json["value"]['neighbors']:
            fields["neighbors:" + str(n['neighborId'])] = n
        fields['numItems'] = sol_json["value"]['numItems']
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HRDISCOVERED:
        fields = sol_json["value"]
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_NOTIF_HREXTENDED:
        fields = {}
        for item, value in enumerate(sol_json["value"]['RSSI']):
            fields[str(item + 11)] = value # 11 is the first channel number
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_SNAPSHOT:
        fields = {"mote": []}
        for mote in sol_json["value"]:
            mote["macAddress"] = _format_buffer(mote["macAddress"])
            for path in mote["paths"]:
                path["macAddress"] = _format_buffer(path["macAddress"])
            fields["mote"].append(mote)
    elif sol_json['type'] == SolDefines.SOL_TYPE_DUST_EVENTNETWORKRESET:
        fields = {'value': 'dummy'}
    else:
        fields = sol_json["value"]
        for (k, v) in fields.items():
            if type(v) == list:  # mac
                if k in ['macAddress', 'source', 'dest']:
                    fields[k] = _format_buffer(v)
                elif k in ['sol_version', 'sdk_version', 'solmanager_version']:
                    fields[k] = ".".join(str(i) for i in v)

    f = flatdict.FlatDict(fields)
    fields = {}
    for (k, v) in f.items():
        fields[k] = v

    # add additionnal field or tag if apply_function exists
    try:
        obj_struct = SolDefines.solStructure(sol_json['type'])
        if 'apply' in obj_struct:
            for ap in obj_struct['apply']:
                arg_list = [fields[arg] for arg in ap["args"]]
                if "field" in ap:
                    fields[ap["field"]] = ap["function"](*arg_list)
                if "tag" in ap:
                    obj_tags[ap["tag"]] = ap["function"](*arg_list)
    except ValueError as err:
        log.warning(err)

    # get SOL type
    measurement = SolDefines.sol_type_to_type_name(sol_json['type'])

    # convert SOL timestamp to UTC
    utc_time = sol_json["timestamp"]*1000000000

    # fill "fields" if empty
    if not fields:
        fields = {'dummy': 'dummy'}
        log.warning("'fields' empty for object {0}".format(sol_json))

    sol_influxdb = {
            "time": utc_time,
            "tags": obj_tags,
            "measurement": measurement,
            "fields": fields,
            }

    return sol_influxdb

def influxdb_to_json(sol_influxdb):
    """
    Converts an Influxdb query reply into a list of dicts.

    :param dict sol_influxdb: the result of a database query (sush as SELECT * FROM)
    :return: a list of JSON SOL objects
    :rtype: list

    """

    # verify influxdb data
    if not ("series" in sol_influxdb):
        raise ValueError("Influxdb data not recognized")

    # init
    json_list = []

    # remove unused headers
    for serie in sol_influxdb["series"]:
        for val in serie['values']:
            # convert to dict
            d_influxdb = dict(zip(serie['columns'], val))

            # unflat dict
            obj_value = flatdict.FlatDict(d_influxdb).as_dict()

            # parse specific HR_NEIGHBORS
            hr_nghb_name    = SolDefines.sol_type_to_type_name(
                                SolDefines.SOL_TYPE_DUST_NOTIF_HRNEIGHBORS)
            if serie['name'] == hr_nghb_name:
                for i in range(0, len(obj_value["neighbors"])+1):
                    ngbr_id = str(i)

                    # new HR_NGBR parsing
                    if ngbr_id in obj_value["neighbors"]:
                        if obj_value["neighbors"][ngbr_id]["neighborFlag"] is None:
                            del obj_value["neighbors"][ngbr_id]

                    # old HR_NGBR parsing
                    if ngbr_id in obj_value:
                        if obj_value[ngbr_id]["neighborFlag"] is not None:
                            obj_value["neighbors"][ngbr_id] = obj_value[ngbr_id]
                        del obj_value[ngbr_id]

            # time is not passed in the "value" field
            del obj_value["time"]

            # create final dict
            jdic = {
                    'type': serie['name'],
                    'mac': serie['tags']['mac'],
                    'value': obj_value,
                    'timestamp': d_influxdb['time'],
                    }
            json_list.append(jdic)
    return json_list

# ==== file manipulation

def dumpToFile(sol_jsonl, file_name):

    with open(file_name, 'ab') as f:
        for sol_json in sol_jsonl:
            sol_bin = json_to_bin(sol_json)
            sol_bin = hdlc.hdlcify(sol_bin)
            sol_bin = ''.join([chr(b) for b in sol_bin])
            f.write(sol_bin)

def loadFromFile(file_name, start_timestamp=None, end_timestamp=None):

    if start_timestamp is not None or end_timestamp is not None:
        assert start_timestamp is not None and end_timestamp is not None

    if start_timestamp is None:
        # retrieve all data

        (bins, _) = hdlc.dehdlcify(file_name)

        sol_jsonl = []
        for b in bins:
            sol_jsonl += [bin_to_json(b)]

    else:

            #=== find start_offset

            while True:

                start_offset = None

                def one_object(offset):
                    (sol, offs) = hdlc.dehdlcify(file_name, fileOffset=offset, maxNum=1)
                    sol = sol[0]
                    sol = bin_to_json(sol)
                    return sol, offs

                def oneTimestamp(offset):
                    (osol, offs) = one_object(offset)
                    return osol['timestamp'], offs

                #=== get boundaries

                left_offset_start = 0
                try:
                    (left_timestamp, left_offset_stop) = oneTimestamp(left_offset_start)
                except IndexError:
                    # complete file is corrupted
                    return []
                with open(file_name, 'rb') as f:
                    f.seek(0, os.SEEK_END)
                    right_offset_start = f.tell()
                while True:
                    right_offset_start = _fileBackUpUntilStartFrame(file_name, right_offset_start)
                    try:
                        (right_timestamp, right_offset_stop) = oneTimestamp(right_offset_start)
                    except IndexError:
                        right_offset_start -= 1
                    else:
                        break

                if left_timestamp > start_timestamp:
                    start_offset = left_timestamp
                    break
                if right_timestamp < start_timestamp:
                    start_offset = right_timestamp
                    break

                #=== binary search

                while left_offset_stop < right_offset_start-1:

                    cur_offset_start = int((right_offset_start-left_offset_start)/2+left_offset_start)
                    (cur_timestamp, cur_offset_stop) = oneTimestamp(cur_offset_start)

                    if cur_timestamp == start_timestamp:
                        start_offset = cur_offset_start
                        break
                    elif cur_timestamp > start_timestamp:
                        right_offset_start = cur_offset_start
                    elif cur_timestamp < start_timestamp:
                        left_offset_start  = cur_offset_start
                        left_offset_stop   = cur_offset_stop

                if start_offset is None:
                    start_offset = left_offset_start

                break

            #=== read objects

            sol_jsonl = []

            curOffset = start_offset
            while True:
                try:
                    (o, curOffset) = one_object(curOffset)
                except IndexError:
                    # we have passed the end of the file
                    break
                if o['timestamp'] > end_timestamp:
                    break
                sol_jsonl += [o]

    return sol_jsonl

# ======================= private =========================================

def _split_dust_notif(dust_notif):
    """
    Split a single Dust serial API notification into a list of Dust notifications
    :param dict dust_notif: The Dust serial API notification as
                            created by the SmartMesh SDK
    :return: A list of Dust notifications
    :rtype: list
    """
    notif_list = []

    if (dust_notif['name'] == 'notifData') and (dust_notif['fields']['dstPort'] == SolDefines.SOL_PORT):
        # OAP: split if multi-MTTLV structure

        # parse header
        sol_header  = dust_notif['fields']['data'][0]
        header_V    = sol_header >> SolDefines.SOL_HDR_V_OFFSET & 0x03
        header_T    = sol_header >> SolDefines.SOL_HDR_T_OFFSET & 0x01
        header_S    = sol_header >> SolDefines.SOL_HDR_S_OFFSET & 0x01
        header_Y    = sol_header >> SolDefines.SOL_HDR_Y_OFFSET & 0x01
        header_L    = sol_header >> SolDefines.SOL_HDR_L_OFFSET & 0x03

        if header_T == 0:
            # single SOL object

            notif_list = [dust_notif]
        else:
            # multiple SOL objects

            # reset header Type bit
            sol_header = dust_notif['fields']['data'][0] & 0xdf

            # get structure size
            solheader_size  = SolDefines.SOL_HEADER_SIZE
            ts_size         = SolDefines.SOL_TIMESTAMP_SIZE
            objnum_size     = SolDefines.SOL_OBJNUMBER_SIZE

            # get time
            ts_sec  = 0
            ts_usec = 0
            ts_offset = 0
            if header_S == 0: # timestamp from smip header
                ts_sec  = dust_notif['fields']['data'][0:ts_size]
                ts_usec = 0
                ts_offset = ts_size
            else: # timestamp from dust notif
                ts_sec  = dust_notif['fields']['utcSecs']
                ts_user = dust_notif['fields']['utcUsecs']

            # get number of objects
            obj_number  = dust_notif['fields']['data'][ts_offset+objnum_size]

            curr_ptr    = solheader_size + ts_offset + objnum_size
            for i in range(0,obj_number):
                obj_type    = dust_notif['fields']['data'][curr_ptr]
                sol_item    = SolDefines.solStructure(obj_type)
                obj_size    = struct.calcsize(sol_item['structure'])
                notif_list += [
                    {
                        'manager': dust_notif['manager'],
                        'name':    dust_notif['name'],
                        'fields': {
                            'macAddress': dust_notif['fields']['macAddress'],
                            'utcSecs': dust_notif['fields']['utcSecs'],
                            'utcUsecs': dust_notif['fields']['utcUsecs'],
                            'srcPort': dust_notif['fields']['srcPort'],
                            'dstPort': dust_notif['fields']['dstPort'],
                            # data = solheader + timestamp + object
                            'data': [sol_header] +
                                dust_notif['fields']['data'][solheader_size:solheader_size+ts_offset] +
                                dust_notif['fields']['data'][curr_ptr:curr_ptr+obj_size+1]
                        },
                    },
                ]
                curr_ptr   += obj_size+1

    elif dust_notif['name'] == 'hr':
        hr_type_list = ['Device', 'Discovered', 'Neighbors', 'Extended']
        notif_keys = dust_notif['hr'].keys()
        for hrName in notif_keys:
            assert hrName in hr_type_list
        for hrName in notif_keys:
            dust_notif_copy = copy.deepcopy(dust_notif)
            for hr_type in [t for t in notif_keys if t != hrName]:
                del dust_notif_copy['hr'][hr_type]
            notif_list += [dust_notif_copy]
    else:
        notif_list += [dust_notif]

    return notif_list

# ==== dust notif to sol json

def _dust_notif_to_sol_json(dust_notif):

    sol_ts = None

    if   dust_notif['name'] == 'notifData':
        (sol_type, sol_ts, sol_value) = _dust_notifData_to_sol_json(dust_notif)
    elif dust_notif['name'] == 'hr':
        (sol_type, sol_value) = _dust_hr_to_sol_json(dust_notif)
    elif dust_notif['name'] == 'oap':
        (sol_type, sol_value) = _dust_oap_to_sol_json(dust_notif)
    elif dust_notif['name'] == 'snapshot':
        sol_type = SolDefines.SOL_TYPE_DUST_SNAPSHOT_2
        sol_value = dust_notif
    else:
        (sol_type, sol_value) = _dust_other_notif_to_sol_json(dust_notif)

    return sol_type, sol_ts, sol_value

# notifData

def _dust_notifData_to_sol_json(dust_notif):

    sol_type   = None
    sol_ts     = None
    sol_value  = None

    if   dust_notif['fields']['dstPort'] == OAP_PORT:
        # notifData contains OAP message

        # this notification will already appear as an oap notification
        raise SolDuplicateOapNotificationException()
    elif dust_notif['fields']['dstPort'] == SolDefines.SOL_PORT:
        # notifData contains SOL message

        sol_type, sol_ts, sol_value = _dust_notifData_with_sol_to_sol_json(dust_notif)
    else:
        # notifData contains does NOT contain neither OAP nor SOL

        sol_type  = SolDefines.SOL_TYPE_DUST_NOTIFDATA
        sol_value = copy.deepcopy(dust_notif['fields'])
        del(sol_value['macAddress'])
        del(sol_value['utcSecs'])
        del(sol_value['utcUsecs'])

    return sol_type, sol_ts, sol_value

def _dust_notifData_with_sol_to_sol_json(dust_notif):
    """
    Turn a notifData dust notification which contains SOL objects
       (SOL_header + timestamp + SOL_object)
    into a dictionnary

    :return: (sol_type, sol_ts, sol_value)
    :rtype: tuple(int, int, int)
    """
    sol_ts          = None
    # check for timestamp flag in SOL_HEADER
    header_offset   = SolDefines.SOL_HEADER_OFFSET
    ts_offset       = SolDefines.SOL_TIMESTAMP_OFFSET
    header_S        = dust_notif['fields']['data'][0] >> SolDefines.SOL_HDR_S_OFFSET & SolDefines.SOL_HDR_S_SIZE
    if header_S == SolDefines.SOL_HDR_S_EPOCH:
        ts = list(dust_notif['fields']['data'][ts_offset:ts_offset+SolDefines.SOL_TIMESTAMP_SIZE])
        ts.reverse()
        #sol_ts      = Sol._list_to_num(ts)
        type_index  = SolDefines.SOL_HEADER_SIZE + SolDefines.SOL_TIMESTAMP_SIZE
    else:
        type_index  = SolDefines.SOL_HEADER_SIZE

    sol_type    = dust_notif['fields']['data'][type_index]
    sol_value   = _binary_to_fields_with_structure(
        dust_notif['fields']['data'][type_index],
        dust_notif['fields']['data'][type_index+1:],
    )
    return sol_type, sol_ts, sol_value

# hr

def _dust_hr_to_sol_json(dust_notif):
    sol_type   = None
    sol_value  = None
    hr_type_list = ['Device', 'Discovered', 'Neighbors', 'Extended']
    for hr_type in hr_type_list:
        if hr_type in dust_notif['hr']:
            assert dust_notif['hr'].keys() == [hr_type]
            sol_type = getattr(SolDefines, "SOL_TYPE_DUST_NOTIF_HR{0}".format(hr_type.upper()))
            sol_value = dust_notif['hr'][hr_type]
    return sol_type, sol_value

# oap

def _dust_oap_to_sol_json(dust_notif):
    if dust_notif['fields']['channel_str'] == 'temperature':
        sol_type  = SolDefines.SOL_TYPE_DUST_OAP_TEMPSAMPLE
        sol_value = {
            'temperature': dust_notif['fields']['samples'][0],
        }
    elif dust_notif['fields']['channel_str'].startswith('analog'):
        sol_type  = SolDefines.SOL_TYPE_DUST_OAP_ANALOG
        sol_value = {
            'input':   dust_notif['fields']['input'],
            'voltage': dust_notif['fields']['samples'][0],
        }
    elif dust_notif['fields']['channel_str'].startswith('digital_in'):
        sol_type  = SolDefines.SOL_TYPE_DUST_OAP_DIGITAL_IN
        if "input" in  dust_notif['fields'] and "samples" in dust_notif['fields']:
            sol_value = {
                'input':   dust_notif['fields']['input'],
                'state':   dust_notif['fields']['samples'][0],
            }
        elif "channel_str" in dust_notif['fields'] and "new_val" in dust_notif['fields']:
            sol_value = {
                'input': dust_notif['fields']['channel'][1],
                'state': dust_notif['fields']['new_val'],
            }
        else:
            log.debug("Unknow format for sol type {0}. dust_notif={1}".format(sol_type, dust_notif))
    else:
        raise NotImplementedError()
    return sol_type, sol_value

# other

def _dust_other_notif_to_sol_json(dust_notif):
    sol_typeName    = _dust_notifName_to_sol_typeName(dust_notif['name'])
    sol_type        = getattr(SolDefines, sol_typeName)
    sol_value       = _fields_to_json_with_structure(
        sol_type,
        dust_notif,
    )

    return sol_type, sol_value

def _dust_notifName_to_sol_typeName(notifName):
    return 'SOL_TYPE_DUST_{0}'.format(notifName.upper())

def _fields_to_json_with_structure(sol_type, dust_notif):

    sol_struct          = SolDefines.solStructure(sol_type)

    returnVal       = {}
    for name in sol_struct['fields']:
        returnVal[name] = dust_notif['fields'][name]
        if name in ['source', 'dest', 'macAddress']:
            returnVal[name] = _format_mac_string_to_bytes(returnVal[name])
    if 'extrafields' in sol_struct:
        returnVal[sol_struct['extrafields']] = dust_notif['fields'][sol_struct['extrafields']]

    for (k, v) in returnVal.items():
        if type(v) == tuple:
            returnVal[k] = [b for b in v]

    return returnVal

def _fields_to_binary_with_structure(sol_type, fields):

    sol_struct      = SolDefines.solStructure(sol_type)

    pack_format     = sol_struct['structure']
    pack_values     = [fields[name] for name in sol_struct['fields'] if name in fields]

    # convert [0x01,0x02,0x03] into 0x010203 to be packable
    for i in range(len(pack_values)):
        if type(pack_values[i]) == list:
            pack_values[i] = _list_to_num(pack_values[i])

    # unpacking field by field
    returnVal = []
    for id, val in enumerate(pack_values):
        returnVal += [ord(b) for b in struct.pack(pack_format[0] + pack_format[id+1], val)]

    if 'extrafields' in sol_struct:
        returnVal  += fields[sol_struct['extrafields']]

    return returnVal

def _binary_to_fields_with_structure(sol_type, binary):

    sol_struct      = SolDefines.solStructure(sol_type)

    pack_format     = sol_struct['structure']
    pack_length     = struct.calcsize(pack_format)

    # unpacking field by field
    t = []
    ptr = 0
    for frmt in pack_format[1:]:
        size = struct.calcsize(pack_format[0] + frmt)
        if len(binary[ptr:ptr+size]) > 0:
            t.append(struct.unpack(pack_format[0] + frmt,
                                   "".join(chr(b) for b in binary[ptr:ptr+size]))[0])
        ptr += size

    returnVal = {}
    for (k, v) in zip(sol_struct['fields'], t):
        returnVal[k] = v

    if 'extrafields' in sol_struct:
        returnVal[sol_struct['extrafields']] = binary[pack_length:]

    for (k, v) in returnVal.items():
        if k in ['macAddress', 'source', 'dest']:
            returnVal[k] = _num_to_list(v, 8)
        elif k in ['sol_version', 'sdk_version', 'solmanager_version']:
            returnVal[k] = _num_to_list(v, 4)

    return returnVal

def _binary_to_fields_snapshot(binary):
    return_val      = []

    # set SNAPSHOT structure
    mote_structure  = ">QHBBBBBIIIIII"
    mote_fields     = [
                'macAddress', 'moteId', 'isAP', 'state', 'isRouting', 'numNbrs',
                'numGoodNbrs', 'requestedBw', 'totalNeededBw', 'assignedBw',
                'packetsReceived', 'packetsLost', 'avgLatency'
            ]
    mote_size       = struct.calcsize(mote_structure)
    path_structure  = ">QBBBbb"
    path_fields     = [
                'macAddress', 'direction', 'numLinks', 'quality',
                'rssiSrcDest', 'rssiDestSrc'
            ]
    path_size       = struct.calcsize(path_structure)

    # get number of motes in snapshot
    num_motes       = struct.unpack('>B', chr(binary[0]))[0]
    binary          = binary[1:]

    # parse SNAPSHOT
    for i in range(0, num_motes):
        # create mote dict
        mote = {}
        m = struct.unpack(mote_structure, ''.join(chr(b) for b in binary[:mote_size]))
        binary          = binary[mote_size:]
        for (k, v) in zip(mote_fields, m):
            mote[k] = v

        # format mac address
        mote["macAddress"] = _num_to_list(mote["macAddress"], 8)

        # get number of paths in mote
        num_paths       = struct.unpack('>B', chr(binary[0]))[0]
        binary          = binary[1:]

        # create path dict
        path_list       = []
        for j in range(0, num_paths):
            path = {}
            p = struct.unpack('>QBBBbb', ''.join(chr(b) for b in binary[:path_size]))
            binary = binary[path_size:]
            for (k, v) in zip(path_fields, p):
                path[k] = v

            # format mac address
            path["macAddress"] = _num_to_list(path["macAddress"], 8)

            path_list.append(path)

        mote["paths"] = path_list

        return_val.append(mote)

    return return_val

def _get_sol_binary_value_dust_hr_neighbors(hr):
    return_val  = []
    return_val += [chr(hr['numItems'])]
    for n in hr['neighbors']:
        return_val += [struct.pack(
            '>HBbHHH',
            n['neighborId'],       # INT16U  H
            n['neighborFlag'],     # INT8U   B
            n['rssi'],             # INT8    b
            n['numTxPackets'],     # INT16U  H
            n['numTxFailures'],    # INT16U  H
            n['numRxPackets'],     # INT16U  H
        )]
    return_val = ''.join(return_val)
    return_val = [ord(c) for c in return_val]

    return return_val

def _get_sol_binary_value_dust_hr_discovered(hr):
    return_val  = []
    return_val += [chr(hr['numJoinParents'])]
    return_val += [chr(hr['numItems'])]
    for n in hr['discoveredNeighbors']:
        return_val += [struct.pack(
            '>HbB',
            n['neighborId'],       # INT16U  H
            n['rssi'],             # INT8    b
            n['numRx'],            # INT8U   B
        )]
    return_val  = ''.join(return_val)
    return_val  = [ord(c) for c in return_val]

    return return_val

def _get_sol_binary_value_dust_hr_extended(hr):
    HR_DESC_EXTENDED_RSSI_DATA = [
        ('idleRssi', 'b'),
        ('txUnicastAttempts', 'H'),
        ('txUnicastFailures', 'H'),
    ]
    HR_ID_EXTENDED_RSSI = 1
    HR_ID_EXTENDED_RSSI_STRUCT = ">" + "".join([i[1] for i in HR_DESC_EXTENDED_RSSI_DATA])
    HR_ID_EXTENDED_RSSI_SIZE = struct.calcsize(HR_ID_EXTENDED_RSSI_STRUCT) * 15 # 15 channels
    return_val = []
    if "RSSI" in hr.keys():
        return_val += [struct.pack("<BB",
                                   HR_ID_EXTENDED_RSSI, # extType
                                   HR_ID_EXTENDED_RSSI_SIZE)] # extLength
        for n in hr['RSSI']:
            return_val += [struct.pack(
                HR_ID_EXTENDED_RSSI_STRUCT,
                n['idleRssi'],          # INT8    b
                n['txUnicastAttempts'], # INT16U  H
                n['txUnicastFailures'], # INT16U  H
            )]
        return_val  = ''.join(return_val)
        return_val  = [ord(c) for c in return_val]
    else:
        raise NotImplementedError

    return return_val

def _get_sol_binary_value_snapshot(snapshot):
    return_val  = ""

    # adding number of items
    return_val  += struct.pack('>B', len(snapshot))

    # converting json to bytes
    for mote in snapshot:
        if isinstance(mote['macAddress'], (str, unicode)):
            mote['macAddress'] = [int(c, 16) for c in mote['macAddress'].split("-")]
        m = struct.pack(
            '>QHBBBBBIIIIII',
            _list_to_num(mote['macAddress']),   # INT64U  Q
            mote['moteId'],                     # INT16U  H
            mote['isAP'],                       # BOOL    B
            mote['state'],                      # INT8U   B
            mote['isRouting'],                  # BOOL    B
            mote['numNbrs'],                    # INT8U   B
            mote['numGoodNbrs'],                # INT8U   B
            mote['requestedBw'],                # INT32U  I
            mote['totalNeededBw'],              # INT32U  I
            mote['assignedBw'],                 # INT32U  I
            mote['packetsReceived'],            # INT32U  I
            mote['packetsLost'],                # INT32U  I
            mote['avgLatency'],                 # INT32U  I
        )
        return_val  += m

        # adding paths list size
        return_val  += struct.pack('B', len(mote['paths']))

        p = ""
        for path in mote['paths']:
            if isinstance(path['macAddress'], (str, unicode)):
                path['macAddress'] = [int(c, 16) for c in path['macAddress'].split("-")]
            p += struct.pack(
                '>QBBBbb',
                _list_to_num(path['macAddress']),  # INT64U  Q
                path['direction'],                      # INT8U   B
                path['numLinks'],                       # INT8U   B
                path['quality'],                        # INT8U   B
                path['rssiSrcDest'],                    # INT8    b
                path['rssiDestSrc'],                    # INT8    b
            )
        return_val += p
    return_val  = ''.join(return_val)
    return_val  = [ord(c) for c in return_val]
    return return_val

# ==== file manipulation

def _fileBackUpUntilStartFrame(file_name, curOffset):
    with open(file_name, 'rb') as f:
        f.seek(curOffset, os.SEEK_SET)
        while True:
            byte = f.read(1)
            if byte == hdlc.HDLC_FLAG:
                return f.tell()-1
            f.seek(-2, os.SEEK_CUR)

# ==== miscellaneous helpers

def _num_to_list(num, length):
    """
    258, 2 -> [1,2]
    :param int num:
    :param int length:
    :rtype: list
    """
    output = []
    for l in range(length):
        output = [int((num >> 8*l) & 0xff)]+output
    return output

def _list_to_num(l):
    """
    [0x01, 0x02] -> 258
    :param list l:
    :rtype: int
    """
    output = 0
    for i in range(len(l)):
        output += l[i] << (8*(len(l)-i-1))
    return output

def _format_mac_string_to_bytes(mac_string):
    """
    "00-11-22-33-44-55-66-77" -> [0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77]
    :param str mac_string:
    :return: the mac address as list of bytes
    :rtype: list
    """
    return [int(b,16) for b in mac_string.split('-')]

def _format_buffer(buf):
    """
    example: [0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88] -> "11-22-33-44-55-66-77-88"
    :param list buf:
    :rtype: str
    """
    return '-'.join(["%.2x"%i for i in buf])

# =========================== main ============================================

if __name__ == "__main__":
    os.system("py.test -vv -x tests/")
    raw_input("Press Enter to close.")


Please note these comics have been scanned in from the originals. Not only that, but it was the first time Trickster ever tried drawing anything like this. They are full of corrections, erasures, bad drawing, and all that sort of thing. You got a problem with that? Too bad. We will be using computer drawing tools from now on, so future comics will be lots cleaner. In the meantime, try to concentrate on the humor and not the image quality.


Hastelloy C276 alloy can be forged, hot-upset and impact extruded. Although the alloy tends to work-harden, you can have it successfully spun, deep-drawn, press formed or punched. All of the common methods of welding can be used, although the oxyacetylene and submerged arc processes are not recommended when the fabricated item is for use in corrosion service.
While marking we choose a specific item number as well different color shade to differentiate steel grades. We mark ASTM B619 UNS N10276 Hastelloy C276 Welded Pipe as needed with the most suitable & visible marking technique.
Packaging is an integral part of the product. It guarantees that the ASTM B619 Hastelloy C276 Welded Pipe is delivered to the customer in the required quality. For smaller orders the size of the ASTM B619 Hastelloy C276 Welded Pipe bundle depends on the no. of Tubes ordered, for larger orders the tubes are packed into individual bundles and in such a way that the maximum weight of 4000kg per bundle is not excedded. Bundle tied down with steel tape. Bundle tied down by steel strap underlaid by tapaten.
We can also provide ASTM B619 Hastelloy C276 Welded Pipe wooden box packing, cardboard boxes, plastic wrapping, using hardened paper with PE meshing (used as protection against mechanical damages of tubes), into tapaten and polyethylene sheet etc.
Where can we find the high quality ASTM B619 UNS N10276 Hastelloy C276 Welded Pipe.


Are your evenings and nights super busy? It seems like we never have a slow day here on the farm, and I've found a quick answer to supper when we are hustling around: Quick and Healthy Chicken Salad. With just a few tricks, you can have this salad made and ready to share in 15 minutes, and around here, that's a very good meal!
Farm Report: First, my favorite farmer, Tall Guy, has a birthday coming up next week, and one of his birthday presents just might be a baby calf. We are headed in to calving season from mid January to mid March.
I asked him exactly how many cows were expecting. He just told me, "I think we have 8-9 pregnant cows..."
I told him either number 9 is or isn't pregnant. There is no "I THINK!"
(Sometimes farmers are just human MEN, and still have no clue about being pregnant!
On the Home Front: We start traveling to 8th grade girls' basketball games next week. With all this on my calendar, there are going to be times when we will need some grab and go food in the fridge. This Quick and Easy Chicken Salad is a great go-to if you do a little prep work ahead of time.
To get ready for this meal, it's nice to have some chicken breasts cooked ahead of time. It can be last night's leftovers, or what we sometimes do is use rotisserie chicken. I'm kind of in love with rotisserie chicken, and if I am in a grocery store that offers them, I will usually grab one or two to take home. At around $5.00 a chicken, it's a great meal in itself. We all love the dark meat, so it's legs and thighs for supper, and the breasts are saved for the next day.
I have to stop here a minute, and tell you that this is a VERY Indiana-based recipe! Besides the Red Gold tomatoes and chilies, Miracle Whip and horseradish are pretty much staples in Hoosier kitchens. The Farm Dust has a great name, and it too is made in Shipshewana, Indiana! This is an Amish family business and goes by Weaver's Dutch Country Seasoning! It's delish on everything you put it on. Amazon is packaging it with a spicy version I didn't know about so YUM! and YEA! QUick Indiana!


text:
Q: Pass in function as input and return function I want to write an R function that takes a mathematical function in x and returns a new function in x as an output. For example:
The input should be passed in as a mathematical function (or relation) in x:
g <- x^2 + 9*x + log(x)

And the resulting output should be:
function(x) (exp(g))

i.e. I want to return the symbolic exponential expression of the original function in x i.e. exp(x^2 + 9*x + log(x)) in this illustrative example
So ideally it would return the function object:
function(x) (exp(x^2 + 9*x + log(x)))

I tried as follows:
test <- function(g){
h <- function(x){exp(g)}
return(h)
}
m <- test(x^2 + 9*x + log(x))
m(10)

So m(10) should return:
exp(10^2 + 9*10 + log(10))

which is exp(192.3026) in this case.
Could anyone show how to do this please?

A: Here is one approach:
test <- function(e) {
    ee <- substitute(e)
    eee <- substitute(exp(X), list(X=ee))
    f <- function(x) {}
    body(f) <- eee
    environment(f) <- parent.frame()
    f
}

## Check that it works
m <- test(x^2 + 9*x + log(x))
m
# function (x)
# exp(x^2 + 9 * x + log(x))
m(1)
# [1] 22026.47
m(1) == exp(10)
# [1] TRUE

A: edit - for functionality in question
f <- function(...) {
  l <- eval(substitute(alist(x = x, ...)))
  l[[2]] <- substitute(exp(X), list(X = l[[2]]))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

g <- f(x^2 + 2*x + 5)
# function (x = x)
#   exp(x^2 + 2 * x + 5)

g(1)
# [1] 2980.958

Here is another way for a general case:
f <- function(...) {
  l <- eval(substitute(alist(...)))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

g <- f(x, x^2 + 9*x + log(x))

# function (x = x)
#   x^2 + 9 * x + log(x)

g(10)
# [1] 192.3026

This version will also work for any number of variables, just define them followed by the function:
g <- f(x, y, z, x + 2 * y + z ** 3)

# function (x = x, y = y, z = z)
#   x + 2 * y + z^3

g(1, 2, 0)
# [1] 5

There may be a better way to add ... to functions, but here is how you can do that
f <- function(..., use_dots = FALSE) {
  l <- eval(substitute(alist(...)))
  if (use_dots)
    l <- c(head(l, -1), list('...' = as.symbol('...')), tail(l, 1))
  as.function(`names<-`(l, l[sapply(l, is.symbol)]))
}

So now you don't have to name all the variables/arguments
g <- f(x, y, plot(x, y, ...), use_dots = TRUE)
g(1:5, 1:5, main = 'main title', pch = 16, col = 3, cex = 3, xpd = NA)

A: You could use package functional:
library(functional)
fun <- Compose(function(x) x^2 + 9*x + log(x), exp)
fun(1)
#[1] 22026.47

redpajama_set_name: RedPajamaStackExchange


text:
New BMW M4 DTM Champion Edition revealed
20 October 2016 | 0 comments
To celebrate the success of Marco Wittmann securing yet another DTM driver's title at the season finale at the Hockenheimring, BMW M is launching the BMW M4 DTM Champion Edition. The new edition model consists of top-class motor racing technology for drive and suspension as well as a specific design that mimics the DTM racing cars built by BMW Motorsport and delivers a power output of 500hp and a maximum torque of 600Nm.
The BMW M4 DTM Champion Edition completes the sprint from zero to 62mph in just 3.8 seconds and has a top speed is limited to 190mph* thanks to the innovative water injection technology featured in the straight six-cylinder power unit, previously seen on the BMW M4 GTS. This innovative technology enables cooling of the combustion chambers, significantly raising the engine's thermally-related performance limits by 16 per cent in power output compared to the production model.
Frank van Meel, President of BMW M GmbH commented: "Congratulations to Marco Wittmann, his team RMG and the entire crew from BMW Motorsport. We have the pleasure of honouring Marco's performance by producing a BMW M4 DTM Champion Edition in 2016 to mark his winning the DTM driver's title. Never before has one of our edition models been so closely linked to motor racing."
The BMW M4 DTM Champion Edition 2016 is exclusively available in Alpine White. Design and shaping of the additional foiling is reminiscent of the look of DTM racing cars produced by BMW Motorsport. Various aerodynamics components finished in visible carbon also give the car that distinctive racing car look. These include the front splitter, the aero flicks positioned in front of the front wheel arches, exterior mirror caps, side skirt attachments, and a rear diffuser as well as the large rear wing firmly mounted on the boot lid.
Inside the two-seater BMW M4 DTM Champion Edition 2016, both driver and co-driver sit in M Carbon bucket seats covered in exclusive Alcantara/Leather Merino. The entire interior is lined with exceptionally high-quality covering material Alcantara, also used on the M Sports steering wheel featuring a grey "12 o'clock" marker. Behind the front bucket seats of the BMW M4 DTM Champion Edition, a white rollover bar replaces the rear seat system.
In terms of comfort and safety, the new edition is by no means sparsely equipped. Features include the BMW Professional Navigation system, air conditioning, adaptive LED headlights with BMW Selective Beam (glare-free high beam assistant), OLED taillights, Park Distance Control (PDC) at the front and rear as well as automatically dimming interior and exterior mirrors. Full UK specification will be announced in due course.
In comparison to the production version of the BMW M4, the DTM Champion Edition impresses not only with enhanced performance, but also with further optimized dynamic handling qualities. This is also the result of even more consistent implementation of the lightweight construction concept. In addition to other components, the bonnet, roof, instrument panel support and rear diffuser are made from carbon fibre reinforced plastic (CFRP). The end silencer of the double-flow sports exhaust system featuring two pairs of tailpipes is made of exceptionally lightweight titanium.
Optimal contact with the road is ensured by Michelin Pilot Sport Cup 2 high-performance tyres size 265/35 R19 at the front and 285/30 R20 at the rear designed specifically for use on the racetrack and mounted on light alloys boasting a star spoke design 666 M in Orbit Grey matt. M carbon-ceramic brakes guarantee fade-free braking even in tough racing conditions. The individually adjustable 3-way coilover suspension is mechanically adjustable both for rebound and damping, thus allowing the car's handling characteristics to be adapted according to personal taste.
The BMW M4 DTM Champion Edition is on sale now, prices to be confirmed.
Thinking of buying the new BMW M4?
Compare the best car insurance deals at MoneySupermarket.
2015 Land Rover Freelander successor 'baby Discovery' starts winter testing
New Renault Twingo revealed with rear-engine and rear-wheel drive
Seat Leon Cupra 280 sets a new Nürburgring record for front-wheel drive cars
Report: Honda S2000 successor coming in 2017 with around 350bhp
Watch Jay Kay's Kermit Green Ferrari LaFerrari at the Goodwood Festival of Speed [videos]
Belgian hybrid supercar Minerva J.M. Brabazon packs 1,200bhp
Finding it difficult to insure your high performance car?
BMW unveils a new i3 and i3S
BRABUS refines the new Mercedes S 63 4MATIC and Mercedes-Maybach S 650 luxury sedans
Nissan Energy Solar now on sale in the UK
No More Rust: 4 Types of Undercoating You Can Apply to Your Truck
Tags: BMW, BMW M4

redpajama_set_name: RedPajamaCommonCrawl


text:
Home > Magazine > Magazine Detail
The Melbourne Grand Prix Circuit - Racing around the lake in the city centre
Featured, Spotlight
Alexander S
The Melbourne Grand Prix Circuit, or the Albert Park Circuit as it also known, is a street circuit around the lake in Melbourne's Albert Park. It is best known as the home of the Formula 1 Australian Grand Prix, but this venue has a long motorsports history and regularly hosts various racing events.
Melbourne Grand Prix Circuit layout
The Melbourne Grand Prix Circuit has FIA Grade 1 licence and it is considered as the one of the most popular tracks in the Formula 1 championship. Made on public roads, this track is 5.303 km long and has 16 turns. The stands capacity is 80.000.
History of the track in Albert Park dates back to the 1950s
The track has a long history, starting from the 1950s when it was called Albert Park Circuit. That layout was slightly shorter than the modern one and had only nine turns. From 1953 until 1958, Albert Park circuit was the host of the various racing formats, including Formula 1 Australian Grand Prix. Another difference from the current track was that racing was done in an anti-clockwise direction.
Start of the 2011 Australian Grand Prix
There is an interesting story about how Formula 1 returned to Melbourne. The ambition of the Victoria state new government was to wake the city up, promoting tourism and boosting the local economy. On the top of the wish list was bringing top international events to the city and Grand Prix race was one of them. Finally, this plan was accomplished when the hosting of the race was taken from the rival city of Adelaide.
Smooth surface despite being street circuit
Located near the centre of Melbourne, Grand Prix Circuit consists of public road sections, many of them incorporated from the old track from the 1950s, but some parts of the circuit were rebuilt before the first Grand Prix race in 1996. Compared to other street circuits, the track in Melbourne has a quite smooth surface. It is a very flat course, considered as a relatively fast track and easy to drive. The drivers commented that it was easy to learn the circuit which allowed them to find a proper rhythm and achieve competitive lap times.
Albert Park Melbourne
Some major changes were made in 2004 when the pit lane chicane was removed and in 2011, when another pit lane was added for the purposes of V8 Supercars paddock. Traditionally, V8 Supercars series non-championship race is a support race for the Formula 1 Australian Grand Prix.
Long preparations for the Australian Grand Prix at circuit in Melbourne
Preparations for the Australian Grand Prix start almost two months before the race. The stands raising, setting up protective fencing and pedestrian overpasses take a lot of time. After the Grand Prix weekend, everything that was set needs to be removed within six weeks.
Pit lane at Melbourne Grand Prix circuit during Australian F1 race
Despite being popular and being the most common destination for the start of the Formula 1 season, the Melbourne Grand Prix Circuit has opponents, mainly in local citizens and the owners of the facilities nearby the circuit. Every year, they are silently protesting against the race, complaining about air pollution, noise and the fact they are losing money due to the access to many facilities being restricted during the racing weekends. Those protests are usually short-lived and they are falling into oblivion after the Grand Prix weekend which is always well attended.
Michael Schumacher holds lap record time
Apart from the Formula 1 Australian Grand Prix, the circuit in Albert Park hosts other international and national racing series, like V8 Supercars. Lap time record holder is Michael Schumacher. Driving a Ferrari in 2004 Australian Grand Prix, the German set the lap time 1:24.125. By the end of 2015, Michael Schumacher was the most successful Formula 1 driver at Melbourne Grand Prix circuit with four wins. Jenson Button has three wins on his account while David Coulthard, Kimi Raikkonen and Lewis Hamilton won the race twice.
Video – Michael Schumacher pole lap, 2004 Australian Grand Prix
Address: 3206, 12 Aughtie Dr, Albert Park VIC 3206, Australia
Phone: + 61 (03) 9258 7100
Website: grandprix.com.au
Photo: sportklub.info thef1spectator.com f1fanatic.co.uk motorauthority.com grandprixevents.com
Australian Grand Prix: Victory for Valtteri Bottas, 1-2 for Mercedes
Sebastian Vettel opens the 2018 F1 season with a victory
Australian Grand Prix: First pole of the season for Lewis Hamilton


Alice in Wonderland was a staple in my childhood – there was even one Christmas where my friend and I gifted each other beautiful copies of the book. So when I was invited to the Wonderland Bar press night I jumped at the chance to see what they had done with this space – especially since it was one of the pop ups I wanted to visit the most this summer!
It's situated in the tunnels below Waterloo train station – so you know you're in for a very cool venue right from the start. They've gone above and beyond with the decor – we really felt as though we had wandered straight into Wonderland itself.
Since we were having a girls night cocktails were necessary and these beauties didn't disappoint. Sweet but dark enough to be delicious – we could have sipped these beauties all evening.
There were even some very sinister looking flamingos on the wall; it's definitely a Wonderland for adults! I thought they were great fun, and since they're slightly neon there's no avoiding these birds!
And then suddenly, with a cry of "Look!" from Lib, we realised what the hoop in the centre of the room was for! Excuse the slightly blurry photos, I couldn't adjust my camera settings in time!
He was swinging away, having a merry old time, whilst the Wonderlanders below watched on, cocktails in hand.
No version of wonderland would be complete without the Queen's Maze and some Flamingo Croquet would it? So we raced up the stairs to see what was in store!
We wished the Flamingo Croquet had been slightly larger, but hey, when space is at a premium something's got to give, eh?
So we followed the lovely Mr Walrus into the maze to see what was going on there! Frankly, this was absolutely hilarious – he was as confused as always and bubmling around muttering that he's sure there's a short cut, that ends up taking you straight back to where you were. It's so great that they've really gone all out for this one.
Cause who needs just another bar, eh? Well, I'm always keen for a fresh, new bar – especially a themed one with Bourne & Hollingsworth designing the cocktails.
Prepare yourself to meet some very fun characters!
We also indulged in a pie (which are really very well priced) at the Pieminster pie bar and boy oh boy was it good. Just what we needed! Though the only downside was, there's a bit of a lack of seating so we had to try and perch and eat. Hmmm, not too easy.
Prepare yourself for a magical night of fun, giggles and good cocktails at Wonderland Bar. What more could you want really?
I'm sure I'll be going back soon – it really was one of the most fun bars I've been to in London for a long time and since it's the anniversary of one of my favourite books, it would be rude not to return, right?
You can find all about Alice Underground and Wonderland Bar on their website, here.


text:
Knowledge >
Sci-tech >
The 3D map of Antarctica
Four years, two expeditions and one robot. That's what it took for a multinational group of scientists to create what they claim is the first ever high resolution 3D map of sea ice in Antarctica.
The project started back in 2010 aboard the Royal Research Ship James Clark Ross, fighting its way through ice to reach the Bellinghausen Sea in Antarctica.
Once there, the researchers dropped an underwater robot equipped with sonar underneath the ice. Its mission was to start mapping the underside of 500,000 square metres of sea ice. Researchers from the British Antarctic Survey say the team wanted to put together a puzzle of sorts, matching data from underneath the ice with satellite imagery from the top in an effort to gauge the thickness of the sea ice.
"What we are trying to do is trying to look at how the surface features and map on the bottom features and from that we will be able to take satellite images that map the surface of the sea ice and therefore use an equation to take that surface mapping and create an ice thickness from that," explained Dr Jeremy Wilkinson, British Antarctic Survey.
And by obtaining ice thickness measurements and its changes over time the scientists can produce more accurate models of the rate at which the planet is warming.
"Sea ice is important if you are in a spacecraft looking at the Earth you look at the polar regions. They are very, very white and that is reflecting a lot of the sunlight back into space. And therefore if you remove that white cap from the poles you get more solar radiation being absorbed, which in turn will heat the planet," said Dr Jeremy Wilkinson.
Wilkinson says the area of sea ice has reduced dramatically in the Bellinghausen Sea in recent years and he hopes these new measurements will help the researchers figure out why.
Seals are new allies in climate change monitoring
How will the new intelligent breed of ROVs benefit us?
United Arab Emirates to launch space mission to Mars
Armed guards, secret location: Inside an illegal marijuana bazaar publicized on Instagram
'Fire clouds': After Australia, scientists warn the erratic weather phenomenon could become a new reality


text:
Quotes: HC Brian Daboll, QB Daniel Jones, DL Leonard Williams
Q: Why did you guys elevate (quarterback) Davis (Webb) and then deactivate him?
A: That's something (general manager) Joe (Schoen) and I talk with Davis about. I'll keep that inhouse, but Davis has done a good job for us.
Q: Is it like a reward essentially?
A: I'm not going to get into the reason why. But that's something Joe and I talked about.
Q: Where does (safety) Landon (Collins) stand at this point?
A: I thought he did some good things last week. That was his last up, so we'll see as we get going here the rest of the way.
Q: How are (cornerback) Adoree' (Jackson) and (safety) Xavier (McKinney) looking?
A: I think Adoree' is getting better, and then with Xavier it's just how his fingers are healing. I think they get a little bit better each week.
Q: Will either of them practice this week?
A: X, no. Adoree', we'll see.
Q: You faced a lot of good receivers this year, but you might be facing the best in the league this Saturday. What makes (Minnesota Vikings wide receiver) Justin Jefferson so good? What do you see when you look at the tape?
A: One, he's extremely talented. He's got good quickness, good body control, can run any route. They line him up all over the place. I think they do a great job with him. He's hard to cover in man. He's got great awareness in zone. He's good after the catch. He can make contested catches. He's a problem.
Q: How about his route running? Would you say he's one of the top route runners?
A: Absolutely. And he can run anything you ask him to run. It's hard to read him because he's so good at the top of the route with his body control, his eyes, his head. He's really good.
Q: Has (safety Jason) Pinnock made Xavier being out a little easier to take because of the way he's played?
A: Yeah, you can't replace really good players for you. But I think Pinnock has done an excellent job of fitting into our defense. I think the defensive coaches have used him the right way, whether it's in the deep part of the field, down in the box, blitzing. He's been a good addition for us.
Q: Does he hit a little harder than most guys? It seems like he brings – especially for a guy that's a former corner.
A: He's so explosive. He's got strength and power and good speed. He can bring it.
Q: What does it do for you defensively when you guys play Landon and (defensive back) Tony (Jefferson) in the box? It seemed to go a little smaller. But also, off of that, what does it do to an offense when they have to adjust to that?
A: Well, it depends. You'd have to ask how the offense accounts for those guys. There's points in every play, whether it's protection or the run game. They're interchangeable. They can play multiple spots. They're extremely smart, both of them. Tony's been in the system before. So, I think he's got a good understanding of how we do things defensively. And Landon is just an instinctive guy. He did a good job last week.
Q: Where are you on (quarterback) Daniel (Jones) and the steps he's taken under your staff's tutelage this season?
A: Well, give Daniel credit, first and foremost. He's an extremely hard worker. I think he understands what we're trying to accomplish each week. Every week, it's a little bit different. But he works extremely hard. He studies. He understands the teams that we're playing, and he makes good decisions for what we ask him to do. Last week was a little bit different than the week before. He's taking care of the football. He's done a good job.
Q: In your experience, how difficult is it for a quarterback who has either a fumbling, an interception issue or a turnover issue to correct that because it seems like, generally speaking, he's done that.
A: Give credit to him. He's got to take care of the ball in the pocket, and he's got to be the one to make good decisions when he's under pressure. I think (quarterbacks coach) Shea (Tierney) has done a really great job with him in the quarterback room. We try to do things that accentuate his strengths. I think he can throw it on all three levels, but there's a way to play each game against each opponent based on what they have defensively, how their rush is, what their corners look like. He's done a good job of operating and executing our offense.
Q: You come from a place where you've experienced a quarterback being a really popular guy in the locker room. It certainly seems like Daniel (Jones) has won over teammates and is highly respected. How much does that matter?
A: I think when I got here, just talking to some of the skill guys and even the defensive guys, they've always had that respect for Daniel because of the way he approaches his job, he's a true pro. And he's a good leader. I know he's kind of a quiet guy. But in the huddle, he's a good leader with those guys. He knows everybody's responsibilities. He can get things lined up; he can correct mistakes. He's a problem solver. So, I think the guys have a lot of respect for him.
Q: The turnover thing, obviously, was a thing early in his career. What do you make of him having – he's thrown four interceptions, the fewest of any quarterback in the NFL this year that's played most of their team's games. What do you make of that?
A: That's good.
Q: What do you attribute it to? Why do you think there's been such a drastic shift there?
A: Well, again, like I was saying: I think he works at it. I think Shea has done a great job. We have certain reads and things in our offense that we teach. And he just goes out and executes well. So, he's done everything that we've asked him to do in terms of the things that we need to do each game. Again, it's never going to be perfect. It's a hard position to play. I think he's got some confidence. We have confidence in him. We just put together a game plan that we think will work well for us as a team but (also will) work well for him, too, as a quarterback.
Q: Do you think there's more upside to him? A lot of times when somebody's that far along in their career, they'll say, 'oh, that's their ceiling".
A: Well, I don't think he's that far along in his career as a quarterback. Again, it's a tough position to play. I can just go by the guys that I've had the last few years. One, I was with him for four years and each year we took a little bit of a step, and you always give credit to the players. His ability to grasp information and then go out there and perform it with what we're asking him to do, I'm not sure the other years he's been here, I think he's made steps each way. Certainly, things to improve on but conscientious, hardworking, tough, competitor. Those are good qualities to have at that position.
Q: The flip side is you've had the fewest 20+ yard pass plays. How much of that do you view as situational, personnel, what do you attribute that to?
A: We always have a gameplan each week. Go into a game of how we want to play it and his job is to make the right decisions. So, if it's to throw a quick game or take an underneath route, he's done a good job of putting the ball where we want him to put it. We certainly would like more explosive plays, that helps you score more points, but he's doing what we ask him to do.
Q: A lot of times guys on the outside have these fiery dispositions. Daniel is not that guy.
A: Oh, I thought you were talking about me (laughs).
Q: Well that we all know, but Daniel's not that way. Does that not tell the whole story about Daniel?
A: Yeah, he's a competitor and I think that's why his teammates respect him so much. I think he's just very levelheaded and that helps too when sometimes there's chaos in the game; whether that's in the pocket, whether you're down. I think he's really been the model of consistency with his attitude and his approach and that's what I appreciate about him.
Q: Understanding that offensive line works as five guys, it certainly seems like early in the season and then again yesterday, the offensive line has played really well with (guard Ben) Bredeson specifically in there. What is it about him that he brings? Unless that's a coincidence.
A: Yeah, he was in there for that 18-play drive. I think Ben's done a good job. He's been a good player for us when we've asked him to be in there, he's coming back from an injury. I thought he did some good things last game. Still, you try to work those guys in that are coming back. Him, (center Nick) Gates, (center Jon) Feliciano, (guard Mark) Glo (Glowinski), we have a lot of confidence in all four of those guys.
Q: Do you think he'll be at left guard specifically? Are you rotating them the rest of the season?
A: That's a good question. I think we'll go through it this week. I think they've all earned the right to play, they know what to do, they're tough, competitive, so that will be a discussion we have kind of at the end of probably every week going forward.
Q: How much is putting Gates at center on the table there?
A: I think we talk about all those things. I think Jon (Feliciano) did a really good job last week. Again, those four guys inside, we have confidence in all those guys.
Q: I know it's a walkthrough, but do you have anybody else out today?
A: No, the two guys would be, they'll be out there running around, the two guys would be Adoree' and (guard) Shane (Lemieux). Everybody else would be doing something.
Q: (Head Coach) Kevin O'Connell, he's a first-year guy, like yourself. We all know what he's doing out in Minnesota. Can you talk about the job he's done, and do you have a relationship with him at all?
A: Yeah, I do. I don't call him up on the phone everyday but if I see him out at the combine or something. I actually went out and worked him out when he was coming up for the draft. Show my age but he's done a really nice job with that team, they've won a lot of one-score games. Give credit to the players, but give credit to him and his staff too. They've got a lot of good coaches on that staff and to be where they're at right now is a testament to him and his team. Smart player, really good guy, good family, he's done a nice job for that organization.
Q: Are they similar to you guys in a way? You talk about Minnesota winning a lot of one score games, a lot of close games. Are they a little bit similar to you guys?
A: No, I think every team is different. I just think they've done a good job of closing out games or obviously coming back like they did last week, and they don't flinch. I think that's a testament to Coach O'Connell, and the rest of the guys on that team.
Q: Did you get a chance to watch any of that game?
A: Yeah, I saw a little bit of it. I mean I watched it on the coaching tape, but I saw a little bit of it at the hotel.
Q: You've often said that I've pretty much seen everything.
A: That was a great comeback. Unbelievable comeback. Pretty resilient team.
Q: Another guy coming back from injury, (defensive lineman) Leonard Williams. It seemed like he played quite a lot of snaps for a guy who admittedly after the game said he wasn't 100 percent. What'd you see from him and just kind of the will he showed?
A: That's him. It was good to have him back. He's one of our best players, particularly inside there with him and (defensive lineman Dexter Lawrence) Dex. Good to have those guys out there.
Q: (Head Coach Bill) Parcells would always say to us, "Let's not put this guy in Canton just yet," but when you see a performance like (outside linebacker) Kayvon (Thibodeaux) the other night, does it make you say, 'Wow, this guy is something special'?
A: I'd probably take a page out of Coach Parcell's book.
Quarterback Daniel Jones
Q: You guys have an opportunity to clinch a playoff spot with a win at Minnesota. What does that mean for you for as a player, and does that add any extra motivation?
A: It's definitely exciting, but I don't think it's extra motivation. I think we're going to prepare as hard as we can, and that doesn't change week-to-week. I think we've been doing that. (We're) treating it one week at a time, and this is an awesome opportunity for us. I don't think the preparation or the approach changes, but we're certainly excited for the opportunity.
Q: If it does happen, how much would that check off a goal for what you guys were trying to accomplish this season? Would it make your season a success?
A: I don't know if we'd say that. It's certainly a goal for us to make playoffs, but we're confident in our ability as a team, and we believe we're a good team. We're just going to keep focusing one week at a time and play as well as we can.
Q: You have the fewest interceptions of any starting quarterback in the NFL this year. What does that mean to you considering where you came from in that statistic two, three years ago?
A: I think I've improved in some of those decision-making situations. Protecting the ball is a big part of the game at this position. I'll try to keep doing that as well as I can. But a lot of credit to our group – I think when you protect the ball, that's a group thing. We've got to be on the same page, a lot of trust in the receivers being in the right spots. They've done a good job doing that, and good job with the coaches also.
Q: You shouldered the blame when it was the other way. You say protecting the ball is a group thing, but when it wasn't protecting the ball, it all fell on you. Is that just the way the quarterback is?
A: I think that's part of it. The quarterback is responsible for decision-making. It goes both ways.
Q: Is there anything about this particular staff where you felt like you clicked either early on or where they've especially helped you grow as a quarterback?
A: I've really enjoyed working with them. I think Dabs (head coach Brian Daboll), Kaf (offensive coordinator Mike Kafka), (quarterbacks coach) Shea (Tierney) – all those guys have helped me out a lot. I think just understanding the game, understanding football, learning this system. I think this is a good system. As we said from the beginning, you can tell this is a quarterback-friendly system where the quarterback is in good position to make good decisions most of the time. I've enjoyed (it), I've learned a ton from them.
Q: You call it, 'quarterback-friendly,' but a lot of people would call it 'conservative,' just in the way you guys have thrown the ball. I think the longest pass you guys threw the ball the other day was 12-yards down the field. Do you ever kind of look around and say, 'I wish I was throwing the ball around a little bit more. I wish I could take deeper shots.' Anything like that, or are you just happy with the way things are?
A: It depends on the game and the way it plays out. We're certainly going to be aggressive when we can. But we won the game, and that's the goal. That's what we're focused on.
Q: Are you happy you don't have to ever hear those questions about the primetime games anymore?
A: (Laughs) It was a big win for us, and I didn't put too much stock in that to begin with.
Q: What's most different about this system? You talked about it's different and leaves decision-making in your hands. Is that the biggest difference from other systems you've been in?
A: I think that's part of it. We've talked a lot about the versatility of it and different options in certain situations to put us all in a position to make plays and adjust to what the defense is doing.
Q: When a new receiver like Isaiah (Hodgins) comes in as late as he does, how do you find the chemistry?
A: A lot of it is conversation. Watching film and the work you do in the meeting room, talking through things, getting an idea of how he sees things and how I see things. He knew the system really well coming from Buffalo; it's similar there, so the concepts were familiar. It was a lot just about conversation and talking through how we saw certain situations. The time on the field is important, too, during practice. A lot of credit to him. He's done a great job for us.
Q: How would you describe what (wide receiver) Richie (James) has done? He had a very good start to the season. (Wide receiver) Wan'Dale (Robinson) came back, and he kind of took a backseat. Now, the last three, four weeks, he's been prominent again in the offense. How would you describe what he's done for this team this season?
A: He's been really big for us. He's made a lot of key plays. He made some key plays the other night on critical downs. He's just extremely consistent day-to-day. You know exactly what you're going to get from him. His approach has been really good. As a quarterback, you like working with those guys. He's stepped-up time and time again. He deserves a lot of credit.
Q: What do you make from that Minnesota tape from watching? There was such a big disparity in the two halves from last week for them. What do you make of this team when you look at that?
A: I think they got in some tough situations in that first half. But they're a good team, they're a good defense. They've got a lot of key veteran players who have played a lot of football who are smart and understand how the offense is trying to attack them. We'll be prepared for that and have a plan for it —but they're a good group.
Q: I assume from that, you're kind of referencing (Minnesota Vikings cornerback Patrick) Peterson and (Minnesota Vikings safety) Harrison Smith and those kind of guys?
A: Yeah, I think those guys. They've got some guys up front that are veterans and good players as well. I think at all three levels they have good veteran players.
Q: Do you think you personally have learned how to win games? Maybe your numbers are better if I go back to even your rookie year, but do you feel like you learned how to win games and maybe not always fill up the box scores?
A: I think each game's different. But I think I've gotten a better idea of what does win in the NFL. A lot of times, it's not what you would think. I think it has a lot to do with taking care of the ball, staying in good situations for the offense, executing on critical downs and scoring in the red zone. But I think I've improved a lot since my rookie year.
Defensive Lineman Leonard Williams
Q: You could theoretically clinch a playoff spot this weekend. You've never been in the playoffs, what would that mean to you?
A: It means a lot to me. I'm in year eight, it's obviously been a long time in the league to not go to the playoffs. That's been a very tough part of my career and it would mean a lot to me to be able to go with these guys that I've been grinding with for the last few years. I've seen a lot of these guys here; I know a lot of these guys here now pretty well. It'd mean a lot for me, and also a lot for me to see them go as well.
Q: You've had exposure to how far this franchise has come. When you were traded, it maybe was one of the worst teams in league. Can you reflect on that and just the journey of that?
A: Yeah, that's what I mean. It's more special to go to the playoffs after you've been on a team like that. I've never been a fan of wanting to be a vet and jump to a team that are Super Bowl contenders, almost like bandwagon jumping type of thing. It wouldn't feel as good to me. Being on a team like this where I've seen the ups and downs and I've known these guys pretty well, I know how much of a struggle we've been going through and stuff like that. So, to be able to go with a team like that means a lot more to me.
Q: It sounds ridiculous but when you're on losing teams people start questioning, 'Do these guys really want to win?' or, 'How badly do they want to win?' For you, and your hunger for winning, how strong is that?
A: To be honest it increases even more when you've been losing so much. It's almost like sometimes I feel like you get more comfortable on a winning team because you're so used to winning that it's almost like you feel like it might be the program or the coaches or whatever the case may be, that's the reason for winning. So, you can kind of be a little more comfortable and relaxed as a player. Whereas we've been losing so we put so much pressure on us, like we have to do this, we have to do this, to get out of this gutter, to get out of this hole, and to be playoff contenders one day. Fortunately, it looks like we're going to be able to have a chance and we've got to just make sure we finish the season strong.
Q: I assume you weren't 100 percent the other day. How are you feeling and how did you play as many snaps as you did as hurt as you were?
A: I'm not 100 percent, definitely was banged up a little bit. I feel like that's the majority of the league right now and that's what we harp on a lot. About it being December football, we know how much of a tough person and player you have to be to keep going near the end of the season like this, because the majority of the league is banged up. It's not an excuse, it's not anything like that. If I'm on the field…
Q: It's new for you because you had never missed a game. I know you've played banged up before, but you had never missed a game which I'm sure made this season feel a little different.
A: Yeah, it definitely felt a little different. This is my first time ever being on the sideline while I'm seeing guys in pads on the field. It's definitely a weird experience, but I've been dealing with it, I've been managing it. Everybody has adversity at times and that's been something I've been dealing with this year and I'm trying to make the best of my situation.
Q: A week ago everybody was wondering if this team could get back up after the loss to Philly. Now it's how high did you get and make sure that you're steady. Is that just kind of an example of this league and this time of the year when you have something playing for?
A: I think it's also an example of why (head coach Brian Daboll) Coach Dabs tells us to keep it in here. That's all outside noise. It's an outside noise thing to say, 'Are they going to be able to come off of this loss?' or, 'Are they getting too high after a win?' When really, we know that we're keeping the same exact routine every week. We're staying right here, and we hear a lot of outside stuff, but we try to keep it the same inside all the time. Granted there is obviously, you feel better after a win, and you feel down after loss, but we try to wash it and move on.
Q: You've mentioned how it's been a whole eight-year career without making the playoffs but it's been a whole eight year career in New York, which is a very hard place to lose because the fans can be difficult. What's it been like to play in New York when you win?
A: That's been crazy. Half of my career has been on two different New York teams and haven't been to the playoffs. I think about that sometimes, winning a championship in New York and picturing a parade in the city and stuff like that. I can't imagine how that would be. Right now, I'm just trying to live in the moment.
Q: Has it been cool to win in New York this year?
A: Yeah, it has been cool. I think because I've been on the downside of it, the losing side of it, and now being on the upside of it I can definitely see the difference in the way the city treats you. It's cool, but at the same time as much as you don't like it when they talk bad about you it's kind of hard to accept it when they start praising you. You know just as much as they praise, they can easily turn on you. At the same time, I just try to pay attention to my guys in here.
Q: How exciting is it for you that you're so close to potentially playing in your first playoff game?
A: Yeah, that's what I was just saying. I'm super excited.
Q: I'm sorry, I'm late.
A: No worries. I'm on my eighth year, been a long time in the league, coming off a double-digit year soon and this might be my first chance of going to the playoffs which is pretty crazy. That's something every player looks forward to as a player, going to the playoffs and having a chance for the championship. Eight years in New York I haven't really an opportunity to do that until now, and we've got to just make sure we finish the season strong for that.
Q: You had your chance your rookie year, right?
A: Yeah, we lost to Buffalo. We were 10-6 that year with the Jets and the last game of the season we lost to Buffalo. That was the closest I've gotten to going to the playoffs.
Q: So that was probably the biggest game you've played in until Sunday. Did Sunday feel like what you'd imagine a playoff game feel like?
A: Yeah exactly. We tried to say that it wasn't a playoff game because obviously it wasn't. Whether we won or lost we were going to have games after, but at the same time it definitely felt like it. The atmosphere felt like it, the way the teams were playing, and we knew how much was at stake. Even though we say it wasn't a playoff game it definitely felt like one.


text:
Got Milk? DoH Consent Decree Requires Shut Down of Big Island Dairy
By News Release @ 4:03 PM :: 4144 Views :: Hawaii County , Environment, Agriculture, Small Business
Hawai'i Department of Health and Big Island Dairy sign consent agreement to protect the environment and community as the dairy closes operations
News Release from Hawaii Department of Health, March 28, 2019
HONOLULU – The Hawai'i Department of Health (DOH) today entered into an Administrative Order on Consent (AOC) with the owners of Big Island Dairy, LLC.
The AOC was completed to address numerous discharges of wastewater containing manure from the dairy to state waters during the past two years that were documented by DOH. The AOC requires Big Island Dairy owners to terminate their dairy operations, remove all their cows from confinement on the site, clean and remove the existing wastewater system, and pay $79,000 by June of 2019, either as an administrative penalty or to fund an environmentally beneficial project in the area.
The removal of cows in confinement and the cleaning and removal of the dairy's wastewater system is expected to halt the odor and wastewater discharges that have affected neighbors in Oʻokala during operations at the Big Island Dairy facility.
"Entry into the AOC ensures that the closing of the dairy is being conducted in an expeditious and responsible manner," said Keith Kawaoka, DOH deputy director of environmental health. "While the Department of Health supports local agricultural and food sustainability, operation of industrial agricultural facilities must be conducted in a manner that respects both Hawaii's delicate environment and the local communities that host them."
Big Island Dairy was unable to comply with state and federal laws in place to protect human and environmental health due to the dairy's size, limitations of its wastewater system and local environmental conditions. The property receives a large amount of rainfall, has steep slopes and volcanic soils making it susceptible to flooding and wastewater discharges. The dairy's inability to comply, along with a federal court lawsuit outside of DOH's enforcement, forced dairy owners to agree to cease milking operations and close their facility.
The Hawai'i Department of Health protects the health of residents and visitors who enjoy the state's coastal and inland water resources. This is accomplished through statewide coastal water surveillance and watershed-based environmental management using a combination of permit issuance, water quality monitoring, investigation, enforcement, polluted runoff control, and public education.
(Editor's Note: We may not have fresh milk, but at least we have B&Bs in Ookala.)


text:
<?php

defined('AJXP_EXEC') or die( 'Access not allowed');

/**
 * Send notifications to user on some predefined actions
 * @package AjaXplorer_Plugins
 * @subpackage Mailer
 */
class PhpMailLiteMailer extends AjxpMailer {

    protected function sendMailImpl($recipients, $subject, $body, $from = null){

        require_once("lib/class.phpmailer-lite.php");
        $realRecipients = $this->resolveAdresses($recipients);

        // NOW IF THERE ARE RECIPIENTS FOR ANY REASON, GO
		$mail = new PHPMailerLite(true);
		$mail->Mailer = $this->pluginConf["MAILER"];
        $from = $this->resolveFrom($from);
        if(!is_array($from) || empty($from["adress"])){
            throw new Exception("Cannot send email without a FROM address. Please check your core.mailer configuration.");
        }
        if(!empty($from)){
            if($from["adress"] != $from["name"]){
                $mail->SetFrom($from["adress"], $from["name"]);
            }else{
                $mail->setFrom($from["adress"]);
            }
        }
		foreach ($realRecipients as $address){
            if($address["adress"] == $address["name"]){
                $mail->AddAddress(trim($address["adress"]));
            }else{
                $mail->AddAddress(trim($address["adress"]), trim($address["name"]));
            }
		}
		$mail->WordWrap = 50;                                 // set word wrap to 50 characters
		$mail->IsHTML(true);                                  // set email format to HTML
        $mail->CharSet = "utf-8";

        $mail->Subject = $subject;
		$mail->Body = nl2br($body);
		$mail->AltBody = strip_tags($mail->Body);

		if(!$mail->Send())
		{
			$message = "Message could not be sent\n";
			$message .= "Mailer Error: " . $mail->ErrorInfo;
			throw new Exception($message);
		}

    }

}

redpajama_set_name: RedPajamaGithub


Found 1 blog entry tagged as "San Rafael Manor".
Tuesday, March 24th, 2015 at 8:59pm.
I had the pleasure of representing the buyer who relocated to Marin from Watsonville a year ago to be near her daughter and two grandchildren. Roslyn was referred to me by Scott Sohle of US Bank in Mill Valley. We hit it off immediately. Roslyn had been renting an apartment in Larkspur Landing and was anxious to be a homeowner again. She knew what she wanted and it didn't take long to find the ideal home for her in San Rafael; a light, spacious 3 bedroom, 1.5 bath townhome with a large enclosed patio for gardening. The front opens onto an expansive lawn area and view of the pool, perfect for her grandchildren this summer. It was a good value at $412,500.


Download Twitter Page Mockup For Free.
Todays freebie is a Twitter Page Mockup created by Anthony Boyd Graphics. This free psd template features a simple setup of the twitter page layout. Use this mockup to test out some custom designs and graphics you might have for your new twitter account. Free for personal and commercial use. Link back to this page if you would like to feature this mockup.