'Calculates the resilience held in the vulnerability_data table
for a specific location and time period.
This is run async within vulnerability_update_aggregates
Where appropriate add test cases to modules/unit_tests/s3db/vulnerability.py'

@staticmethod
def vulnerability_resilience(location_id, resilience_pid, indicator_pids, date_period_start, date_period_end, use_location):

    location_level = 'L3'
    db = current.db
    s3db = current.s3db
    vtable = s3db.vulnerability_data
    atable = db.vulnerability_aggregate
    query = (((vtable.deleted != True) & (vtable.approved_by != None)) & vtable.parameter_id.belongs(indicator_pids))
    ward_count = 1
    if use_location:
        query &= (vtable.location_id == location_id)
    else:
        child_locations = current.gis.get_children(location_id, location_level)
        child_ids = [row.id for row in child_locations]
        ward_count = len(child_ids)
        query &= vtable.location_id.belongs(child_ids)
    if (date_period_end is None):
        pass
    elif (date_period_end == 'None'):
        date_period_end = None
    else:
        query &= (vtable.date <= date_period_end)
    rows = db(query).select(vtable.parameter_id, vtable.location_id, vtable.value, vtable.date, orderby=(vtable.location_id, vtable.parameter_id, (~ vtable.date)))
    values = []
    append = values.append
    locations = []
    new_location = locations.append
    last_record = (0, 0)
    for row in rows:
        value = row.value
        if (not value):
            continue
        l = row.location_id
        key = (l, row.parameter_id)
        if (last_record != key):
            last_record = key
            append(value)
            if (l not in locations):
                new_location(l)
    values_len = len(values)
    if (not values_len):
        return
    values_sum = sum(values)
    values_min = min(values)
    values_max = max(values)
    values_avg = (float(values_sum) / values_len)
    from numpy import median
    values_med = median(values)
    values_mad = median([abs((v - values_med)) for v in values])
    reported_count = len(locations)
    query = (((atable.location_id == location_id) & (atable.date == date_period_start)) & (atable.parameter_id == resilience_pid))
    record = db(query).select(atable.id, limitby=(0, 1)).first()
    if record:
        db(query).update(date=date_period_start, end_date=date_period_end, reported_count=reported_count, ward_count=ward_count, min=values_min, max=values_max, mean=values_avg, median=values_med, mad=values_mad)
    else:
        id = atable.insert(agg_type=4, parameter_id=resilience_pid, location_id=location_id, date=date_period_start, end_date=date_period_end, reported_count=reported_count, ward_count=ward_count, min=values_min, max=values_max, mean=values_avg, median=values_med, mad=values_mad)
    return
