text:
// ===================================================
// Package.cpp
// ===================================================

#include <stdio.h>
#include <time.h>
#include "CmpGlobl.h"
#include "ListADT.h"
#include "APITypes.h"
#include "Objectiv.h"
#include "Find.h"
#include "Path.h"
#include "ASearch.h"
#include "Campaign.h"
#include "CampList.h"
#include "mission.h"
#include "Package.h"
#include "update.h"
#include "team.h"
#include "atm.h"
#include "AIInput.h"
#include "MsgInc/AirTaskingMsg.h"
#include "Feature.h"
#include "classtbl.h"

#include "Debuggr.h"

#define AMIS_SUPPORT_MASK AMIS_ADDAWACS | AMIS_ADDJSTAR | AMIS_ADDECM | AMIS_ADDTANKER

#define MIN_FORCE_ESCORT 12

// ============================================
// Externals
// ============================================

#ifdef KEV_ADEBUG
extern char MissStr[AMIS_OTHER][16];
#endif

#ifdef CAMPTOOL
// Renaming tool stuff
extern VU_ID_NUMBER RenameTable[65536];
extern int gRenameIds;
#endif

extern FILE
*save_log,
*load_log;

extern int
start_save_stream,
start_load_stream;

#ifdef DEBUG
int gSEADrequested = 0;
int gSEADgot = 0;
int gFACrequested = 0;
int gFACgot = 0;
int gBARCAPrequested = 0;
int gBARCAPgot = 0;
int gSWEEPrequested = 0;
int gSWEEPgot = 0;
int gESCORTrequested = 0;
int gESCORTgot = 0;

extern int gCheckConstructFunction;
#endif

int PackInserted = 0;

#define ATM_HIGH_PRIORITY 150
#pragma warning (disable : 4786) // debug info truncation

extern int gCampDataVersion;
extern bool g_bTankerWaypoints;
extern bool g_bLargeStrike;

#ifdef DEBUG
//#define DEBUG_COUNT // this can cause crashes when doing long debug runs !
// JPO some simple package tracking code, keeps track of whats been lost.
#include <map>

int gPackageCount = 0;
class PackageListCounter
{
    typedef std::map<int, PackageClass *> ID2PACK;
    int maxoccupancy;

    ID2PACK packlist;
public:
    PackageListCounter() : maxoccupancy(0) { };
    void Report()
    {
        MonoPrint("%d (%d) packages of %d left\n", gPackageCount, packlist.size(), maxoccupancy);
        ID2PACK::iterator it;

        for (it = packlist.begin(); it != packlist.end(); it++)
        {
            PackageClass *ent = (*it).second;
            MonoPrint("Package left %d campid %d ref %d\n", (*it).first,
                      ent->GetCampId(), ent->RefCount());
        }

        packlist.clear();
    }
    void AddObj(int id, PackageClass *entry)
    {
        packlist[id] = entry;

        if (packlist.size() > maxoccupancy)
            maxoccupancy = packlist.size();
    };
    void DelObj(int id)
    {
        ID2PACK::iterator it;
        it = packlist.find(id);
        packlist.erase(it);
    }
};
static PackageListCounter mypacklist;
void PackageReport(void)
{
    mypacklist.Report();
}
#endif

// ============================================
// Prototypes
// ============================================

void FinalizeFlight(Unit flight, int flights);

int CallInOCAStrikes(MissionRequest mis);

// =================================
// Smart heap pool stuff
// =================================

#ifdef USE_SH_POOLS
MEM_POOL PackageClass::pool;
#endif

// ============================================
// PackageClass Functions
// ============================================

// KCK: ALL PACKAGE CONSTRUCTION SHOULD USE THIS FUNCTION!
PackageClass* NewPackage(int type)
{
    PackageClass *new_package;
#ifdef DEBUG
    gCheckConstructFunction = 1;
#endif
    VuEnterCriticalSection();
    lastVolitileId = vuAssignmentId;
    vuAssignmentId = lastPackageId;
    // vuAssignmentId = lastLowVolitileId;
    vuLowWrapNumber = FIRST_LOW_VOLITILE_VU_ID_NUMBER;
    vuHighWrapNumber = (FIRST_LOW_VOLITILE_VU_ID_NUMBER + LAST_LOW_VOLITILE_VU_ID_NUMBER) / 2;
    new_package = new PackageClass(type);
    lastPackageId = vuAssignmentId;
    // lastLowVolitileId = vuAssignmentId;
    vuAssignmentId = lastVolitileId;
    vuLowWrapNumber = FIRST_VOLITILE_VU_ID_NUMBER;
    vuHighWrapNumber = LAST_VOLITILE_VU_ID_NUMBER;
    VuExitCriticalSection();
#ifdef DEBUG
    gCheckConstructFunction = 0;
#endif
    return new_package;
}

PackageClass::PackageClass(ushort type) : AirUnitClass(type)
{
#ifdef DEBUG
    ShiAssert(gCheckConstructFunction);
#endif

    elements = 0;
    c_element = 0;
    memset(element, 0, sizeof(VU_ID)*MAX_UNIT_CHILDREN);
    interceptor = FalconNullId;
    wait_cycles = 0;
    flights = 0;
    wait_for = 0;
    iax = iay = 0;
    eax = eay = 0;
    bpx = bpy = 0;
    tpx = tpy = 0;
    takeoff = 0;
    tp_time = 0;
    caps = 0;
    package_flags = 0;
    requests = 0;
    responses = 0;
    aa_strength = 0;
    ingress = NULL;
    egress = NULL;
    dirty_package = 0;
    SetParent(1);
#ifdef DEBUG_COUNT
    gPackageCount++;
    mypacklist.AddObj(Id().num_, this);
#endif
}

PackageClass::PackageClass(VU_BYTE **stream) : AirUnitClass(stream)
{
    if (load_log)
    {
        fprintf(load_log, "%08x PackageClass ", *stream - start_load_stream);
        fflush(load_log);
    }

    if (share_.id_.creator_ == vuLocalSession.creator_ && share_.id_.num_ > lastPackageId)
        lastPackageId = share_.id_.num_;

    memset(element, 0, sizeof(VU_ID)*MAX_UNIT_CHILDREN);
    memcpy(&elements, *stream, sizeof(uchar));
    *stream += sizeof(uchar);
    memcpy(element, *stream, sizeof(VU_ID)*elements);
    *stream += sizeof(VU_ID) * elements;
#ifdef DEBUG

    for (int i = 0; i < elements; i++)
        element[i].num_ &= 0xffff;

#endif
    memcpy(&interceptor, *stream, sizeof(VU_ID));
    *stream += sizeof(VU_ID);

    if (gCampDataVersion >= 7)
    {
        memcpy(&awacs, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(&jstar, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(&ecm, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(&tanker, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
    }

#ifdef DEBUG
    awacs.num_ &= 0x0000ffff;
    jstar.num_ &= 0x0000ffff;
    ecm.num_ &= 0x0000ffff;
    tanker.num_ &= 0x0000ffff;
#endif
    memcpy(&wait_cycles, *stream, sizeof(uchar));
    *stream += sizeof(uchar);

    // If this package has already been planned, we can save some room
    if (Final() && !wait_cycles)
    {
        memcpy(&requests, *stream, sizeof(short));
        *stream += sizeof(short);

        if (gCampDataVersion < 35)
        {
            short threat_stats;
            memcpy(&threat_stats, *stream, sizeof(short));
            *stream += sizeof(short);
        }

        memcpy(&responses, *stream, sizeof(short));
        *stream += sizeof(short);
        memcpy(&mis_request.mission, *stream, sizeof(short));
        *stream += sizeof(short);
        memcpy(&mis_request.context, *stream, sizeof(short));
        *stream += sizeof(short);
        memcpy(&mis_request.requesterID, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(&mis_request.targetID, *stream, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
#ifdef DEBUG
        mis_request.requesterID.num_ &= 0x0000ffff;
        mis_request.targetID.num_ &= 0x0000ffff;
#endif

        if (gCampDataVersion >= 26)
        {
            memcpy(&mis_request.tot, *stream, sizeof(CampaignTime));
            *stream += sizeof(CampaignTime);
        }
        else if (gCampDataVersion >= 16)
        {
            memcpy(&mis_request.tot, *stream, sizeof(CampaignTime));
            *stream += sizeof(CampaignTime);
        }

        if (gCampDataVersion >= 35)
        {
            memcpy(&mis_request.action_type, *stream, sizeof(uchar));
            *stream += sizeof(uchar);
        }
        else
        {
            mis_request.action_type = 0;
        }

        if (gCampDataVersion >= 41)
        {
            memcpy(&mis_request.priority, *stream, sizeof(short));
            *stream += sizeof(short);
        }
        else
        {
            mis_request.priority = 1;
        }

        ingress = NULL;
        egress = NULL;
        package_flags = 0;
    }

    // Otherwise, we'd better save everything
    else
    {
        uchar wps;
        WayPoint w, lw;

        memcpy(&flights, *stream, sizeof(uchar));
        *stream += sizeof(uchar);
        memcpy(&wait_for, *stream, sizeof(short));
        *stream += sizeof(short);
        memcpy(&iax, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&iay, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&eax, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&eay, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&bpx, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&bpy, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&tpx, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&tpy, *stream, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(&takeoff, *stream, sizeof(CampaignTime));
        *stream += sizeof(CampaignTime);
        memcpy(&tp_time, *stream, sizeof(CampaignTime));
        *stream += sizeof(CampaignTime);
        memcpy(&package_flags, *stream, sizeof(ulong));
        *stream += sizeof(ulong);
        memcpy(&caps, *stream, sizeof(short));
        *stream += sizeof(short);
        memcpy(&requests, *stream, sizeof(short));
        *stream += sizeof(short);

        if (gCampDataVersion < 35)
        {
            short threat_stats;
            memcpy(&threat_stats, *stream, sizeof(short));
            *stream += sizeof(short);
        }

        memcpy(&responses, *stream, sizeof(short));
        *stream += sizeof(short);
        // Read in routes
        memcpy(&wps, *stream, sizeof(uchar));
        *stream += sizeof(uchar);
        ingress = lw = NULL;

        while (wps)
        {
            w = new WayPointClass(stream);

            if (!lw)
                ingress = lw = w;
            else
                lw->InsertWP(w);

            lw = w;
            wps--;
        }

        memcpy(&wps, *stream, sizeof(uchar));
        *stream += sizeof(uchar);
        egress = lw = NULL;

        while (wps)
        {
            w = new WayPointClass(stream);

            if (!lw)
                egress = lw = w;
            else
                lw->InsertWP(w);

            lw = w;
            wps--;
        }

        if (gCampDataVersion < 35)
        {
            // This isn't valid any more
            memcpy(&mis_request, *stream, 64);
            *stream += 64;
        }
        else
        {
            // MLR Had a CTD here while exiting Takeoff TE, called by LoadCampaign()->LoadUnit()->DecodeUnitData()->NewUnit()
            // the stream isn't long enough, trying to copy 76 bytes.  Reason unknown?
            memcpy(&mis_request, *stream, sizeof(MissionRequestClass));
            *stream += sizeof(MissionRequestClass);
        }
    }

    dirty_package = 0;
#ifdef DEBUG_COUNT
    gPackageCount++;
    mypacklist.AddObj(Id().num_, this);
#endif
}

PackageClass::~PackageClass(void)
{
    if (IsAwake())
        Sleep();

    WayPoint w, nw;

    w = egress;

    while (w)
    {
        nw = w->GetNextWP();
        delete w;
        w = nw;
    }

    egress = NULL;
    w = ingress;

    while (w)
    {
        nw = w->GetNextWP();
        delete w;
        w = nw;
    }

    ingress = NULL;

    if (wp_list)
        DisposeWayPoints();

    wp_list = NULL;
#ifdef DEBUG_COUNT
    gPackageCount--;
    mypacklist.DelObj(Id().num_);
#endif
}

int PackageClass::SaveSize(void)
{
    WayPoint w;
    int iw = 0, ew = 0, size;

    size = AirUnitClass::SaveSize()
           + sizeof(uchar)
           // + sizeof(VU_ID)*MAX_UNIT_CHILDREN
           + sizeof(VU_ID) * elements
           + sizeof(VU_ID)
           + sizeof(VU_ID)
           + sizeof(VU_ID)
           + sizeof(VU_ID)
           + sizeof(VU_ID)
           + sizeof(uchar);

    // If this package has already been planned, we can save some room
    if (Final() && !wait_cycles)
    {
        size += sizeof(short)
                + sizeof(short)
                + sizeof(short)
                + sizeof(short)
                + sizeof(VU_ID)
                + sizeof(VU_ID)
                + sizeof(CampaignTime)
                + sizeof(uchar)
                + sizeof(short);
    }
    else
    {
        // Count route lengths
        w = ingress;

        while (w)
        {
            iw++;
            w = w->GetNextWP();
        }

        w = egress;

        while (w)
        {
            ew++;
            w = w->GetNextWP();
        }

        size += sizeof(uchar)
                + sizeof(short)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(GridIndex)
                + sizeof(CampaignTime)
                + sizeof(CampaignTime)
                + sizeof(ulong)
                + sizeof(short)
                + sizeof(short)
                + sizeof(short)
                + sizeof(uchar)
                + sizeof(uchar)
                + sizeof(MissionRequestClass);
        w = ingress;

        while (w)
        {
            size += w->SaveSize();
            w = w->GetNextWP();
        }

        w = egress;

        while (w)
        {
            size += w->SaveSize();
            w = w->GetNextWP();
        }
    }

    return size;
}

int PackageClass::Save(VU_BYTE **stream)
{
    WayPoint w;
    uchar iw = 0, ew = 0;

    AirUnitClass::Save(stream);

    if (save_log)
    {
        fprintf(save_log, "%08x PackageClass ", *stream - start_save_stream);
        fflush(save_log);
    }

    memcpy(*stream, &elements, sizeof(uchar));
    *stream += sizeof(uchar);
#ifdef CAMPTOOL

    if (gRenameIds)
    {
        for (int i = 0; i < elements; i++)
            element[i].num_ = RenameTable[element[i].num_];

        interceptor.num_ = RenameTable[interceptor.num_];
        awacs.num_ = RenameTable[awacs.num_];
        jstar.num_ = RenameTable[jstar.num_];
        ecm.num_ = RenameTable[ecm.num_];
        tanker.num_ = RenameTable[tanker.num_];
        mis_request.requesterID.num_ = RenameTable[mis_request.requesterID.num_];
        mis_request.targetID.num_ = RenameTable[mis_request.targetID.num_];
    }

#endif
    memcpy(*stream, element, sizeof(VU_ID)*elements);
    *stream += sizeof(VU_ID) * elements;
    memcpy(*stream, &interceptor, sizeof(VU_ID));
    *stream += sizeof(VU_ID);
    memcpy(*stream, &awacs, sizeof(VU_ID));
    *stream += sizeof(VU_ID);
    memcpy(*stream, &jstar, sizeof(VU_ID));
    *stream += sizeof(VU_ID);
    memcpy(*stream, &ecm, sizeof(VU_ID));
    *stream += sizeof(VU_ID);
    memcpy(*stream, &tanker, sizeof(VU_ID));
    *stream += sizeof(VU_ID);
    memcpy(*stream, &wait_cycles, sizeof(uchar));
    *stream += sizeof(uchar);

    // If this package has already been planned, we can save some room
    if (Final() && !wait_cycles)
    {
        memcpy(*stream, &requests, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &responses, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &mis_request.mission, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &mis_request.context, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &mis_request.requesterID, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(*stream, &mis_request.targetID, sizeof(VU_ID));
        *stream += sizeof(VU_ID);
        memcpy(*stream, &mis_request.tot, sizeof(CampaignTime));
        *stream += sizeof(CampaignTime);
        memcpy(*stream, &mis_request.action_type, sizeof(uchar));
        *stream += sizeof(uchar);
        memcpy(*stream, &mis_request.priority, sizeof(short));
        *stream += sizeof(short);
    }

    // Otherwise, we'd better save everything
    else
    {
        // Count route lengths
        w = ingress;

        while (w)
        {
            iw++;
            w = w->GetNextWP();
        }

        w = egress;

        while (w)
        {
            ew++;
            w = w->GetNextWP();
        }

        memcpy(*stream, &flights, sizeof(uchar));
        *stream += sizeof(uchar);
        memcpy(*stream, &wait_for, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &iax, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &iay, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &eax, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &eay, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &bpx, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &bpy, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &tpx, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &tpy, sizeof(GridIndex));
        *stream += sizeof(GridIndex);
        memcpy(*stream, &takeoff, sizeof(CampaignTime));
        *stream += sizeof(CampaignTime);
        memcpy(*stream, &tp_time, sizeof(CampaignTime));
        *stream += sizeof(CampaignTime);
        // package flags need to be saved always... MOVE IN FUTURE
        memcpy(*stream, &package_flags, sizeof(ulong));
        *stream += sizeof(ulong);
        memcpy(*stream, &caps, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &requests, sizeof(short));
        *stream += sizeof(short);
        memcpy(*stream, &responses, sizeof(short));
        *stream += sizeof(short);
        // save routes
        memcpy(*stream, &iw, sizeof(uchar));
        *stream += sizeof(uchar);
        w = ingress;

        while (w)
        {
            w->Save(stream);
            w = w->GetNextWP();
        }

        memcpy(*stream, &ew, sizeof(uchar));
        *stream += sizeof(uchar);
        w = egress;

        while (w)
        {
            w->Save(stream);
            w = w->GetNextWP();
        }

        memcpy(*stream, &mis_request, sizeof(MissionRequestClass));
        *stream += sizeof(MissionRequestClass);
    }

    return PackageClass::SaveSize();
}

// event handlers
int PackageClass::Handle(VuFullUpdateEvent *event)
{
    return (AirUnitClass::Handle(event));
}

#define AIRBASE_ATTACK_WARNING_RANGE 25

int PackageClass::MoveUnit(CampaignTime time)
{
    Unit e;
    e = GetFirstUnitElement();

    if (!e)
    {
        // This package is gone
        KillUnit();
        return 0;
    }

    return 1;
}

int PackageClass::CheckNeedRequests(void)
{
    if (Final() || Aborted())
        return -1;

    Unit e;

    // Check if we're waiting on planning elements
    if (wait_cycles)
        wait_cycles--;

    if (!wait_cycles || Camp_GetCurrentTime() > takeoff + (AMIS_TAKEOFF_DELAY - 1) * CampaignMinutes)
    {
        // 2001-09-16 REMOVED by M.N. We don't need this anymore - is done by AddTankerWaypoints result
        // -> If no tanker, packageelement->KillUnit();
        /* if (wait_for & AMIS_NEEDTANKER)
         {
         // Cancel package if no tanker planned
         wait_for = 0;
         KillUnit();
         return 0;
         } */
        if (wait_for & AMIS_BARCAP || wait_for & AMIS_SWEEP)
        {
            // if we're still waiting on these, they arn't planned yet and probably won't be.
            wait_for |= AMIS_BARCAP | AMIS_SWEEP;
            wait_for ^= AMIS_BARCAP | AMIS_SWEEP;
        }

        if (package_flags & AMIS_ADDBDA && mis_request.priority > MINIMUM_BDA_PRIORITY)
        {
            MissionRequestClass mis;
            Objective target;

            // Add BDA with any spare aircraft
            GetUnitDestination(&mis.tx, &mis.ty);
            target = GetObjectiveByXY(mis.tx, mis.ty);

            if (target)
            {
                mis.mission = AMIS_BDA;
                mis.who = GetTeam();
                mis.vs = target->GetTeam();
                mis.targetID = target->Id();
                mis.target_num = 255;
                mis.aircraft = MissionData[mis.mission].str;
                mis.tot = mis_request.tot + (CampaignTime)(MissionData[mis.mission].separation) * CampaignSeconds;
                mis.tot_type = TYPE_EQ;
                mis.roe_check = ROE_AIR_ENGAGE;
                mis.caps = caps | MissionData[mis.mission].caps;
                mis.speed = mis_request.speed;
                mis.priority = GetPriority(&mis);
                e = AttachFlight(&mis, this);

                if (e)
                {
                    if (e->BuildMission(&mis) == PRET_SUCCESS)
                        RecordFlightAddition((Flight)e, &mis, 0);
                    else
                        CancelFlight((Flight)e);
                }
            }
        }

        // 2001-09-11 ADDED BY M.N. if the packags wants a tanker AND the package
        // really *needs* a tanker, add refueling waypoints

        if (g_bTankerWaypoints)
        {
            if ((wait_for & AMIS_ADDTANKER) && (package_flags & AMIS_NEEDTANKER))
            {
                e = GetFirstUnitElement();
                Flight f = (Flight)e;

                while (e)
                {
                    // add to all package elements that really need to refuel
                    if (e->GetUnitMission() != AMIS_TANKER && f->refuel != 0)
                    {
                        if (!AddTankerWayPoint(f, f->refuel))
                        {
                            // M.N. remove the kill unit call - the 2D fuelneeded calculation has a too high
                            // variance so that we shouldn't delete the package here
                            // e->KillUnit();
                            break;
                        }
                    }

                    e = GetNextUnitElement();
                    f = (Flight)e;
                }
            }
        }

        // END OF ADDED SECTION

        // Now finalize our component flights
        e = GetFirstUnitElement();

        while (e)
        {
            FinalizeFlight(e, flights);
            e = GetNextUnitElement();
        }

        if (flights < 2)
        {
            // This package isn't really needed, only parent to one flight.
            // Can we just promote the flight to parent status and remove the package?
        }

        SetFinal(1);
        package_flags = 0;
    }

    return 0;
}

int PackageClass::BuildPackage(MissionRequest mis, F4PFList assemblyList)
{
    int targets = 0, tar = 0, retval = PRET_SUCCESS, result;
    int targetf[5], targetd = 0, hs, ls, bs = 0;
    uchar targeted[128];
    Flight flight = NULL, add_at_end = NULL;
    CampEntity target = NULL;
    MissionRequestClass newmis;

    SetUnitDestination(mis->tx, mis->ty);
    SetLocation(0, 0);
    mis_request = *mis;
    interceptor = FalconNullId;
    package_flags = MissionData[mis->mission].flags;
    escort_type = MissionData[mis->mission].escorttype; // 2001-09-19 M.N.

    aa_strength = 0;
    flights = 0;
    SetFinal(0);

#ifdef KEV_ADEBUG
    MonoPrint("Trying to build team %d %s mission (%d) at %d,%d\n", mis->who, MissStr[mis->mission], mis->mission, mis->tx, mis->ty);
#endif

    mis->min_to = 127;
    mis->max_to = -127;

    // 1. Analyse target, determine # of strikes (and type?) needed.
    memset(targeted, 0, FEATURES_PER_OBJ);

    if (mis->targetID)
        target = FindEntity(mis->targetID);

    if (target && target->IsObjective())
    {
        if (mis->target_num < FEATURES_PER_OBJ)
        {
            targets = 1;
            targetf[tar] = mis->target_num;
            targeted[mis->target_num] = 1;
        }
        else
        {
            // Plan enough strikes to get the target to 0% efficiency (assuming one target per flight)
            int stat, f, j, count = 0;
            short fid, fid2;

            stat = ((Objective)target)->GetObjectiveStatus();

            while (stat > 0 && tar < 5 && targets < 4 && count < 10)
            {
                count++;
                f = BestTargetFeature((Objective)target, targeted);

                if (f >= FEATURES_PER_OBJ || !((Objective)target)->GetFeatureValue(f))
                {
                    count = 10;
                    continue;
                }

                targeted[f] = 1;

                for (j = 0; j < targets; j++)
                {
                    // Check to make sure the types are different - otherwise it looks weird.
                    fid = ((Objective)target)->GetFeatureID(targetf[j]);
                    fid2 = ((Objective)target)->GetFeatureID(f);

                    if (Falcon4ClassTable[fid].vuClassData.classInfo_[VU_TYPE] == Falcon4ClassTable[fid2].vuClassData.classInfo_[VU_TYPE])
                        j = 100;
                }

                if (j > 50)
                    continue;

                stat -= ((Objective)target)->GetFeatureValue(f);

                if (MissionData[mis->mission].str > 2)

                    // TJL 10/24/03 Allow for Large strike packages in campaign
                    if (g_bLargeStrike)
                    {
                        stat = 100; //TJL 10/24/03 Multiple 4 ships
                    }
                    else
                    {
                        stat = 0; // Never fly multiple 4 ship flights
                    }

                targetf[tar] = f;
                tar++;
                targets++;

                // Force a second strike for high priority packages (the ATM_HIGH_PRIORITY define
                // is a hack - probably should read in from AIInputs)
                if (mis->priority > ATM_HIGH_PRIORITY && targets < 2)
                    stat = 100;
            }

            if (targets < 1)
                return PRET_NOTARGET;
        }

        if (targets > 1)
        {
            // Reduce number of flights while keeping 2 aircraft per target
            mis->aircraft = targets * 2;
            targets = 1;

            // Limit number of aircraft assigned to low priority targets
            if (mis->priority < ATM_HIGH_PRIORITY)
                mis->aircraft = 4;

            if (mis->aircraft > 4)
            {
                mis->aircraft = 4;
                targets = 2;
            }
        }
    }
    else if (target && target->IsUnit())
    {
        targets = 1;
        targetf[tar] = 255;

        if (mis->mission == AMIS_SEADSTRIKE)
        {
            UnitClassDataType *uc = ((Unit)target)->GetUnitClassData();

            if (uc->RadarVehicle < 255 && ((Unit)target)->GetNumVehicles(uc->RadarVehicle))
                targetf[tar] = uc->RadarVehicle;
        }

        if (mis->mission == AMIS_ONCALLCAS)
        {
            targets = ONCALL_CAS_FLIGHTS_PER_REQUEST;
            memset(targetf, 255, 5);
        }
    }
    else // Location
    {
        targets = 1;
        targetf[tar] = 255;
    }

    // Check target viability (SAM coverage at target)
    ls = ScoreThreatFast(mis->tx, mis->ty, GetAltitudeLevel(MissionData[mis->mission].minalt * 100), mis->who);
    hs = ScoreThreatFast(mis->tx, mis->ty, GetAltitudeLevel(MissionData[mis->mission].maxalt * 100), mis->who);

    if (ls > MIN_SEADESCORT_THREAT || hs > MIN_SEADESCORT_THREAT)
        targetd |= NEED_SEAD;

    if (mis->priority > ATM_HIGH_PRIORITY && ls && hs)
        targetd |= NEED_SEAD;

    if (package_flags & AMIS_HIGHTHREAT)
        tar = MAX_FLYMISSION_HIGHTHREAT;
    else if (package_flags & AMIS_NOTHREAT)
        tar = MAX_FLYMISSION_NOTHREAT;
    else
        tar = MAX_FLYMISSION_THREAT;

    if (ls > tar && hs > tar)
    {
        // If the threat is so high even SEAD can't get in, just cancel now.
        if (ls > MAX_FLYMISSION_HIGHTHREAT && hs > MAX_FLYMISSION_HIGHTHREAT)
            return PRET_CANCELED;

        // Trigger an OCA strike mission and cancel this mission
        CallInOCAStrikes(mis);
        return PRET_CANCELED;
    }

    tar = 0;

    while (targets)
    {
        // 2. Create and build these strikes
        mis->target_num = targetf[tar];
        mis->caps |= MissionData[mis->mission].caps;

        if (!mis->aircraft)
            mis->aircraft = MissionData[mis->mission].str;

        flight = AttachFlight(mis, this);

        if (flight)
        {
            mis->tx = mis_request.tx;
            mis->ty = mis_request.ty;

            if (MissionData[mis->mission].loitertime)
                mis->tot = mis_request.tot + MissionData[mis->mission].loitertime * flights * CampaignMinutes;
            else
                mis->tot = mis_request.tot + (CampaignTime)((flights) * 10 * CampaignSeconds);

            result = flight->BuildMission(mis);

            if (result == PRET_SUCCESS)
            {
                targetd = RecordFlightAddition(flight, mis, targetd);
                flight->SetTarget(0);
            }
            else
            {
                CancelFlight((Flight)flight);

                if (result == PRET_ABORTED && !flights && (ls || hs))
                {
                    // This flight couldn't get to target
                    return PRET_ABORTED;
                }

                if (result == PRET_CANCELED && !flights)
                {
                    // This flight probably could arm itself or get to the target -
                    // If we can disable us from finding the squadron next time through,
                    // that'd be ideal, otherwise we need to cancel
                    return PRET_CANCELED;
                }
            }
        }

        // If we're gonna add a FAC, do it now
        // This is kinda annoying, because we have to fuck with the flights counter, etc..
        // But if I need to convert my ONCALLCAS to a PRPLANCAS I only want to have to
        // convert one.
        if (flights == 1 && (package_flags & AMIS_ADDFAC))
        {
            // Add FAC directly
            newmis = *mis;
            newmis.mission = AMIS_FAC;
            newmis.target_num = 255;
            newmis.targetID = FalconNullId;
            newmis.tot = mis_request.tot - 5 * CampaignMinutes;
            newmis.caps |= MissionData[newmis.mission].caps;
            newmis.aircraft = MissionData[newmis.mission].str;
            newmis.flags = REQF_USERESERVES;
            newmis.priority = 0;
            newmis.priority = GetPriority(&newmis);
            add_at_end = AttachFlight(&newmis, this);
#ifdef DEBUG
            gFACrequested++;

            if (add_at_end)
                gFACgot++;

#endif

            if (add_at_end)
            {
                if (add_at_end->BuildMission(&newmis) != PRET_SUCCESS)
                {
                    CancelFlight((Flight)add_at_end);
                    add_at_end = NULL;
                }
                else
                    RemoveChild(add_at_end->Id()); // Play games to get the ordering right
            }
            else
            {
                // No FAC available - we need to convert our ONCALLCAS to PREPLANCAS or cancel
                flight = (Flight) GetFirstUnitElement();
                mis->tx = mis_request.tx;
                mis->ty = mis_request.ty;
                mis_request.mission = mis->mission = AMIS_PRPLANCAS;

                if (flight->BuildMission(mis) != PRET_SUCCESS)
                {
                    CancelFlight((Flight)flight);
                    DeleteWPList(ingress);
                    ingress = NULL;
                    DeleteWPList(egress);
                    egress = NULL;
                    DisposeWayPoints();
                    return PRET_CANCELED;
                }

                targets = 1;
            }
        }

        targets--;
        tar++;
    }

    // Correct for any weirded out target locations (ie: ONCALLCAS missions)
    mis->tx = mis_request.tx;
    mis->ty = mis_request.ty;

    if (add_at_end)
    {
        AddUnitChild(add_at_end);
        flights++;
    }

    if (!flights || !flight)
        return PRET_NO_ASSETS;

#ifdef KEV_ADEBUG
    MonoPrint("Building team #%d %s mission (%d) at %d,%d\n", mis->who, MissStr[mis_request.mission], mis_request.mission, mis->tx, mis->ty);
#endif
    //TJL 11/13/03 Scene of a repeated CTD
    /*
    if (flight->IsHelicopter())
     {
     // Helocopter flights don't make any requests or ask for support
     return PRET_SUCCESS;
     }
    */

    // 3. Trigger required mission requests
    if ((package_flags & AMIS_ADDSEAD) && (targetd & NEED_SEAD))
    {
        // Add SEAD directly
        newmis = *mis;
        newmis.mission = AMIS_SEADESCORT;
        newmis.targetID = element[0];
        newmis.target_num = 255;
        newmis.tot = mis_request.tot;
        newmis.caps |= MissionData[newmis.mission].caps;
        newmis.aircraft = MissionData[newmis.mission].str;
        newmis.priority = 0;
        newmis.priority = GetPriority(&newmis);
        // newmis.flags = REQF_USERESERVES;
        flight = AttachFlight(&newmis, this);
#ifdef DEBUG
        gSEADrequested++;

        if (flight)
            gSEADgot++;

#endif

        if (flight)
        {
            newmis.tot = mis_request.tot + (CampaignTime)(MissionData[newmis.mission].separation) * CampaignSeconds;

            if (flight->BuildMission(&newmis) == PRET_SUCCESS)
            {
                targetd = RecordFlightAddition(flight, mis, targetd);
                flight->SetUnitMissionTarget(GetMainFlightID());
            }
            else
                CancelFlight((Flight)flight);
        }

#ifdef KEV_ADEBUG
        else
            MonoPrint("Failed to find SEAD Escort!\n");

#endif
    }

    // Marco edit - We want Escort regardless of threat
    if ((package_flags & AMIS_ADDESCORT))  // && mis->vs && TeamInfo[mis->vs]->atm->averageCAStrength > aa_strength)
    {
        // Add ESCORT directly
        newmis = *mis;
        newmis.mission = escort_type; // 2001-11-10 Modified by M.N. use requested escort type
        newmis.targetID = element[0];
        newmis.target_num = 255;
        newmis.tot = mis_request.tot;
        newmis.caps |= MissionData[newmis.mission].caps;
        newmis.aircraft = MissionData[newmis.mission].str;
        newmis.priority = GetPriority(&newmis);
        // newmis.flags = REQF_USERESERVES;
        flight = AttachFlight(&newmis, this);

        if (flight)
        {
            newmis.tot = mis_request.tot + (CampaignTime)(MissionData[newmis.mission].separation) * CampaignSeconds;

            if (flight->BuildMission(&newmis) == PRET_SUCCESS)
            {
                targetd = RecordFlightAddition(flight, mis, targetd);
                flight->SetUnitMissionTarget(GetMainFlightID());
            }
            else
                CancelFlight((Flight)flight);
        }
    }

    if (package_flags & AMIS_ADDBARCAP)
    {
        // Request and enemy BARCAP mission
        newmis.requesterID = Id();
        newmis.targetID = GetMainFlightID();
        newmis.vs = GetTeam();
        newmis.tot = mis_request.tot - 240 + (rand() % 120 * CampaignSeconds);
        newmis.tot_type = TYPE_EQ;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        newmis.match_strength = aa_strength;
        newmis.mission = AMIS_BARCAP;
        newmis.roe_check = ROE_AIR_ENGAGE;
        newmis.priority = mis->priority / 5;

        if (MissionData[mis_request.mission].skill == ARO_GA)
            newmis.context = enemyCASAircraftPresent;
        else
            newmis.context = enemyStrikesExpected;

        newmis.flags = REQF_NEEDRESPONSE | REQF_ONETRY;

        if (mis->flags & REQF_PART_OF_ACTION)
            newmis.flags |= REQF_PART_OF_ACTION;

        newmis.action_type = mis->action_type;
        newmis.aircraft = 2 * flights;

        if (newmis.aircraft > 4)
            newmis.aircraft = 4;

        newmis.RequestEnemyMission();
        wait_for |= AMIS_ADDBARCAP;
        wait_cycles = (uchar)PACKAGE_CYCLES_TO_WAIT;
#ifdef DEBUG
        gBARCAPrequested++;
#endif
    }

    if (package_flags & AMIS_ADDSWEEP)
    {
        // Request an enemy Sweep mission
        newmis.requesterID = Id();
        newmis.targetID = GetMainFlightID();
        newmis.vs = GetTeam();
        newmis.tot = mis_request.tot - 60 + (rand() % 120 * CampaignSeconds);
        newmis.tot_type = TYPE_LE;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        newmis.match_strength = aa_strength;
        newmis.mission = AMIS_SWEEP;
        newmis.priority = 0;
        newmis.roe_check = ROE_AIR_ENGAGE;

        if (MissionData[mis_request.mission].skill == ARO_GA || MissionData[mis_request.mission].skill == ARO_REC)
            newmis.context = enemyCASAircraftPresent;
        else if (MissionData[mis_request.mission].skill == ARO_ASW)
            newmis.context = enemyAircraftPresent;
        else
            newmis.context = enemySupportAircraftPresent;

        if (mis->flags & REQF_PART_OF_ACTION)
            newmis.flags |= REQF_PART_OF_ACTION;

        newmis.action_type = mis->action_type;
        newmis.flags = REQF_NEEDRESPONSE | REQF_ONETRY;
        newmis.aircraft = 2 * flights;

        if (newmis.aircraft > 4)
            newmis.aircraft = 4;

        newmis.RequestEnemyMission();
        wait_for |= AMIS_ADDSWEEP;
        wait_cycles = (uchar)PACKAGE_CYCLES_TO_WAIT;
#ifdef DEBUG
        gSWEEPrequested++;
#endif
    }

    FindSupportFlights(mis, targetd);

#ifdef DEBUG

    if (mis->mission == AMIS_BARCAP)
        gBARCAPgot++;

    if (mis->mission == AMIS_SWEEP)
        gSWEEPgot++;

#endif
    return PRET_SUCCESS;
}

// This records important data from the flight passed into the package's structures
int PackageClass::RecordFlightAddition(Flight flight, MissionRequest mis, int targetd)
{
    flights++;
    aa_strength += GetUnitScore(flight, Air);

    if (flights == 1)
    {
        WayPoint w, aw = NULL, bw = NULL, tw = NULL, eaw = NULL, lw = NULL;
        int intarget = 0;

        // Do some stuff for the first flight only
        mis->speed = flight->GetCombatSpeed();
        mis_request.speed = mis->speed;
        mis_request.tot = flight->GetUnitTOT();

        // If we can add SEAD, and havn't already decided to, check if we need to
        if ((package_flags & AMIS_ADDSEAD) && !(targetd & NEED_SEAD))
            targetd |= CheckPathThreats(flight);
        // If we can add ECM, check if we need to
        else if (package_flags & AMIS_ADDECM)
            targetd |= CheckPathThreats(flight);

        if (!(MissionData[mis->mission].flags & AMIS_TARGET_ONLY))
        {
            // Find assembly points
            w = flight->GetFirstUnitWP();

            while (w)
            {
                if (w->GetWPFlags() & WPF_ASSEMBLE && !aw)
                    aw = w;

                if (w->GetWPFlags() & WPF_BREAKPOINT)
                    bw = w;

                if (w->GetWPFlags() & WPF_TARGET || w->GetWPFlags() & WPF_IP || w->GetWPFlags() & WPF_CP || /* w->GetWPFlags() & WPF_TURNPOINT || */ w->GetWPFlags() & WPF_REPEAT)
                {
                    if (!bw)
                        bw = lw;

                    if (lw->GetWPFlags() & WPF_TARGET || lw->GetWPFlags() & WPF_CP)
                        tw = w; // Just passed the target waypoint

                    intarget = 1;
                }
                else if (intarget) // && !tw)
                {
                    tw = w; // Just passed the target waypoint
                    intarget = 0;
                }
                else
                    intarget = 0;

                if (w->GetWPFlags() & WPF_ASSEMBLE)
                    eaw = w;

                lw = w;
                w = w->GetNextWP();
            }

            if (!bw && MissionData[mis->mission].flags & AMIS_NO_BREAKPT)
                bw = tw;

            ShiAssert(bw && tw && aw && eaw)
            // copy ingress and egress paths to package
            w = bw->GetNextWP();
            ingress =  CloneWPToList(aw, w);
            w = eaw->GetNextWP();
            egress =  CloneWPToList(tw, w);
        }
    }

    return targetd;
}

void PackageClass::FindSupportFlights(MissionRequest mis, int targetd)
{
    MissionRequestClass newmis;

    if (!(package_flags & AMIS_SUPPORT_MASK))
        return;

    if (TeamInfo[GetTeam()] && TeamInfo[GetTeam()]->atm && TeamInfo[GetTeam()]->atm->packageList)
    {
        // Look for any existing missions which can help us out.
        VuListIterator packit(TeamInfo[GetTeam()]->atm->packageList);
        Package pack;
        Flight flight;
        MissionRequest pmis;
        GridIndex px, py;
        float dist;
        float bestAWACSDist = (float)Map_Max_X * Map_Max_Y; // Reasonable maximum distance squared
        float bestJSTARDist = (float)Map_Max_X * Map_Max_Y; // Reasonable maximum distance squared
        float bestTANKDist = (float)Map_Max_X * Map_Max_Y; // Reasonable maximum distance squared
        float bestECMDist = (float)Map_Max_X * Map_Max_Y; // Reasonable maximum distance squared
        CampaignTime startTime, endTime;

        startTime = mis->tot - 10 * CampaignMinutes;
        endTime = mis->tot + (MissionData[mis->mission].loitertime + 10) * CampaignMinutes;
        pack = (Package) GetFirstUnit(&packit);

        while (pack)
        {
            pmis = pack->GetMissionRequest();
            flight = (FlightClass*) pack->GetFirstUnitElement();

            if (flight && !flight->Aborted() && pmis->tot < startTime)
            {
                if ((package_flags & AMIS_ADDAWACS) && flight->GetUnitMission() == AMIS_AWACS)
                {
                    pack->GetUnitDestination(&px, &py);
                    dist = (float)DistSqu(mis->tx, mis->ty, px, py);

                    if (pmis->tot + MissionData[AMIS_AWACS].loitertime * CampaignMinutes > endTime && dist < bestAWACSDist)
                    {
                        awacs = flight->Id();
                        bestAWACSDist = dist;
                    }
                }

                if ((package_flags & AMIS_ADDJSTAR) && flight->GetUnitMission() == AMIS_JSTAR)
                {
                    pack->GetUnitDestination(&px, &py);
                    dist = (float)DistSqu(mis->tx, mis->ty, px, py);

                    if (pmis->tot + MissionData[AMIS_JSTAR].loitertime * CampaignMinutes > endTime && dist < bestJSTARDist)
                    {
                        jstar = flight->Id();
                        bestJSTARDist = dist;
                    }
                }

                if ((package_flags & AMIS_ADDECM) && (targetd & NEED_ECM) && flight->GetUnitMission() == AMIS_ECM)
                {
                    pack->GetUnitDestination(&px, &py);
                    dist = (float)DistSqu(mis->tx, mis->ty, px, py);

                    if (pmis->tot + MissionData[AMIS_ECM].loitertime * CampaignMinutes > endTime && dist < bestECMDist)
                    {
                        ecm = flight->Id();
                        bestECMDist = dist;
                    }
                }

                if ((package_flags & AMIS_ADDTANKER) && flight->GetUnitMission() == AMIS_TANKER)
                {
                    GridIndex x, y;
                    pack->GetUnitDestination(&px, &py);
                    GetUnitAssemblyPoint(0, &x, &y);

                    if (x && y)
                        dist = (float)DistSqu(x, y, px, py);
                    else
                        dist = (float)DistSqu(mis->tx, mis->ty, px, py);

                    if (pmis->tot + MissionData[AMIS_TANKER].loitertime * CampaignMinutes > endTime && dist < bestTANKDist)
                    {
                        tanker = flight->Id();
                        bestTANKDist = dist;
                    }
                }
            }

            pack = (Package) GetNextUnit(&packit);
        }
    }

    // Now request anything we couldn't find
    if ((package_flags & AMIS_ADDAWACS) && awacs == FalconNullId)
    {
        newmis.requesterID = Id();
        newmis.targetID = FalconNullId;
        newmis.who = GetTeam();
        newmis.vs = 0;
        newmis.tot = mis_request.tot;
        newmis.tot_type = TYPE_LE;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        newmis.mission = AMIS_AWACS;
        newmis.roe_check = ROE_AIR_OVERFLY;
        newmis.context = friendlyAWACSNeeded;
        newmis.aircraft = 0;
        newmis.priority = 0;
        newmis.flags = REQF_NEEDRESPONSE;
        newmis.RequestMission();
    }

    if ((package_flags & AMIS_ADDJSTAR) && jstar == FalconNullId)
    {
        newmis.requesterID = Id();
        newmis.targetID = FalconNullId;
        newmis.who = GetTeam();
        newmis.vs = 0;
        newmis.tot = mis_request.tot;
        newmis.tot_type = TYPE_LE;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        newmis.mission = AMIS_JSTAR;
        newmis.roe_check = ROE_AIR_OVERFLY;
        newmis.context = enemyGroundForcesPresent;
        newmis.aircraft = 0;
        newmis.priority = 0;
        newmis.flags = REQF_NEEDRESPONSE;
        newmis.RequestMission();
    }

    // 4. Trigger conditional mission requests.
    if ((package_flags & AMIS_ADDECM) && (targetd & NEED_ECM) && ecm == FalconNullId)
    {
        newmis.requesterID = Id();
        newmis.targetID = FalconNullId;
        newmis.who = GetTeam();
        newmis.vs = 0;
        newmis.tot = mis_request.tot;
        newmis.tot_type = TYPE_EQ;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        newmis.mission = AMIS_ECM;
        newmis.roe_check = ROE_AIR_OVERFLY;
        newmis.context = enemyRadarPresent;
        newmis.aircraft = 0;
        newmis.priority = 0;
        newmis.flags = REQF_NEEDRESPONSE;
        newmis.RequestMission();
    }

    if ((package_flags & AMIS_ADDTANKER) && tanker == FalconNullId)
    {
        GridIndex x, y;
        // Make sure some tankers are going to be here - later only ask for it if we'll be
        // short on fuel.
        newmis.requesterID = Id();
        newmis.targetID = FalconNullId;
        newmis.who = GetTeam();
        newmis.vs = 0;
        newmis.tot = mis_request.tot;
        newmis.tot_type = TYPE_LE;
        newmis.tx = mis->tx;
        newmis.ty = mis->ty;
        GetUnitAssemblyPoint(0, &x, &y);

        if (x && y)
        {
            newmis.tx = x;
            newmis.ty = y;
        }

        newmis.mission = AMIS_TANKER;
        newmis.roe_check = ROE_AIR_OVERFLY;
        newmis.context = friendlyAssetsRefueling;
        newmis.priority = 50; // We REALLY need this tanker
        newmis.aircraft = 0;
        newmis.flags = REQF_NEEDRESPONSE | REQF_ONETRY;
        newmis.RequestMission();
        wait_for |= AMIS_ADDTANKER;
        wait_cycles = (uchar)PACKAGE_CYCLES_TO_WAIT;
    }
}

void PackageClass::HandleRequestReceipt(int type, int them, VU_ID triggered_flight)
{
    MissionRequestClass mis;
    Unit flight, enemy;

    if (!wait_cycles)
        return; // Error of sorts - response mission was planned after our wait period timed out

    switch (type)
    {
        case AMIS_BARCAP:
        case AMIS_SWEEP:
            wait_for |= AMIS_BARCAP | AMIS_SWEEP;
            wait_for ^= AMIS_BARCAP | AMIS_SWEEP;
            responses |= PRESPONSE_CA;
            interceptor = triggered_flight;
            enemy = FindUnit(triggered_flight);

            if (!enemy)
                return;

            mis.mission = MissionData[mis_request.mission].escorttype;
            mis.who = GetTeam();
            mis.vs = them;
            mis.target_num = 255;
            mis.aircraft = MissionData[mis.mission].str;
            // skip this if our current package has enough air strength
            mis.match_strength = GetUnitScore(enemy, Air);

            // mis.match_strength = enemy->GetUnitRoleScore(ARO_CA, CALC_TOTAL, USE_EXP | USE_VEH_COUNT);
            if (aa_strength > mis.match_strength)
                return;

            mis.match_strength -= aa_strength; // we only want to match the excess
            mis.tot = mis_request.tot + MissionData[mis.mission].separation * CampaignSeconds;
            mis.tot_type = TYPE_EQ;
            mis.roe_check = ROE_AIR_ENGAGE;
            mis.priority = (mis.match_strength) / 2;

            if (mis_request.flags & REQF_PART_OF_ACTION)
            {
                mis.flags = REQF_PART_OF_ACTION;
                mis.action_type = mis_request.action_type;
            }

            mis.targetID = triggered_flight;

            // Mission location is assembly point initially (if we have one)
            // So we find the closest squadron to the assembly point
            if (iax > 0 && iay > 0)
            {
                mis.tx = iax;
                mis.ty = iay;
            }
            else
                GetUnitDestination(&mis.tx, &mis.ty);

            if (mis.mission == AMIS_ESCORT || mis.mission == AMIS_HAVCAP)
            {
                // Add a new flight to this package
                mis.caps = caps | MissionData[mis.mission].caps;
                mis.speed = mis_request.speed;
                mis.targetID = element[0];
                mis.priority = GetPriority(&mis);
                flight = AttachFlight(&mis, this);
#ifdef DEBUG
                gESCORTrequested++;

                if (flight)
                    gESCORTgot++;

#endif

                if (flight)
                {
                    // Now set the mission destination correctly
                    GetUnitDestination(&mis.tx, &mis.ty);

                    if (flight->BuildMission(&mis) == PRET_SUCCESS)
                    {
                        RecordFlightAddition((Flight)flight, &mis, 0);
                        flight->SetUnitMissionTarget(GetMainFlightID());
                    }
                    else
                        CancelFlight((Flight)flight);
                }

#ifdef KEV_ADEBUG
                else
                    MonoPrint("Failed to find CA Escort!\n");

#endif
            }
            else if (mis.mission)
            {
                // Request a new package (Sweep or RESCAP mostly)
                if (mis.mission == AMIS_SWEEP && mis_request.mission >= AMIS_FAC && mis_request.mission <= AMIS_CAS)
                    mis.context = friendlyCASExpected;
                else if (mis.mission == AMIS_RESCAP)
                    mis.context = friendlyRescueExpected;
                else
                    mis.context = friendlyAssetsExpected;

                mis.requesterID = Id();
                mis.RequestMission();
            }

            break;

        case AMIS_TANKER:
            responses |= PRESPONSE_TANKER;
            tanker = triggered_flight;
            break;

        case AMIS_AWACS:
            responses |= PRESPONSE_AWACS;
            awacs = triggered_flight;
            break;

        case AMIS_JSTAR:
            responses |= PRESPONSE_JSTAR;
            jstar = triggered_flight;
            break;

        case AMIS_ECM:
            responses |= PRESPONSE_ECM;
            ecm = triggered_flight;
            break;

        default:
            break;
    }
}

void PackageClass::SetUnitAssemblyPoint(int type, GridIndex x, GridIndex y)
{
    switch (type)
    {
        case 0:
            iax = x;
            iay = y;
            break;

        case 1:
            eax = x;
            eay = y;
            break;

        case 2:
            bpx = x;
            bpy = y;
            break;

        case 3:
            tpx = x;
            tpy = y;
            break;
    }
}

void PackageClass::GetUnitAssemblyPoint(int type, GridIndex *x, GridIndex *y)
{
    switch (type)
    {
        case 0:
            *x = iax;
            *y = iay;
            break;

        case 1:
            *x = eay;
            *y = eay;
            break;

        case 2:
            *x = bpy;
            *y = bpy;
            break;

        case 3:
            *x = tpx;
            *y = tpy;
            break;
    }
}

void PackageClass::CancelFlight(Flight flight)
{
#ifdef KEV_ADEBUG
    MonoPrint("FLIGHT CANCELED (%s)\n", MissStr[flight->GetUnitMission()]);
#endif
    flight->SetDead(1);
    RemoveChild(flight->Id());

    // JPO - another memory leak - lets assume if its not in the database then it s not been added
    if (VuState() < VU_MEM_ACTIVE || flight->Remove() == VU_NO_OP)
    {
        // Never inserted - let vu do the deletion.
        VuReferenceEntity(flight);
        VuDeReferenceEntity(flight);
    }
}

Unit PackageClass::GetFirstUnitElement(void)
{
    c_element = 0;
    return FindUnit(element[c_element]);
}

Unit PackageClass::GetNextUnitElement(void)
{
    c_element++;

    while (c_element < elements)
    {
        if (element[c_element])
            return FindUnit(element[c_element]);

        c_element++;
    }

    c_element = 0;
    return NULL;
}

Unit PackageClass::GetUnitElement(int en)
{
    if (en < elements && element[en])
        return (Unit)vuDatabase->Find(element[en]);

    return NULL;
}

Unit PackageClass::GetUnitElementByID(int eid)
{
    Unit e = NULL;

    if (eid < elements)
        e = (Unit)vuDatabase->Find(element[eid]);

    return e;
}

/* int i=0;

 while (i < elements)
 {
 if (element[i])
 {
 e = (Unit)vuDatabase->Find(element[i]);
 if (e && e->GetUnitElement() == eid)
 return  e;
 }
 i++;
 }
 return NULL;
 }
*/

void PackageClass::AddUnitChild(Unit e)
{
    int i = 0;

    while (element[i] && i < MAX_UNIT_CHILDREN)
    {
        if (element[i] == e->Id())
            return;

        i++;
    }

    if (i < MAX_UNIT_CHILDREN)
        element[i] = e->Id();

    if (i >= elements)
        elements = i + 1;
}

void PackageClass::DisposeChildren(void)
{
    Unit e;
    int i = elements - 1;

    while (i >= 0)
    {
        if (element[i])
        {
            e = (Unit)vuDatabase->Find(element[i]);

            if (e)
                e->KillUnit();

            element[i] = FalconNullId;
            elements--;
        }

        i--;
    }
}

void PackageClass::RemoveChild(VU_ID eid)
{
    int i = 0, j;

    while (i < elements)
    {
        if (element[i] == eid)
        {
            for (j = i; j < MAX_UNIT_CHILDREN - 1; j++)
                element[j] = element[j + 1];

            element[j] = FalconNullId;
            elements--;
        }
        else
            i++;
    }
}

VU_ID PackageClass::GetMainFlightID(void)
{
    Unit e;

    e = GetFirstUnitElement();

    if (e && e->IsFlight() && e->GetUnitMissionID() == 0)
        return e->Id();

    return FalconNullId;
}

Flight PackageClass::GetMainFlight(void)
{
    Unit e;

    e = GetFirstUnitElement();

    if (e && e->IsFlight() && e->GetUnitMissionID() == 0)
        return (Flight)e;

    return NULL;
}

// ================================
// Support Functions
// ================================

// Transfer a flight from it's current package to the one passed
void TransferFlight(Flight flight, Package pack)
{
    Package oldp;

    oldp = (Package)flight->GetUnitParent();

    if (oldp)
        oldp->RemoveChild(flight->Id());

    flight->SetUnitParent(pack);
}

// Creates a new flight, adds aircraft and attaches to the package.
Flight AttachFlight(MissionRequest mis, Package pack)
{
    Squadron squadron;
    Flight flight;
    short tid;
    GridIndex bx, by, x, y;

    if (!TeamInfo[mis->who]->atm)
    {
#ifdef KEV_DEBUG
        MonoPrint("Error, I don't own the ATM!\n");
#endif
        return NULL;
    }

    if (!pack)
        return NULL;

    pack->GetLocation(&bx, &by);

    if (mis->flags & AMIS_IMMEDIATE)
    {
        flight = TeamInfo[mis->who]->atm->FindBestAirFlight(mis); // We steal the aircraft from a current flight (all the aircraft)

        if (!flight)
            return NULL;

        mis->aircraft = flight->GetTotalVehicles();

        // Ok, this package is a go - add it locally
        if (!PackInserted)
        {
            PackInserted = 1;
            vuDatabase->SilentInsert(pack);
        }

        // Transfer the flight to the new parent
        TransferFlight((Flight)flight, pack);
    }
    else
    {
        squadron = TeamInfo[mis->who]->atm->FindBestAir(mis, bx, by);

        if (!squadron)
            return NULL;

        if (!bx && !by) // Call this our home base for this package set
        {
            squadron->GetLocation(&bx, &by);
            pack->SetLocation(bx, by);
        }

        // Ok, this package is a go - add it locally
        if (!PackInserted)
        {
            PackInserted = 1;
            vuDatabase->SilentInsert(pack);
        }

        tid = GetClassID(DOMAIN_AIR, CLASS_UNIT, TYPE_FLIGHT, squadron->GetSType(), squadron->GetSPType(), 0, 0, 0);
#ifdef DEBUG
        ShiAssert(tid);

        if (!tid)
            return NULL;

#endif
        tid += VU_LAST_ENTITY_TYPE;
        flight = NewFlight(tid, pack, squadron);

        if (!flight)
            return NULL;

        flight->SetOwner(squadron->GetOwner());
        squadron->GetLocation(&x, &y);
        flight->SetLocation(x, y);
        pack->GetUnitDestination(&x, &y);
        flight->SetUnitDestination(x, y);
        flight->SetFinal(0);

        // If we've got a bomber assigned to a lead strike role, switch the mission type to strat
        // bomb so that everything will be planned correctly
        if (!pack->GetFlights() && MissionData[mis->mission].skill == ARO_S && squadron->GetRating(ARO_SB) > squadron->GetRating(ARO_S))
        {
            mis->mission = AMIS_STRATBOMB;
            pack->GetMissionRequest()->mission = AMIS_STRATBOMB;
        }
    }

    flight->SetUnitMissionID(pack->GetFlights());
#ifdef KEV_ADEBUG
    MonoPrint("Attaching flight %d to package %d\n", flight->GetCampID(), pack->GetCampID());
#endif
    return flight;
}

// Strip or rename unneeded waypoints.
void FinalizeFlight(Unit flight, int flights)
{
    int assem;
    WayPoint w;

#ifdef KEV_ADEBUG
    Unit pack;
    pack = flight->GetUnitParent();
    MonoPrint("Finalizing flight %d, package %d\n", flight->GetCampID(), pack->GetCampID());
#endif

#if 0
#ifdef DEBUG

    if (flight->GetTotalVehicles() <= PILOTS_PER_FLIGHT) // && (MissionData[mis->mission].flags & AMIS_DONT_USE_AC))
    {
        // Verify a few things are correct for this flight
        int acp, acr = flight->GetTotalVehicles();
        acp = 0;

        for (int i = 0; i < PILOTS_PER_FLIGHT; i++)
        {
            if (((FlightClass*)flight)->plane_stats[i] == AIRCRAFT_AVAILABLE)
                acp++;
        }

        ShiAssert(acp == acr);
    }

#endif
#endif

    if (flights > 1 && !(MissionData[flight->GetUnitMission()].flags & AMIS_DONT_COORD) && !(MissionData[flight->GetUnitMission()].flags & AMIS_TARGET_ONLY))
        assem = 1;
    else
        assem = 0;

    w = flight->GetFirstUnitWP();

    while (w)
    {
        if (w->GetWPFlags() & WPF_BREAKPOINT && !assem)
            w->SetWPFlags(w->GetWPFlags() ^ WPF_BREAKPOINT); // Clear our flag

        if (w->GetWPFlags() & WPF_ASSEMBLE && !assem)
        {
            w->SetWPAction(WP_NOTHING); // Clear our action
            w->SetWPRouteAction(MissionData[flight->GetUnitMission()].routewp);
            w->SetWPFlags(w->GetWPFlags() ^ WPF_ASSEMBLE); // Clear our flag
        }

        if (w->GetWPAction() == WP_NOTHING && !(w->GetWPFlags() & 0x4FF))
        {
            // This is an unused waypoint (Nothing action and no flags set)
            // Check if in line or co-existant with other wps, if so, remove
            // KCK NOTE: I'll leave it if it'll cut a large leg in half.
            WayPoint pw, nw;
            GridIndex x, y, px, py, nx, ny;
            float d1, d2, d3;

            pw = w->GetPrevWP();
            nw = w->GetNextWP();

            if (pw && nw)
            {
                w->GetWPLocation(&x, &y);
                pw->GetWPLocation(&px, &py);
                nw->GetWPLocation(&nx, &ny);

                // Check if waypoint is inline with other waypoints
                if (Distance(px, py, nx, ny) < 50)
                {
                    d1 = AngleTo(px, py, x, y);
                    d2 = AngleTo(x, y, nx, ny);
                    d3 = d2 - d1;

                    if (d3 < 0.1F && d3 > -0.1F)
                    {
                        w->DeleteWP();
                        w = pw;
                    }
                }

                // Check if waypoint is co-located with adjacent waypoints
                if (w != pw && ((px == x && py == y) || (x == nx && y == ny)))
                {
                    w->DeleteWP();
                    w = pw;
                }
            }
        }

        w = w->GetNextWP();
    }

    flight->SetFinal(1);
}

// This sends a message to the ATM to remove the package's mission from it's planned list.
// Also - calculate player debrief stuff for player packages.
/*
void CompleteMission(Package pack)
 {
 if (pack->requestID >= 0)
 TeamInfo[pack->GetTeam()]->atm->SendATMMessage(pack->Id(), pack->GetTeam(), FalconAirTaskingMessage::atmCompleteMission, pack->requestID, 0, NULL, 0);
 }
*/

int CallInOCAStrikes(MissionRequest mis)
{
#ifdef USE_HASH_TABLES
    FalconPrivateHashTable list(&CampFilter);
#else
    FalconPrivateList list(&CampFilter);
#endif
    short ts = 0;

    if (mis->mission == AMIS_SEADSTRIKE) // Don't generate recursive SEAD missions
        return 0;

    // Trigger OCA missions
    CollectThreatsFast(mis->tx, mis->ty, 1, mis->who, FIND_NOAIR | FIND_NOMOVERS | FIND_FINDUNSPOTTED | FIND_NODETECT, &list);
    CollectThreatsFast(mis->tx, mis->ty, 99, mis->who, FIND_NOAIR | FIND_NOMOVERS | FIND_FINDUNSPOTTED | FIND_NODETECT, &list);
    TargetThreats(mis->who, mis->priority, &list, LowAir, mis->tot, AMIS_ADDOCASTRIKE, &ts);
    return ts;
}

Flight PackageClass::GetFACFlight(void)
{
    Flight fac;

    if (MissionData[mis_request.mission].skill != ARO_GA)
        return NULL;

    fac = (Flight) GetFirstUnitElement();

    while (fac)
    {
        if (fac->GetUnitMission() == AMIS_FAC)
            return fac;

        fac = (Flight) GetNextUnitElement();
    }

    return NULL;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::SetTanker(VU_ID t)
{
    tanker = t;

    MakePackageDirty(DIRTY_TANKER, DDP[116].priority);
    // MakePackageDirty (DIRTY_TANKER, SEND_EVENTUALLY);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::SetPackageFlags(ulong f)
{
    package_flags |= f;

    MakePackageDirty(DIRTY_PACKAGE_FLAGS, DDP[117].priority);
    // MakePackageDirty (DIRTY_PACKAGE_FLAGS, SEND_EVENTUALLY);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::SetTakeoff(CampaignTime t)
{
    takeoff = t;

    MakePackageDirty(DIRTY_TAKEOFF, DDP[118].priority);
    // MakePackageDirty (DIRTY_TAKEOFF, SEND_EVENTUALLY);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::SetTPTime(CampaignTime t)
{
    tp_time = t;

    MakePackageDirty(DIRTY_TP_TIME, DDP[119].priority);
    // MakePackageDirty (DIRTY_TP_TIME, SEND_EVENTUALLY);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::MakePackageDirty(Dirty_Package bits, Dirtyness score)
{
    if (!IsLocal())
        return;

    if (VuState() != VU_MEM_ACTIVE)
        return;

    if (!IsAggregate())
    {
        score = (Dirtyness)((int) score * 10);
    }

    dirty_package |= bits;

    MakeDirty(DIRTY_PACKAGE, score);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::WriteDirty(unsigned char **stream)
{
    //MonoPrint ("  PC %08x", dirty_package);

    *(uchar *)*stream = dirty_package;
    *stream += sizeof(uchar);

    if (dirty_package & DIRTY_TANKER)
    {
        *(VU_ID*)*stream = tanker;
        *stream += sizeof(VU_ID);
    }

    if (dirty_package & DIRTY_PACKAGE_FLAGS)
    {
        *(ulong*)*stream = package_flags;
        *stream += sizeof(ulong);
    }

    if (dirty_package & DIRTY_TAKEOFF)
    {
        *(CampaignTime*)*stream = takeoff;
        *stream += sizeof(CampaignTime);
    }

    if (dirty_package & DIRTY_TP_TIME)
    {
        *(CampaignTime*)*stream = tp_time;
        *stream += sizeof(CampaignTime);
    }

    dirty_package = 0;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void PackageClass::ReadDirty(unsigned char **stream)
{
    uchar
    bits;

    bits = *(uchar *)*stream;
    *stream += sizeof(uchar);

    //MonoPrint ("  PC %08x", bits);

    if (bits & DIRTY_TANKER)
    {
        tanker = *(VU_ID*)*stream;
        *stream += sizeof(VU_ID);
    }

    if (bits & DIRTY_PACKAGE_FLAGS)
    {
        package_flags = *(ulong*)*stream;
        *stream += sizeof(ulong);
    }

    if (bits & DIRTY_TAKEOFF)
    {
        takeoff = *(CampaignTime*)*stream;
        *stream += sizeof(CampaignTime);
    }

    if (bits & DIRTY_TP_TIME)
    {
        tp_time = *(CampaignTime*)*stream;
        *stream += sizeof(CampaignTime);
    }
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


Intuitive Surgical's two-part fourth-quarter earnings release concluded Thursday with the income portion of the profit-loss statement. You'll recall that the robotic surgery company released preliminary revenue and procedure numbers last week so it could discuss the numbers at the big J.P. MorganHealthcare Conference.
Adjusted revenue increased 4% year over year in the fourth quarter.
The 137 da Vinci systems placed in the fourth quarter was fairly similar to the 138 systems placed in the year-ago quarter.
Procedures performed on the company's robots increased 10% year over year in the fourth quarter, bringing 2014's procedure growth to 9% over 2013.
The increase in procedures helped grow fourth-quarter sales of instruments and accessories by 5% year over year; the slower growth relative to procedures appears to be due to stocking and nothing to be worried about.
Basically, there's nothing in the year-over-year comparisons to get too excited about, but investors can take solace in that the fourth-quarter numbers were a substantial improvement over previous quarters of 2014. For example, the aforementioned 137 systems placed trumped the 87, 96, and 111 systems placed in the three prior quarters.
Despite revenue growth, fourth-quarter adjusted income decreased 4.7% year over year from $193 million last year to $184 million in the recently completed quarter. Earnings per share were down only 1.2% year over year to $4.92 per share thanks to a share buyback last year that reduced the denominator in earnings-per-share calculation.
The culprit in the reduced earnings was a lower gross margin caused by the introduction of the new da Vinci Xi system. Gross margins on product sales slipped from 69.5% in the year-ago quarter to just 65.2% in the fourth quarter of 2014. Heading into 2015, it doesn't appear we'll see much of a rebound in margins, as the company will be hurt negatively by changes in foreign currency exchange rates that will negatively affect margins when foreign sales are translated back into U.S. dollars.
Looking aheadDespite the lower margins, the rapid adoption of the Xi systems -- 97 in the fourth quarter, compared with 50 and 59 in the second and third quarter, respectively -- is a good sign for the future growth. There are certain procedures that can only be performed on the Xi because the robot's arms can reach into all four quadrants of the torso. Increased procedures result in more accessory sales and, as the machines reach capacity, result in sales of a second Xi system at the hospital. Rinse and repeat.
Speaking of going after new procedures, Intuitive Surgical is working on its next-generation system, called the da Vinci Sp, a single-port system that allows all the instruments to enter a single opening, potentially a natural opening, and reach far into the body. In addition to new procedures, the machine could also reduce scarring and recovery time of current procedures.
The Sp system is slated to begin customer testing this year, with the final design that could be submitted to regulatory authorities for approval after their feedback is incorporated.
The article Don't Fret About Intuitive Surgical, Inc.'s Lower Gross Margins originally appeared on Fool.com.
Brian Orelli has no position in any stocks mentioned. The Motley Fool recommends Intuitive Surgical and owns shares of the company. Try any of our Foolish newsletter services free for 30 days. We Fools don't all hold the same opinions, but we all believe that considering a diverse range of insights makes us better investors. The Motley Fool has a disclosure policy.


text:
Ukraine offered the USA new conditions for the transfer of ATACMS missiles to the Ukrainian Armed Forces
Kostia Andreikovets
18:07, 3 october 2022
Ukraine offers the administration of US President Joe Biden to agree on potential targets in the event of the transfer of ATACMS long-range missile systems to the Armed Forces.
This is reported by CNN with reference to US officials.
U.S. officials say that in an effort to overcome White House resistance to providing Ukraine with ATACMS missiles, Ukrainian authorities are now offering the U.S. full and ongoing information on a list of potential Russian targets.
Such transparency gives the USA a "veto right" over the actions of the Armed Forces. This approach will allow the US not to be afraid of strikes on the Russian Federation, which could provoke an escalation of the conflict between the two countries.
The war. The Ukrainian army cleared Lyman, the presidents of 9 countries supported Ukraine's accession to NATO, and the Russian Constitutional Court approved the annexation of Ukrainian territories. Day 222: live coverage
ATACMS has a range of up to 300 kilometers. The Biden administration still believes that providing these systems could be escalating because they could be used to target Russia itself. Currently, the maximum range of weapons that the USA provides to Ukraine is about 80 kilometers. The Biden administration is still not inclined to provide ATACMS systems to Ukraine.
In August, the Pentagon declared that the Armed Forces did not need ATACMS yet. At the same time, Ukraine included them in the list of necessary weapons for the continuation of the counter-offensive.
Noticed an error? Highlight it and press Ctrl + Enter — we will correct
I always interested in — how and why
© 2023 Babel. All rights reserved.
Babel is not against reprints, but first write us
made by ideil.
All right, just want to warn that Бабель uses cookies. Thats how we analyze traffic and set up advertising.

redpajama_set_name: RedPajamaCommonCrawl


text:
Saturday, 24 September 2016 08:11	administrator
21 September 2016: In collaboration with the NUS Botany Laboratory, Department of Biological Sciences, the FloraSG Android app is now available in the Google Play Store. The FloraSG app is designed to provide information on native plant species in Singapore, and thus familiarise the user with some of these species. It can be used as a plant identification tool that works through the selection of a set of characters of plants which best fit the species that the user has encountered. Alternatively, the user may simply browse for information on a known species. Roopal Kondepudi and Rajiv Ratn Shah are the lead developers.
Last Updated on Saturday, 24 September 2016 08:43
Tuesday, 13 September 2016 06:09	administrator
29 August 2016: Rajiv Ratn Shah has been awarded a Student Travel Grant to attend the ACM Multimedia 2016 conference, to be held in Amsterdam, The Netherlands. Congratulations! Rajiv will be presenting his research in the Doctoral Symposium as well as at the Multimedia COMMONS 2016 Workshop.
Friday, 17 June 2016 13:55	administrator
7/8 June 2016: The NUS InnovFest Suzhou 2016 was organized and held at the National University of Singapore Suzhou Research Institute (NUSRI), Suzhou, China. There were more than 30 theme presentations in areas such as biological medical, development and application of computer technology, intelligent hardware, clean energy and new energy, water and environmental science.
26 September 2016: Roger Zimmermann gave a talk at the Bay Area Multimedia Forum (BAMMF) at Intel in Santa Clara. The talk was entitled "DASH Streaming and Software Defined Networking."
ACM Multimedia 2016 TPC Workshop
Thursday, 02 June 2016 09:48	administrator
9 June 2016: Roger Zimmermann attended the ACM Multimedia 2016 TPC Workshop at the Columbia University School of International and Public Affairs and presented a talk entitled: "DASH Streaming and Software Defined Networking."
Last Updated on Monday, 13 June 2016 15:36
Keynote Speaker at JCSSE 2016
Map Matching Patent Application Published
GeoVid Patent Application Published
IDMI Sharing @ Blk 71


Moshe Feiglin, a nationalist member of Prime Minister Benjamin Netanyahu's Likud Party, visited the compound on Thursday, after calling on the Israeli Knesset last week to strengthen Israel's control over the holy site and usurp sovereignty.
The Haram al-Sharif, which includes the Al Aqsa mosque and the Dome of the Rock, is Islam's third holiest site and is known to Jews as the Temple Mount. Israel captured the area from Jordan in the 1967 war.
Hundreds of Palestinians were protesting in the area after Feiglin's visit.
Palestinian religious and political leaders were outraged on Monday when the Knesset's interior affairs committee set up a Jewish commission to supervise daily Jewish incursions into Al Aqsa mosque's courtyard to perform worshipping rituals.
During the Knesset's meeting – the first of its kind since the occupation of East Jerusalem – it was also suggested the courtyard's gates be opened for all Israelis.


We offer a Military discount to those who have served or are currently serving in any branch.
I have never lived somewhere that had such quick maintenance response. Literally a day after I put in a work order, they show up to resolve the issue. Very nice staff who are always available to help. Would 100% recommend to friends and family!
This is wonderful to hear! We're thrilled you've been pleased with the maintenance service you've received here at Academy Park Apartments. If there is ever anything we can do to help make your experience even more of a five-star one, please feel free to let us know!
I recommend that potential tenants speak with former residents prior to choosing this community. This company makes a practice of keeping security deposits due to the unit not being cleaned adequately. They provide no evidence but hire collection agencies to scare people into paying. Good luck.
Overall it was okay. Looks a little older on the outside than what the pic's depicted online. Rooms are pretty spacious. The pool, clubhouse and tennis courts were really nice. A little pricey on the units compared to some other properties that looked a little better on the outside with the same square footage or more. I did like the storage space though that is included -that was a bonus and definitely a nice feature. I am just not convinced it is worth close to 1200 for the 3bed/2bath -and if my memory serves me correctly it doesn't include any utilities either. Definitely not a bad place to live overall.
Where nature and sophistication converge...Boulder Creek Apartments. Come and enjoy our peaceful, country setting conveniently located near everything you need. We are moments away from I-64, I-264, I-265, Bluegrass Industrial Park and charming downtown Jeffersontown. Select from one of our outstanding floor plans designed with you in mind. We offer one, two or three bedroom apartment homes. Some of our unique floor plans even feature lofts! Call us now for more information and your personal tour! We are proudly owned & managed by Brown Capital LLLP.
Last Viewing Ends 1/2 hour before closing each day.
I'm interested in Boulder Creek Of Vantage Pointe. Please send me current availability and additional details.


text:
National Park Service renews mask mandate for all visitors
The National Park Service on Monday reinstated a mask mandate for all visitors, workers and volunteers at NPS buildings and crowded outdoor areas, regardless of vaccination status.
In May, the agency said it would require only unvaccinated people to wear masks. Recently, as the delta variant of the coronavirus has led to a spike in cases throughout the country, the NPS also required people from areas of high transmission to mask up, consistent with Centers for Disease Control and Prevention guidance.
Park Service sites in areas of high transmission also adopted their own mask mandates.
The new universal masking rule marks a return to the NPS policy from February to May.
The agency announced the change in policy Monday afternoon, and said it was effective immediately and would remain in place "until further notice."
"Visitors to national parks are coming from locations across the country, if not across the world," NPS Deputy Director Shawn Benge said in a statement. "Because of this, and recognizing that the majority of the United States is currently in substantial or high transmission categories, we are implementing a service-wide mask requirement to ensure our staff and visitors' safety."
Some state and local governments have returned to mandating masks in recent weeks as a response to delta, a more contagious and dangerous strain of the coronavirus.
Research shows that fully vaccinated people are less likely to get seriously ill, but can still pass the virus to others. About 59 percent of Americans over 12 are fully vaccinated, while nearly 70 percent have received at least one dose, according to the CDC.
Originally published at www.penncapital-star.com,by Jacob Fischler
Heces: la nueva herramienta de detección de covid y otras enfermedades
Pa. Democrats running for U.S. Senate united in efforts to maintain party majority in Congress
Cinco cosas que deberías saber sobre las pruebas caseras "gratis" para covid
From Oregon to Pennsylvania, legislatures across country split on pandemic protocols…
Amazon Delivery Driver Suspected Of Stealing Packages In…


text:
Kansas Family Physician of the Year
Kansas Exemplary Teaching Awards
Kansas Humanitarian Award
Maintain your membership
Residents & Students
Summer Training Option in Rural Medicine (STORM)
Family Medicine Interest Group
Hostetter Student Award
Carol A Johnson MD Family Medicine International Mission Scholarship
Family Doctor of the Day
Advocacy Day
Happening in Topeka
Health Committees
KS Legislature
AAFP Advocacy
Virtual CME
Fam Med Forward
FMF Virtual CME
Resident Presentations
Attendee Hub
Supporter & Exhibitor Hub
CME Proposals
Let's Move, Kansas
Dillons Community Rewards & AmazoneSmile
Center for History of Family Medicine
Contact KAFP
KAFP Team
KAFP Communications
KAFP News
KAFP Blog
Kansas Family Physician
HUD Housing Now Smoke-Free
KDHE
As of July 30, 2018, the U.S. Department of Housing and Urban Development (HUD) public housing is smoke-free nationwide. This new federal rule intends to protect residents from the dangers of secondhand smoke – such as premature death and diseases including cancer, asthma, pneumonia, bronchitis, Sudden Infant Death Syndrome (SIDS) and more.[i]
This is a critical time to talk to your patients who use tobacco products about becoming and staying tobacco-free. Even brief counseling increases the odds that a patient will successfully quit smoking compared to those who do not receive counseling from a health care provider.[ii]
Remind them that most insurance plans, including Medicaid, cover counseling and cessation medications to assist them in their quitting process. KanCare (Kansas Medicaid) now covers up to four quit attempts per year. Each "quit attempt" includes a free round of nicotine replacement therapy and unlimited counseling sessions.
Don't forget about the free resources available to tobacco users and their families through the Kansas Tobacco Quitline. The Quitline is available online and by phone, text, or mobile application 24 hours a day, 7 days a week. Translation services are available in 150 languages and to people with hearing impairments. The Quitline can be contacted by calling 1-800- QUIT- NOW (784-8669) or by visiting www.KSQuit.org.
The Quitline also offers a Behavioral Health Program which provides free nicotine replacement therapy and additional calls with a Quit Coach for callers with certain mental illnesses including bipolar disorder, schizophrenia, depression, substance (drug or alcohol) use disorder (SUD), generalized anxiety disorder, post-traumatic stress disorder (PTSD), and attention deficit hyperactivity disorder (ADHD).
In addition, the Kansas Department of Health and Environment can provide guidance, resources, and technical assistance to help your organization improve tobacco screening guidelines, provide provider education, develop tobacco-free campus policies, and more, all at no cost. Contact the Kansas Tobacco Use Prevention Program at 785-296-8127 or kdhe.tupp@ks.gov.
[i]Office of the Surgeon General. The Health Consequences of Involuntary Exposure to Tobacco Smoke: A Report of the Surgeon General. Rockville, MD: U.S. Department of Health and Human Services, 2006.
[ii]Fiore, M.C. Treating Tobacco Use and Dependence: 2008 Update. Rockville, MD: U.S. Department of Health and Human Services, Public Health Service, 2008.
October 22, 2018 /by Jesse Soyez
https://kafponline.org/wp-content/uploads/2018/01/KSSPTG_web_large.png 0 0 Jesse Soyez https://kafponline.org/wp-content/uploads/2018/01/KSSPTG_web_large.png Jesse Soyez2018-10-22 18:01:222018-10-22 18:03:01HUD Housing Now Smoke-Free
2021 Renewal Incentive for AAFP Active Members
New Expansion of Free NRT from the Kansas Tobacco Quitline
Don't Forget to Update Your Email Address
Kansas Family Physician Now Available Online
KANSAS ACADEMY OF FAMILY PHYSICIANS
7570 W 21ST ST N #1026 C, 104
WICHITA KANSAS 67205
Email:info@kafponline.org
© Copyright - KAFP 2017 - powered by Enfold WordPress Theme
KAFP'S EVP ANNOUNCES RETIREMENT; SEEKING EVP APPLICATIONS October 29 Webinar – Successful ACOs: A Strong Foundation of Primary ...


text:
#ifndef ROLLING_FILE_LOGGER_HPP
#define ROLLING_FILE_LOGGER_HPP

#include "globals.hpp"
#include <string>
#include <streambuf>
#include <dlib/threads.h>
#include <dlib/dir_nav.h>

class RollingFileLogger {
public:
  enum RollingSchedule {
    DAILY, WEEKLY, NEVER
  };

  /* Default the rolling logger to change create a new file every 10M of data */

  RollingFileLogger(std::string aName,
                    int aMaxBackupIndex = 9,
                    size_t aMaxSize = 10*1024*1024,
                    RollingSchedule aSchedule = NEVER);
  ~RollingFileLogger();

  void write(const char *aLine);

  int getMaxSize() const { return mMaxSize; }

protected:
  void rollover(size_t aSize);
  int getFileAge();

private:
  dlib::mutex *mFileLock;

  std::string mName;
  dlib::directory mDirectory;
  dlib::file mFile;

  int mMaxBackupIndex;
  size_t mMaxSize;
  RollingSchedule mSchedule;

  int mFd;
};

#endif

redpajama_set_name: RedPajamaGithub


Today's post is a practical and simple time-saver that has to do with the shape of dinner.Yes, the actual, geometric shape of dinner.
If you have ever prepared meals ahead to freeze, you may have found that how you store your meal going into the freezer can determine how handily dinner will be complete once you take it out of the freezer. Think hack-sawing a square hunk of chicken pot pie to make it fit a round baking dish. This is not fun.
More of a method than a recipe, bucket dinners may ease that problem.
Bucket Lasagna* is where you construct your favorite lasagna recipe in a clean ice cream bucket, then freeze. To conserve freezer space, you can then transfer the frozen mold to a freezer bag.
On the day you want to serve it, pop the meal into a sprayed 5-quart, round slow cooker. The bucket mold fits just right into that size. Cook it low and slow, and dinner will be one less thing you have to worry about that day. This would also be a neat way to store up some meals in advance to bless someone in need.
If you think this method would be helpful but you don't have a round slow cooker, you may easily find one at a second-hand store or garage sale for little cost.
There are many good recipes online for make-ahead meals--no matter what shape you store them in. Here are two that you may like to try and perhaps even add to your bucket list. Hope you like them.


text:
from distutils.core import setup
import os

parent_directory = os.path.abspath(os.path.dirname(__file__))

meta_files = {
    'README.md': None,
    'CLASSIFIERS.txt': None,
}

for filename in meta_files:
    try:
        current_file = open(os.path.join(parent_directory, filename))
        meta_files[filename] = current_file.read()
        current_file.close()
    except IOError:
        raise IOError('{0} not found.'.format(filename))

classifiers = meta_files['CLASSIFIERS.txt'].split('\n')
classifiers.remove('')

setup(name='django-aliases',
      version='0.1',
      description='Some useful tools for "aliasing" objects in django.',
      long_description=meta_files['README.md'],
      classifiers=classifiers,
      author='Brandon R. Stoner',
      author_email='monokrome@limpidtech.com',
      url='http://github.com/LimpidTech/django-aliases',
      packages=['aliases'],
      keywords = 'web django aliases shortcuts',
)


1971 – TEA BREAK: 3.45pm weekday thirty-minuter ("the programme for women with the work done and minds of their own") from Thames presented by – and this can't have been good – MICHAEL PARKINSON, aided by RENNY LISTER. "Michael Parkinson introduces the first programme in a twice-weekly series aimed mainly at women, and at those at home in the afternoon who could do with a break about now. Whatever the topic, there are women with a view about it. This is their programme. So put down that duster, put up your feet and prepare to relax." Cheers.
1972 – GOOD AFTERNOON!: Moved to 2.30, but continuity was maintained with presenter Sylvia Duncan. JILL TWEEDIE and MARY PARKINSON also signed up. There was a sort of weekly rota, here – Mavis looked at education, RITA DANDO health, and Jill – but of course – women's rights. Clocked up well over a thousand editions by its termination in '78.
1979 – AFTERNOON PLUS: as above.
1982 – A PLUS: An abbreviation of the name, an extension of the time to 45 minutes, but otherwise business as usual. Trevor Hyett handled the first season, with Nicholson, Grand et al. appearing more frequently as time ground on. PEREGRINE WORSTHORNE and ANNE ROBINSON contributed to a Review of the Year in early '83. That extra quarter-hour was later rescinded, and the format trundled on until mid-'84.
1984 – A PLUS 4: As the name suggests, a translation of the old warhorse to Channel Four, with MAVIS NICHOLSON, GILL NEVILL and PAUL JONES in the comfy chairs. "Discussion, music and interviews, with an original view on all that's new in politics, entertainment and health." Rambled on endlessly until Michael Grade passed the death sentence.
Is this the Afternoon Plus Vyv wanted to watch in the episode of the Young Ones with the nuclear bomb?


'Sharwane' is a very tidy example of this sturdy river & inshore cruiser.
Her accommodation includes a large double berth/dinette in the 'V' with storage underneath & bookshelves to the sides, large dinette/double berth on the port side, a well equipped galley to starboard. The shower room has a chemical toilet, shower & wash basin.
The large cockpit has ample room for 4 plus the helmsman.
The aft cabin will accommodate 2 & is ,at the moment used to stow a tender & outboard motor which are included in the sale.
These boats are renowned for their stability & build quality.
Hello, thought you may be interested in this boat for sale from Tewkesbury Boat Sales!
Hello, please contact me with reference to this boat, I would be interested in finding out more.
Offered subject to being unsold. Particulars given are subject to confirmation by buyer. In this case we are acting as brokers only. Whilst every care has been taken in their preparation, the correctness of these particulars is not guaranteed. The particulars are intended only as a guide and they do not constitute a term of any contract. A prospective buyer is strongly advised to check the particulars. Where appropriate at his own expense to employ a qualified Marine Surveyor to carry out a survey, and/or to have an engine trial conducted, which if conducted by us shall not imply any liability for such engines on our part.
© 2018 Tewkesbury Marina Boat Sales All rights reserved.


This is part 1 of «the making of 'Cultivating Creativity'», a presentation I entered in SlideShare.com's «World's Best Presentation Contest».
For those of you who have yet to see the 'Cultivating Creativity' presentation, just scroll down to my last post. As a huge part of my blog-posts have been about Slideware Presentations I figured I had to participate. And if I was to participate, I wanted to do it right, meaning: adhering to my own ideas and philosophies about what makes a great presentation. As an oral presentation wouldn't be possible I would have to use more text than I would normally do, but it had to be strong visually. First thing's first though and the first challenge was to decide upon a topic for the presentation.
So with this in mind I began doodling and brainstorming on paper. While doing so however I felt that the topic was perhaps too shallow. While I felt fairly comfortable that I could make a presentation interesting to watch, it might be a hard sell to actually get anyone to watch it in the first place. Yet, I didn't have any better idea, so I pushed on. When it suddenly hit me: My search for creativity was the answer. How often hadn't I found myself in search for the creative spark? How often hadn't I experienced the creative part of my brain firing on all cylinders when laying in bed waiting for Mr. Sandman to arrive? And even better: I knew how to treat my brain to spark the creative process in the first place!


text:
Black Panther dies after being freed from 40 years' jail in U.S.
AFP October 4, 2013 October 4, 2013
WASHINGTON, D.C. – Herman Wallace, a former Black Panther who spent more than four decades in solitary confinement for murdering a prison guard, died Friday, three days after his release, lawyers said.
The 71-year-old, who has always denied his involvement in the murder, died of liver cancer.
"Although his freedom was much too brief, it meant the world to Herman to spend these last three days surrounded by the love of his family and friends," his defense team said. "One of the final things that Herman said to us was, 'I am free. I am free.'"
Wallace is a member of the "Angola Three," whose cases have drawn international attention because of the long stretches they spent in solitary after the 1972 death of prison guard Brent Miller.
The group was named after the notorious Louisiana state prison where the three were held, known as Angola because it was built on the site of a former plantation worked by slaves from Africa.
They have always maintained their innocence and challenged the evidence that was presented against them.
The trio had embraced the Black Panther movement – an African-American militant organization – while already serving time in prison for lesser crimes.
One of the three, Robert King, was freed in 2001. Wallace and his other co-defendant, Albert Woodfox, had stayed behind bars, confined to a tiny cell for 23 hours a day.
Wallace was released late Tuesday after a federal judge overturned his murder conviction and life sentence saying they violated his constitutional right to a fair trial.
The state of Louisiana had refused to free him on medical grounds over his terminal cancer.
Fonseca, Martínez embody new breed of Cuban music
In IPO, Twitter seeks to be 'anti-Facebook'


text:
Robust password policies cut cyber attacks by 60%
Research shows that hackers most often use brute force password attacks and flaw exploitation
by: Rene Millman
Deploying an appropriate patch management policy decreases the risk of hacking by 30%, while a robust password policy reduces the likelihood of being attacked by 60%, according to a new report.
The Incident Response Analyst Report 2021, published by IT security firm Kaspersky, found brute force is the most widely used initial vector to penetrate a company's network. Compared to the previous year, the share of brute force attacks has skyrocketed from 13% to 31.6%. The report's authors said this was perhaps due to the pandemic and the boom of remote working.
Hackers use open source tools to steal usernames and passwords
1Password Business review: First choice for business travel and guest accounts
Keeper Security review: Keeps corporate password management simple
Kaspersky Password Manager generates passwords that can be 'cracked in seconds'
The analysis of anonymized data from incident response (IR) cases found that the second most seen attack is vulnerability exploitation with a 31.5% share. The research showed that vulnerabilities from 2020 were used in only a few incidents. In other cases, adversaries used older, unpatched vulnerabilities, such as CVE-2019-11510, CVE-2018-8453, and CVE-2017-0144.
Over half of attacks that started with malicious emails, brute force, and external application exploitation were detected in hours (18%) or days (55%). The report added that some of these attacks lasted much longer, with an average duration of up to 90.4 days.
The report also found that industrial businesses were the most affected by cyber attacks (22%), followed by government institutions (19%).
Analysis of the data from incident responses found that in 44% of all incidents, hackers used existing, well known offensive tools from GitHub, such as Mimikatz, AdFind, and Masscan. They also used specialized commercial frameworks, such as Cobalt Strike.
Defeating ransomware with unified security from WatchGuard
How SMBs can defend against the onslaught of ransomware attacks
Konstantin Sapronov, head of Kaspersky's global emergency response team said that even if the IT security department does its best to ensure safety of the company's infrastructure, legacy OS usage, low-end equipment, compatibility issues, and human factors often result in security breaches that can jeopardize an organization's security.
"Protective measures alone can't provide a holistic cyber defense. Therefore, they should always be combined with detection and response tools that are able to recognize and eliminate an attack at an early stage, as well as address the cause of the incident," Sapronov said.
The report urged organizations to deploy a robust password policy, including multi-factor authentication (MFA) and identity and access management tools, and ensure software is patched regularly to fix vulnerabilities.
Russia's "politically motivated" REvil raid could be used as leverage, experts warn
Meta files lawsuit to uncover hackers targeting Facebook, WhatsApp
NCA donates 225 million passwords to Have I Been Pwned
Five things to consider before choosing an MFA solution


text:
Biografia
Era la figlia di José Casimiro Manuel de Villena, e di sua moglie, María Josefa Álvarez de las Asturias Bohórquez. Alla nascita del fratello Enrique, perse i suoi diritti ereditati.

Nel testamento del padre, María Isabel ereditò i titoli di Contessa di Vía Manuel, Contessa di Granja, Baronessa di Puebla. Alla fine del 1866, all'età di 16 anni, María Isabel prese possesso del suo patrimonio.

Isabella II la nominò Marchesa di Puebla, con un regio decreto il 30 maggio 1867, in segno di gratitudine per il sostegno fornito alla corona in passato dal nonno Cristóbal Manuel de Villena durante la prima guerra carlista.

Matrimonio
Sposò, il 12 gennaio 1867 a Madrid, Arturo de Pardo (21 luglio 1840-17 marzo 1907), capitano di cavalleria, senatore e Gentiluomo da camera di Alfonso XII. Ebbero otto figli:

 Isabel de Pardo (26 ottobre 1867-1940), sposò Alonso Barroeta, non ebbero figli;
 Josefa de Pardo (13 febbraio 1869-1976), sposò in prime nozze Juan Manuel Agrela, ebbero un figlio, e in seconde nozze Carlos Luis Ruspoli, non ebbero figli;
 Arturo de Pardo (27 marzo 1870-16 agosto 1907);
 Laura María de Pardo (22 dicembre 1872-22 gennaio 1914);
 Alfonso de Pardo (18 febbraio 1876-21 giugno 1955);
 María Juana Ramona Josefa de Pardo (18 ottobre 1878-1972), sposò Alfonso José Maldonado, non ebbero figli;
 Ramón de Pardo (29 gennaio 1880-1880)
 María del Milagro Sofia Franca Lazara Tomasa María de las Mercedes de Pardo (dicembre 1881-1 giugno 1982), sposò Enrique María del Arroyo, non ebbero figli.

Morte
Il 24 maggio 1874 suo fratello venne ucciso con un'arma da fuoco. María Isabel ereditò tutti i suoi titoli.

Morì il 18 aprile 1929 a Madrid

Onorificenze

Onorificenze spagnole

Bibliografia
 Javier Baeza Valero (2008 - 2009): III estudio sobre: Casas nobles de España

Collegamenti esterni

María Isabel
María Isabel
María Isabel
María Isabel
María Isabel
María Isabel

redpajama_set_name: RedPajamaWikipedia


Junglemap offers an innovative opportunity for e-learning in a simple but effective way. Junglemap NanoLearning is a learning process based on a series of 2-5 minute modules by email offering infinite opportunities with maximum learning effect. Junglemap NanoLearning is entirely responsive and supports all browsers and operating systems. No plugins or app installations required. The platform provides unlimited opportunities for very large organisations and clusters, too. 400,000 people have already completed the most popular course simultaneously, to date.