Project analysts help drive a project from start to finish by coordinating information, providing support through data analysis, and contributing to overall strategy and performance evaluation. They're responsible for project documentation and monitoring. Because of their detailed view of the project, they play an important role in both internal and external communication. Project analysts often report to project or senior managers, and they spend most of their workday inside the office, generally following regular hours with the occasional overtime for urgent projects. Full-time positions for large companies are most common, but part-time work is also possible.
Project analysts work with other team members to prepare detailed plans for new projects, determining resource allocation, deliverable timelines, and possible issues. They may also conduct a feasibility analysis to ensure consistency with client demands.
A key part of a project analyst's job is providing support by handling some of the operational aspects of a project. Possible tasks include coordinating with stakeholders and consultants, conducting internal meetings, reviewing finances, and streamlining the overall workflow, with the primary aim of keeping the project on schedule.
During planning, project analysts kick off the evaluation process by establishing performance indicators. They then monitor every step of the project with reference to cost estimates, overall plans, and deliverable deadlines. This leads to a strategic advantage, since they can better identify roadblocks and propose process improvements.
Project analysts dedicate many of their work hours to handling data, which they research, monitor, and analyze to produce business insights and action recommendations. From project reviews to performance optimization, the applications of this are endless.
Project analysts are accountable for creating and maintaining project documentation, including timelines, resource plans, and meeting minutes. They must also prepare presentations and regular status reports, serving as the main source of information about the project to external teams.
For the project analyst position, most employers require at least a bachelor's degree in a field such as business, finance, or computer science. Certification for project management is not necessary, but it may improve the employment chances of candidates with unrelated degrees. Most project analysts have at least one year of prior experience in a management or analytical role. Hands-on training is provided on the job, although it's expected that project analysts are already aware of business fundamentals, including basic models and diagrams.
The average salary for a project analyst is around $61,000 per year, according to Glassdoor. Income ranges from a low of $46,000 to a high of $84,000 annually.
The Bureau of Labor Statistics reports that there were over 806,000 management analysts employed in 2016, a number that's projected to grow 14 percent by 2026. This is a faster-than-average rate, signaling that companies will increasingly seek out management analysts, including project analysts, to optimize projects and bolster efficiency.


text:
#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "ECEditorWindow.h"
#include "ECBrowser.h"
#include "EntityPlacer.h"
#include "AddComponentDialog.h"
#include "EntityActionDialog.h"
#include "FunctionDialog.h"
#include "ArgumentType.h"
#include "FunctionInvoker.h"
#include "ECEditorModule.h"
#include "TransformEditor.h"
#include "UndoCommands.h"
#include "UndoManager.h"

#include "Scene/Scene.h"
#include "Entity.h"
#include "Application.h"
#include "Profiler.h"
#include "SceneAPI.h"
#include "EC_Name.h"
#include "EC_Placeable.h"
#include "EC_Mesh.h"
#include "InputAPI.h"
#include "UiAPI.h"
#include "UiMainWindow.h"
#include "LoggingFunctions.h"
#include "Math/float2.h"
#include "Math/float3.h"
#include "Math/float4.h"
#include "Math/Quat.h"
#ifdef EC_Highlight_ENABLED
#include "EC_Highlight.h"
#endif

#include <QUiLoader>
#include <QDomDocument>

#include "MemoryLeakCheck.h"

namespace
{

const char *cEcEditorHighlight = "EcEditorHighlight";

uint AddUniqueListItem(const EntityPtr &entity, QListWidget* list, const QString& name)
{
    for(int i = 0; i < list->count(); ++i)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(list->item(i));
        if (item && item->Entity() && item->Entity() == entity)
            return i;
    }

    new EntityListWidgetItem(name, list, entity);
    return list->count() - 1;
}

} // ~unnamed namespace

ECEditorWindow::ECEditorWindow(Framework* fw, QWidget *parent) :
    QWidget(parent),
    framework(fw),
    toggleEntitiesButton(0),
    entityList(0),
    ecBrowser(0),
    hasFocus(true)
{
    QUiLoader loader;
    loader.setLanguageChangeEnabled(true);
    QFile file(Application::InstallationDirectory() + "data/ui/eceditor.ui");
    file.open(QFile::ReadOnly);
    if (!file.exists())
    {
        LogError("Cannot find " + Application::InstallationDirectory() + "data/ui/eceditor.ui file.");
        return;
    }

    QWidget *contents = loader.load(&file, this);
    if (!contents)
    {
        LogError("Could not load editor layout");
        return;
    }
    contents->installEventFilter(this);
    file.close();

    Scene *scene = fw->Scene()->MainCameraScene();
    assert(scene);
    undoManager_ = new UndoManager(scene->shared_from_this(), this);
    transformEditor = new TransformEditor(scene->shared_from_this(), undoManager_);

    QVBoxLayout *layout = new QVBoxLayout(this);
    undoButton_ = findChild<QToolButton *>("undoButton");
    undoButton_->setDisabled(true);
    redoButton_ = findChild<QToolButton *>("redoButton");
    redoButton_->setDisabled(true);

    undoButton_->setIcon(QIcon(Application::InstallationDirectory() + "data/ui/images/icon/undo-icon.png"));
    redoButton_->setIcon(QIcon(Application::InstallationDirectory() + "data/ui/images/icon/redo-icon.png"));

    undoButton_->setMenu(undoManager_->UndoMenu());
    redoButton_->setMenu(undoManager_->RedoMenu());

    layout->addWidget(contents);
    layout->setContentsMargins(0,0,0,0);
    setLayout(layout);
    setWindowTitle(contents->windowTitle());
    resize(contents->size());

    toggleEntitiesButton = findChild<QPushButton *>("but_show_entities");
    entityList = findChild<QListWidget*>("list_entities");
    QWidget *entity_widget = findChild<QWidget*>("entity_widget");
    if(entity_widget)
        entity_widget->hide();

    QWidget *browserWidget = findChild<QWidget*>("browser_widget");
    if (browserWidget)
    {
        ecBrowser = new ECBrowser(framework, this, browserWidget);
        ecBrowser->setMinimumWidth(100);
        QVBoxLayout *property_layout = dynamic_cast<QVBoxLayout *>(browserWidget->layout());
        if (property_layout)
            property_layout->addWidget(ecBrowser);
    }

    ECEditorModule *ecEditorModule = framework->GetModule<ECEditorModule>();
    if (ecBrowser)
    {
        // signals from attribute browser to editor window.
        connect(ecBrowser, SIGNAL(ShowXmlEditorForComponent(const QString &)), SLOT(ShowXmlEditorForComponent(const QString &)));
        connect(ecBrowser, SIGNAL(CreateNewComponent()), SLOT(CreateComponent()));
        connect(ecBrowser, SIGNAL(SelectionChanged(const QString&, const QString &, const QString&, const QString&)),
            SLOT(HighlightEntities(const QString&, const QString&)));
        connect(ecBrowser, SIGNAL(SelectionChanged(const QString&, const QString &, const QString&, const QString&)),
            SIGNAL(SelectionChanged(const QString&, const QString&, const QString&, const QString&)), Qt::UniqueConnection);

        ecBrowser->SetItemExpandMemory(ecEditorModule->ExpandMemory());
    }

    if (entityList)
    {
        entityList->setSelectionMode(QAbstractItemView::ExtendedSelection);
        connect(entityList, SIGNAL(itemSelectionChanged()), this, SLOT(RefreshPropertyBrowser()));
        connect(entityList, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ShowEntityContextMenu(const QPoint &)));
    }

    if (toggleEntitiesButton)
        connect(toggleEntitiesButton, SIGNAL(pressed()), this, SLOT(ToggleEntityList()));

    QPushButton *expandOrCollapseButton = findChild<QPushButton *>("expandOrCollapseButton");
    if (expandOrCollapseButton && ecBrowser)
        connect(expandOrCollapseButton, SIGNAL(clicked()), ecBrowser, SLOT(ExpandOrCollapseAll()));

    connect(scene, SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)), SLOT(RemoveEntity(Entity*)), Qt::UniqueConnection);
    connect(scene, SIGNAL(ActionTriggered(Entity *, const QString &, const QStringList &, EntityAction::ExecTypeField)),
        SLOT(OnActionTriggered(Entity *, const QString &, const QStringList &)), Qt::UniqueConnection);

    connect(this, SIGNAL(FocusChanged(ECEditorWindow *)), ecEditorModule, SLOT(ECEditorFocusChanged(ECEditorWindow*)));
    connect(this, SIGNAL(EditEntityXml(const QList<EntityPtr> &)), ecEditorModule, SLOT(CreateXmlEditor(const QList<EntityPtr> &)));
    connect(this, SIGNAL(EditComponentXml(const QList<ComponentPtr> &)), ecEditorModule, SLOT(CreateXmlEditor(const QList<ComponentPtr> &)));
    //connect(this, SIGNAL(AttributeAboutToBeEdited(IAttribute *)), this, SLOT(OnAboutToEditAttribute(IAttribute* )));
    connect(undoManager_, SIGNAL(CanUndoChanged(bool)), this, SLOT(OnUndoChanged(bool)));
    connect(undoManager_, SIGNAL(CanRedoChanged(bool)), this, SLOT(OnRedoChanged(bool)));
    connect(undoButton_, SIGNAL(clicked()), undoManager_, SLOT(Undo()));
    connect(redoButton_, SIGNAL(clicked()), undoManager_, SLOT(Redo()));

    connect(framework->Input()->TopLevelInputContext(), SIGNAL(KeyPressed(KeyEvent*)), SLOT(OnKeyEvent(KeyEvent*)));
}

ECEditorWindow::~ECEditorWindow()
{
    SAFE_DELETE(undoManager_);
    SAFE_DELETE(transformEditor);
    //DeselectAllEntities(); the list is already cleared here
}

EntityListWidgetItem *ECEditorWindow::AddEntity(entity_id_t entity_id, bool updateUi)
{
    EntityListWidgetItem *item = 0;
    PROFILE(ECEditorWindow_AddEntity);
    if (entityList)
    {
        entityList->blockSignals(true);
        //If entity don't have EC_Name then entity_name is same as it's id.
        QString entity_name = QString::number(entity_id);
        EntityPtr entity = framework->Scene()->MainCameraScene()->GetEntity(entity_id);
        if (entity && entity->GetComponent<EC_Name>())
            entity_name.append(" " + entity->Name());

        int row = AddUniqueListItem(entity, entityList, entity_name);
        item = dynamic_cast<EntityListWidgetItem *>(entityList->item(row));
        assert(item);

        entityList->blockSignals(false);
    }

    if (updateUi)
        RefreshPropertyBrowser();

    return item;
}

void ECEditorWindow::AddEntities(const QList<entity_id_t> &entities, bool select_all)
{
    // SetEntitySelected() will block entity list's signals, no need to do it here.
    ClearEntities();
    foreach(entity_id_t id, entities)
    {
        EntityListWidgetItem *item = AddEntity(id, false);
        if (select_all)
            SetEntitySelected(item, true);
    }
    RefreshPropertyBrowser();
}

void ECEditorWindow::RemoveEntity(entity_id_t entity_id, bool udpate_ui)
{
    PROFILE(ECEditorWindow_RemoveEntity);
    if (!entityList)
        return;

    entityList->blockSignals(true);
    EntityPtr entity = framework->Scene()->MainCameraScene()->GetEntity(entity_id);
    if (!entity)
    {
        LogError("Failed to remove entity, since scene doesn't contain entity with ID: " + QString::number(entity_id));
        return;
    }

    for(uint i = 0; i < (uint)entityList->count(); i++)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item && item->Entity() && item->Entity().get() == entity.get())
        {
            entityList->removeItemWidget(item);
            SAFE_DELETE(item)
            break;
        }
    }

    entityList->blockSignals(false);
    if (udpate_ui)
        RefreshPropertyBrowser();
}

void ECEditorWindow::SetSelectedEntities(const QList<entity_id_t> &ids)
{
    PROFILE(ECEditorWindow_SetSelectedEntities);
    if (!entityList)
        return;

    entityList->blockSignals(true);
    foreach(entity_id_t id, ids)
        for(uint i = 0; i < (uint)entityList->count(); ++i)
        {
            QListWidgetItem *item = entityList->item(i);
            if (id == (entity_id_t)item->text().toInt())
            {
                item->setSelected(true);
                break;
            }
        }

    entityList->blockSignals(false);
    RefreshPropertyBrowser();
}

void ECEditorWindow::ClearEntities()
{
    DeselectAllEntities();
    if (entityList)
        entityList->clear();
    RefreshPropertyBrowser();
}

QObjectList ECEditorWindow::SelectedComponents() const
{
    if (ecBrowser)
        return ecBrowser->SelectedComponents();
    return QObjectList();
}

QList<EntityPtr> ECEditorWindow::SelectedEntities() const
{
    QList<EntityPtr> ret;

    if (!entityList)
        return ret;

    Scene *scene = framework->Scene()->MainCameraScene();
    if (!scene)
        return ret;

    for(uint i = 0; i < (uint)entityList->count(); ++i)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item && item->Entity() && item->isSelected())
        {
            EntityPtr entity = scene->GetEntity(item->Entity()->Id());
            if (entity)
                ret.push_back(entity);
        }
    }
    return ret;
}

void ECEditorWindow::SetEntitySelected(EntityListWidgetItem *item, bool select)
{
    entityList->blockSignals(true);
    item->setSelected(select);
    entityList->blockSignals(false);
    if (framework->GetModule<ECEditorModule>()->IsHighlightingEnabled())
        HighlightEntity(item->Entity(), select);
    emit EntitySelected(item->Entity(), select);
}

EntityListWidgetItem *ECEditorWindow::FindItem(entity_id_t id) const
{
    for(uint i = 0; i < (uint)entityList->count(); i++)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item && item->Entity() && item->Entity()->Id() == id)
            return item;
    }

    return 0;
}

void ECEditorWindow::SetHighlightingEnabled(bool show)
{
    for(uint i = 0; i < (uint)entityList->count(); i++)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item && item->isSelected())
            HighlightEntity(item->Entity(), show);
    }
}

void ECEditorWindow::SetGizmoVisible(bool show)
{
    transformEditor->SetGizmoVisible(show);
}

void ECEditorWindow::DeleteEntitiesFromList()
{
    if (entityList && entityList->hasFocus())
        for(int i = entityList->count() - 1; i >= 0; --i)
            if (entityList->item(i)->isSelected())
            {
                QListWidgetItem* item = entityList->takeItem(i);
                delete item;
            }
}

void ECEditorWindow::DeleteComponent(const QString &componentType, const QString &name)
{
    if(componentType.isEmpty())
        return;

    foreach(const EntityPtr &entity, SelectedEntities())
    {
        ComponentPtr component = entity->GetComponent(componentType, name);
        if (component)
            entity->RemoveComponent(component, AttributeChange::Default);
    }
}

void ECEditorWindow::CreateComponent()
{
    QList<entity_id_t> ids;
    foreach(const EntityPtr &e, SelectedEntities())
        ids.push_back(e->Id());

    if (ids.size())
    {
        AddComponentDialog *dialog = new AddComponentDialog(framework, ids, framework->Ui()->MainWindow(), Qt::Tool);
        dialog->SetComponentList(framework->Scene()->ComponentTypes());
        connect(dialog, SIGNAL(finished(int)), this, SLOT(AddComponentDialogFinished(int)));
        dialog->show();
        dialog->activateWindow();
    }
}

void ECEditorWindow::OnKeyEvent(KeyEvent *keyEvent)
{
    if (!isVisible() || !undoManager_ || !framework || !framework->Input())
        return;

    const QKeySequence undo = framework->Input()->KeyBinding("TundraEditors.Undo", QKeySequence(Qt::ControlModifier + Qt::Key_Z));
    const QKeySequence redo = framework->Input()->KeyBinding("TundraEditors.Redo", QKeySequence(Qt::ControlModifier + Qt::Key_Y));

    if (keyEvent->sequence == undo)
    {
        undoManager_->Undo();
        keyEvent->Suppress();
    }
    else if( keyEvent->sequence == redo)
    {
        undoManager_->Redo();
        keyEvent->Suppress();
    }
}

void ECEditorWindow::EntityActionDialogFinished(int result)
{
    EntityActionDialog *dialog = qobject_cast<EntityActionDialog *>(sender());
    if (!dialog)
        return;

    if (result == QDialog::Rejected)
        return;

    foreach(const EntityWeakPtr &e, dialog->Entities())
        if (!e.expired())
            e.lock()->Exec(dialog->ExecutionType(), dialog->Action(), dialog->Parameters());
}

void ECEditorWindow::FunctionDialogFinished(int result)
{
    FunctionDialog *dialog = qobject_cast<FunctionDialog *>(sender());
    if (!dialog)
        return;

    if (result == QDialog::Rejected)
        return;

    // Get the list of parameters we will pass to the function we are invoking,
    // and update the latest values to them from the editor widgets the user inputted.
    QVariantList params;
    foreach(IArgumentType *arg, dialog->Arguments())
    {
        arg->UpdateValueFromEditor();
        params << arg->ToQVariant();
    }

    // Clear old return value from the dialog.
    dialog->SetReturnValueText("");

    foreach(const QObjectWeakPtr &o, dialog->Objects())
        if (o.lock())
        {
            QObject *obj = o.lock().get();

            QString objName = obj->metaObject()->className();
            QString objNameWithId = objName;
            {
                Entity *e = dynamic_cast<Entity *>(obj);
                IComponent *c = dynamic_cast<IComponent *>(obj);
                if (e)
                    objNameWithId.append('(' + QString::number((uint)e->Id()) + ')');
                else if (c && !c->Name().trimmed().isEmpty())
                    objNameWithId.append('(' + c->Name() + ')');
            }

            QString errorMsg;
            QVariant ret;
            FunctionInvoker::Invoke(obj, dialog->Function(), params, &ret, &errorMsg);

            QString retValStr;
            ///\todo For some reason QVariant::toString() cannot convert QStringList to QString properly.
            /// Convert it manually here.
            if (ret.type() == QVariant::StringList)
                foreach(QString s, ret.toStringList())
                    retValStr.append("\n" + s);
            else
                retValStr = ret.toString();

            if (errorMsg.isEmpty())
                dialog->AppendReturnValueText(objNameWithId + ' ' + retValStr);
            else
                dialog->AppendReturnValueText(objNameWithId + ' ' + errorMsg);
        }
}

void ECEditorWindow::OnActionTriggered(Entity *entity, const QString &action, const QStringList &params)
{
    if (action == "MousePress" && params.size())
    {
        MouseEvent::MouseButton button = static_cast<MouseEvent::MouseButton>(params[0].toUInt());
        if (hasFocus && isVisible() && button == MouseEvent::LeftButton)
        {
            /// @todo This will now work if we lose windows focus and previous key state stays, replace this with InputContext.
            // If Ctrl is down, we're appending selection. If not, clear the old selection completely.
            if (!framework->Input()->IsKeyDown(Qt::Key_Control))
                DeselectAllEntities();

            EntityListWidgetItem *item = FindItem(entity->Id());
            if (item)
                SetEntitySelected(item, !item->isSelected());
            else
            {
                item = AddEntity(entity->Id());
                SetEntitySelected(item, true);
            }
            RefreshPropertyBrowser();
        }
    }
}

void ECEditorWindow::DeleteEntity()
{
    Scene *scene = framework->Scene()->MainCameraScene();
    if (!scene)
        return;

    QList<EntityPtr> entities = SelectedEntities();
    for(uint i = 0; i < (uint)entities.size(); ++i)
        scene->RemoveEntity(entities[i]->Id(), AttributeChange::Default);
}

void ECEditorWindow::CopyEntity()
{
    /// @todo multiple entities copy-paste support.
    QDomDocument temp_doc;

    // Create root Scene element always for consistency, even if we only have one entity
    QDomDocument scene_doc("Scene");
    QDomElement scene_elem = temp_doc.createElement("scene");
    foreach(const EntityPtr &entity, SelectedEntities())
        if (entity)
        {
            QDomElement entity_elem = temp_doc.createElement("entity");
            entity_elem.setAttribute("id", QString::number((int)entity->Id()));

            const Entity::ComponentMap &components = entity->Components();
            for (Entity::ComponentMap::const_iterator i = components.begin(); i != components.end(); ++i)
                i->second->SerializeTo(temp_doc, entity_elem);

            scene_elem.appendChild(entity_elem);
        }

    temp_doc.appendChild(scene_elem);

    QApplication::clipboard()->setText(temp_doc.toString());
}

void ECEditorWindow::PasteEntity()
{
    ///\todo EntityPlacer is deprecated? If so, remove for good.
    // Dont allow paste operation if we are placing previosuly pasted object to a scene.
//    if(findChild<QObject*>("EntityPlacer"))
//        return;

    // First we need to check if component is holding EC_Placeable component to tell where entity should be located at.
    /// \todo local only server wont save those objects.
    Scene *scene = framework->Scene()->MainCameraScene();
    assert(scene);
    if (!scene)
        return;

    QString errorMsg;
    QDomDocument temp_doc("Scene");
    if (!temp_doc.setContent(QApplication::clipboard()->text(), false, &errorMsg))
    {
        LogError("Parsing scene XML from clipboard failed: " + errorMsg);
        return;
    }

    // Check if clipboard contain infomation about entity's id,
    // which is used to find a right type of entity from the scene.
    QDomElement sceneElem = temp_doc.firstChildElement("scene");
    if (sceneElem.isNull())
        return;
    QDomElement ent_elem = sceneElem.firstChildElement("entity");
    if (ent_elem.isNull())
        return;
    QString id = ent_elem.attribute("id");
    EntityPtr originalEntity = scene->GetEntity((entity_id_t)id.toInt());
    if (!originalEntity)
    {
        LogWarning("ECEditorWindow::PasteEntity: cannot create a new copy of entity, because scene manager couldn't find the original entity. (id " + id + ").");
        return;
    }

    EntityPtr entity = scene->CreateEntity(originalEntity->IsLocal() ? scene->NextFreeIdLocal() : scene->NextFreeId());
    assert(entity);
    if (!entity)
        return;

//    bool hasPlaceable = false;
    const Entity::ComponentMap &components =  originalEntity->Components();
    for(Entity::ComponentMap::const_iterator i = components.begin(); i != components.end(); ++i)
    {
        // If the entity is holding placeable component we can place it into the scene.
//        if (i->second->TypeName() == EC_Placeable::TypeNameStatic())
//            hasPlaceable = true;
        ComponentPtr component = entity->GetOrCreateComponent(i->second->TypeName(), i->second->Name(), AttributeChange::Default);
        const AttributeVector &attributes = i->second->Attributes();
        for(uint j = 0; j < attributes.size(); j++)
            if (attributes[j])
            {
                IAttribute *attribute = component->AttributeByName(attributes[j]->Name());
                if(attribute)
                    attribute->FromString(attributes[j]->ToString(), AttributeChange::Default);
            }
    }

    ///\todo EntityPlacer is deprecated? If so, remove for good.
/*
    if(hasPlaceable)
    {
        EntityPlacer *entityPlacer = new EntityPlacer(framework, entity->Id(), this);
        entityPlacer->setObjectName("EntityPlacer");
    }
*/

    AddEntity(entity->Id());
}

void ECEditorWindow::OpenEntityActionDialog()
{
    QList<EntityWeakPtr> entities;
    foreach(const EntityPtr &entity, SelectedEntities())
        entities.append(entity);

    if (entities.size())
    {
        EntityActionDialog *d = new EntityActionDialog(entities, this);
        connect(d, SIGNAL(finished(int)), this, SLOT(EntityActionDialogFinished(int)));
        d->show();
    }
}

void ECEditorWindow::OpenFunctionDialog()
{
    QObjectWeakPtrList objs;
    foreach(const EntityPtr &entity, SelectedEntities())
        objs << dynamic_pointer_cast<QObject>(entity);

    if (objs.size())
    {
        FunctionDialog *d = new FunctionDialog(objs, this);
        connect(d, SIGNAL(finished(int)), this, SLOT(FunctionDialogFinished(int)));
        d->show();
    }
}

void ECEditorWindow::HighlightEntities(const QString &type, const QString &name)
{
    QSet<entity_id_t> entities;
    foreach(const EntityPtr &entity, SelectedEntities())
        if (entity->GetComponent(type, name))
            entities.insert(entity->Id());
    BoldEntityListItems(entities);
}

void ECEditorWindow::RefreshPropertyBrowser()
{
    PROFILE(ECEditorWindow_RefreshPropertyBrowser);
    if (!ecBrowser)
        return;

    Scene *scene = framework->Scene()->MainCameraScene();
    if (!scene)
    {
        ecBrowser->clear();
        return;
    }

    // Unbold all items for starters.
    BoldEntityListItems(QSet<entity_id_t>());

    QList<EntityPtr> entities = SelectedEntities();
    if (entities.empty()) // If any of entities was not selected clear the browser window.
    {
        ecBrowser->clear();
        transformEditor->SetGizmoVisible(false);
        return;
    }

    QList<EntityPtr> old_entities = ecBrowser->Entities();
    qStableSort(entities.begin(), entities.end());
    qStableSort(old_entities.begin(), old_entities.end());

    // Check what entities need to get removed/added to browser.
    QList<EntityPtr>::iterator iter1 = old_entities.begin(), iter2 = entities.begin();
    while(iter1 != old_entities.end() || iter2 != entities.end())
    {
        // No point to continue the iteration if old_entities list is empty. We can just push all new entities into the browser.
        if (iter1 == old_entities.end())
        {
            for(;iter2 != entities.end(); ++iter2)
                ecBrowser->AddEntity(*iter2);
            break;
        }
        // Only old entities are left and they can just be removed from the browser.
        else if(iter2 == entities.end())
        {
            for(;iter1 != old_entities.end(); ++iter1)
                ecBrowser->RemoveEntity(*iter1);
            break;
        }

        // Entity has already added to the browser.
        if((*iter1)->Id() == (*iter2)->Id())
        {
            ++iter2;
            ++iter1;
        }
        // Found new entity that that need to be added to the browser.
        else if((*iter1)->Id() > (*iter2)->Id())
        {
            ecBrowser->AddEntity(*iter2);
            ++iter2;
        }
        // Couldn't find entity in new entities list, so it need to be removed from the browser.
        else
        {
            ecBrowser->RemoveEntity(*iter1);
            ++iter1;
        }
    }

    ecBrowser->UpdateBrowser();

    // Show/set only entities with placeable to transform editor
    QList<EntityPtr> entitiesWithPlaceable;
    foreach(const EntityPtr &e, SelectedEntities())
        if (e->GetComponent<EC_Placeable>())
            entitiesWithPlaceable.append(e);

    if (!entitiesWithPlaceable.isEmpty())
    {
        transformEditor->SetSelection(entitiesWithPlaceable);
        transformEditor->FocusGizmoPivotToAabbCenter();
        // Shows gizmo only if we have focus.
        bool enabled = framework->GetModule<ECEditorModule>()->IsGizmoEnabled();
        transformEditor->SetGizmoVisible(hasFocus && enabled);
    }
}

void ECEditorWindow::ShowEntityContextMenu(const QPoint &pos)
{
    assert(entityList);
    if (!entityList)
        return;

    QListWidgetItem *item = entityList->itemAt(pos);
    // Do not necessarily return if we have no item
    // We can use paste entity without selection if we seem to have valid scene XML in the contents.
    QString clipboardContents = QApplication::clipboard()->text();
    bool clipboardHasEntityXml = clipboardContents.contains("scene") && clipboardContents.contains("entity");
    if (!item && !clipboardHasEntityXml)
        return;

    QMenu *menu = new QMenu(this);
    menu->setAttribute(Qt::WA_DeleteOnClose); ///<\todo has no effect if we don't call close() explicitly, and hence leaks memory (until ECEditorWindow is destroyed).
    QAction *editXml = 0, *deleteEntity = 0, *addComponent = 0, *copyEntity = 0, *pasteEntity = 0, *actions = 0, *functions = 0;
    if (item)
    {
        editXml = new QAction(tr("Edit XML..."), menu);
        deleteEntity = new QAction(tr("Delete"), menu);
        addComponent = new QAction(tr("Add new component..."), menu);
        copyEntity = new QAction(tr("Copy"), menu);
        actions = new QAction(tr("Actions..."), menu);
        functions = new QAction(tr("Functions..."), menu);

        connect(editXml, SIGNAL(triggered()), this, SLOT(ShowXmlEditorForEntity()));
        connect(deleteEntity, SIGNAL(triggered()), this, SLOT(DeleteEntity()));
        connect(addComponent, SIGNAL(triggered()), this, SLOT(CreateComponent()));
        connect(copyEntity, SIGNAL(triggered()), this, SLOT(CopyEntity()));
        connect(actions, SIGNAL(triggered()), this, SLOT(OpenEntityActionDialog()));
        connect(functions, SIGNAL(triggered()), this, SLOT(OpenFunctionDialog()));
    }

    if (clipboardHasEntityXml)
    {
        pasteEntity = new QAction(tr("Paste"), menu);
        connect(pasteEntity, SIGNAL(triggered()), this, SLOT(PasteEntity()));
    }

    if (item)
    {
        menu->addAction(editXml);
        menu->addAction(deleteEntity);
        menu->addAction(addComponent);
        menu->addAction(copyEntity);
    }
    if (clipboardHasEntityXml)
        menu->addAction(pasteEntity);
    if (item)
    {
        menu->addAction(actions);
        menu->addAction(functions);
    }

    if (item)
    {
        QList<QObject*> targets;
        EntityListWidgetItem* entityItem = dynamic_cast<EntityListWidgetItem*>(item);
        if (entityItem && entityItem->Entity())
            targets.push_back(entityItem->Entity().get());
        framework->Ui()->EmitContextMenuAboutToOpen(menu, targets);
    }

    menu->popup(entityList->mapToGlobal(pos));
}

void ECEditorWindow::ShowXmlEditorForEntity()
{
    QList<EntityPtr> entities = SelectedEntities();
    std::vector<EntityComponentSelection> selection;
    for(uint i = 0; i < (uint)entities.size(); i++)
    {
        EntityComponentSelection entityComponent;
        entityComponent.entity = entities[i];
        const Entity::ComponentMap &components = entities[i]->Components();
        for (Entity::ComponentMap::const_iterator i = components.begin(); i != components.end(); ++i)
            entityComponent.components.push_back(i->second);
        selection.push_back(entityComponent);
    }

    if (!selection.size())
        return;

    QList<EntityPtr> ents;
    foreach(const EntityComponentSelection &ecs, selection)
        ents << ecs.entity;

    emit EditEntityXml(ents);
}

void ECEditorWindow::ShowXmlEditorForComponent(const QList<ComponentPtr> &components)
{
    emit EditComponentXml(components);
}

void ECEditorWindow::ShowXmlEditorForComponent(const QString &componentType)
{
    QList<ComponentPtr> components;
    foreach(const EntityPtr &e, SelectedEntities())
    {
        ComponentPtr component = e->GetComponent(componentType);
        if (component)
            components << component;
    }

    emit EditComponentXml(components);
}

void ECEditorWindow::ToggleEntityList()
{
    QWidget *entity_widget = findChild<QWidget*>("entity_widget");
    if(entity_widget)
    {
        if (entity_widget->isVisible())
        {
            entity_widget->hide();
            resize(size().width() - entity_widget->size().width(), size().height());
            if (toggleEntitiesButton)
                toggleEntitiesButton->setText(tr("Show Entities"));
        }
        else
        {
            entity_widget->show();
            resize(size().width() + entity_widget->sizeHint().width(), size().height());
            if (toggleEntitiesButton)
                toggleEntitiesButton->setText(tr("Hide Entities"));
        }
    }
}

void ECEditorWindow::RemoveEntity(Entity* entity)
{
    for(uint i = 0; i < (uint)entityList->count(); i++)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item->Entity().get() == entity)
        {
            SAFE_DELETE(item);
            break;
        }
    }
}

void ECEditorWindow::SetFocus(bool focus)
{
    hasFocus = focus;
    SetGizmoVisible(!SelectedEntities().isEmpty() && hasFocus);
    if (framework->GetModule<ECEditorModule>()->IsHighlightingEnabled())
        for(uint i = 0; i < (uint)entityList->count(); i++)
        {
            EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
            if (item && item->isSelected())
                HighlightEntity(item->Entity(), hasFocus);
        }
}

void ECEditorWindow::setVisible(bool visible)
{
    QWidget::setVisible(visible);
    if (visible)
        emit FocusChanged(this);

    transformEditor->SetGizmoVisible(!SelectedEntities().isEmpty() && hasFocus);

    if (framework->GetModule<ECEditorModule>()->IsHighlightingEnabled())
        for(uint i = 0; i < (uint)entityList->count(); i++)
        {
            EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
            if (item && item->isSelected())
                HighlightEntity(item->Entity(), hasFocus);
        }
}

void ECEditorWindow::DeselectAllEntities()
{
    for(uint i = 0; i < (uint)entityList->count(); i++)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item)
            SetEntitySelected(item, false);
    }
}

void ECEditorWindow::HighlightEntity(const EntityPtr &entity, bool highlight)
{
#ifdef EC_Highlight_ENABLED
    if (entity)
    {
        // Optimization when selecting large group of entities, and sensible logic otherwise too:
        // Don't create EC_Highlight if there is no EC_Mesh in the entity. EC_Highlight does
        // absolutely nothing if there is no mesh. Granted it listens when EC_Mesh is added, but if you
        // are going to add meshes you might as well reselect your entities to get a highlight.
        // Creating the EC_Highlight to the entity is a major time spender if we are talking of large amount of entities.
        if (!entity->GetComponent<EC_Mesh>())
            return;

        // If component already has an EC_Highlight, that is not ours, do nothing, as the highlights would conflict
        ComponentPtr c = entity->GetComponent(EC_Highlight::TypeNameStatic());
        if (c && c->Name() != cEcEditorHighlight)
            return;

        if (highlight)
        {
            EC_Highlight *hl = dynamic_cast<EC_Highlight *>(entity->GetOrCreateLocalComponent(EC_Highlight::TypeNameStatic(), cEcEditorHighlight).get());
            if (hl)
            {
                hl->SetTemporary(true);
                hl->visible.Set(true, AttributeChange::Default);
            }
        }
        else
        {
            ComponentPtr c = entity->GetComponent(EC_Highlight::TypeNameStatic(), cEcEditorHighlight);
            if (c)
                entity->RemoveComponent(c);
        }
    }
#else
    LogInfo("ECEditorWindow::HighlightEntity: EC_Highlight not included in the build.");
#endif
}

void ECEditorWindow::hideEvent(QHideEvent* e)
{
    ClearEntities();
    if (ecBrowser)
        ecBrowser->clear();
    transformEditor->SetGizmoVisible(false);

    QWidget::hideEvent(e);
}

void ECEditorWindow::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange)
        setWindowTitle(tr("Entity-Component Editor"));
    else
       QWidget::changeEvent(e);
}

bool ECEditorWindow::eventFilter(QObject *obj, QEvent *e)
{
    if (e->type() == QEvent::WindowActivate)
        emit FocusChanged(this);
    return QWidget::eventFilter(obj, e);
}

void ECEditorWindow::BoldEntityListItems(const QSet<entity_id_t> &bolded_entities)
{
    PROFILE(ECEditorWindow_BoldEntityListItems);
    for(uint i = 0; i < (uint)entityList->count(); ++i)
    {
        EntityListWidgetItem *item = dynamic_cast<EntityListWidgetItem*>(entityList->item(i));
        if (item)
        {
            EntityPtr ent = item->Entity();
            QFont font = item->font();
            if (ent && bolded_entities.contains(ent->Id()))
            {
                font.setBold(true);
                item->setFont(font);
            }
            else
            {
                font.setBold(false);
                item->setFont(font);
            }
        }
    }
}

/*
void ECEditorWindow::OnDefaultSceneChanged(Scene *scene)
{
    if (!scene)
        return;

    /// @todo disconnect previous scene connection.
    connect(scene, SIGNAL(EntityRemoved(Entity*, AttributeChange::Type)),
        SLOT(RemoveEntity(Entity*)), Qt::UniqueConnection);
    connect(scene, SIGNAL(ActionTriggered(Entity *, const QString &, const QStringList &, EntityAction::ExecTypeField)),
        SLOT(OnActionTriggered(Entity *, const QString &, const QStringList &)), Qt::UniqueConnection);
}
*/

void ECEditorWindow::AddComponentDialogFinished(int result)
{
    AddComponentDialog *dialog = qobject_cast<AddComponentDialog*>(sender());
    if (!dialog)
        return;

    if (result != QDialog::Accepted)
        return;

    Scene *scene = framework->Scene()->MainCameraScene();
    if (!scene)
    {
        LogWarning("Failed to add new component to entity, since main camera scene was null");
        return;
    }

    QList<entity_id_t> targetEntities;

    foreach(entity_id_t id, dialog->EntityIds())
    {
        EntityPtr entity = scene->GetEntity(id);
        if (!entity)
        {
            LogWarning("Failed to add a new component to an entity, since couldn't find a entity with ID: " + QString::number(id));
            continue;
        }

        // Check if component has been already added to a entity.
        ComponentPtr comp = entity->GetComponent(dialog->TypeName(), dialog->Name());
        if (comp)
        {
            LogWarning("Failed to add a new component, because there was already a component with the same type and the same name.");
            continue;
        }

        targetEntities << id;
    }

    undoManager_->Push(new AddComponentCommand(scene->shared_from_this(), undoManager_->Tracker(),
        targetEntities, dialog->TypeId(), dialog->Name(), dialog->IsReplicated(), dialog->IsTemporary()));
}

void ECEditorWindow::OnAboutToEditAttribute(IAttribute *attr)
{
    switch(attr->TypeId())
    {
    case cAttributeReal:
        undoManager_->Push(new EditAttributeCommand<float>(attr));
        break;
    case cAttributeInt:
        undoManager_->Push(new EditAttributeCommand<int>(attr));
        break;
    case cAttributeUInt:
        undoManager_->Push(new EditAttributeCommand<unsigned int>(attr));
        break;
    case cAttributeFloat2:
        undoManager_->Push(new EditAttributeCommand<float2>(attr));
        break;
    case cAttributeFloat3:
        undoManager_->Push(new EditAttributeCommand<float3>(attr));
        break;
    case cAttributeFloat4:
        undoManager_->Push(new EditAttributeCommand<float4>(attr));
        break;
    case cAttributeQuat:
        undoManager_->Push(new EditAttributeCommand<Quat>(attr));
        break;
    case cAttributeColor:
        undoManager_->Push(new EditAttributeCommand<Color>(attr));
        break;
    case cAttributeString:
        undoManager_->Push(new EditAttributeCommand<QString>(attr));
        break;
    case cAttributeBool:
        undoManager_->Push(new EditAttributeCommand<bool>(attr));
        break;
    case cAttributeQVariant:
        undoManager_->Push(new EditAttributeCommand<QVariant>(attr));
        break;
    case cAttributeQVariantList:
        undoManager_->Push(new EditAttributeCommand<QVariantList>(attr));
        break;
    case cAttributeEntityReference:
        undoManager_->Push(new EditAttributeCommand<EntityReference>(attr));
        break;
    case cAttributeAssetReference:
        undoManager_->Push(new EditAttributeCommand<AssetReference>(attr));
        break;
    case cAttributeAssetReferenceList:
        undoManager_->Push(new EditAttributeCommand<AssetReferenceList>(attr));
        break;
    case cAttributeTransform:
        undoManager_->Push(new EditAttributeCommand<Transform>(attr));
        break;
    case cAttributeQPoint:
        undoManager_->Push(new EditAttributeCommand<QPoint>(attr));
        break;
    default:
        LogWarning("Unknown attribute type " + attr->TypeName() + " for pushing into the undo stack.");
        break;
    }
}

void ECEditorWindow::OnUndoChanged(bool canUndo)
{
    undoButton_->setEnabled(canUndo);
}

void ECEditorWindow::OnRedoChanged(bool canRedo)
{
    redoButton_->setEnabled(canRedo);
}

UndoManager *ECEditorWindow::GetUndoManager()
{
    return undoManager_;
}

redpajama_set_name: RedPajamaGithub


If there are any inaccuracies, Email me.
Mercury unveiled the Cougar amid a great deal of excitement due to Ford's massive advertising campaigns in 1966. Despite this attention, many felt that the Cougar was doomed by Lincoln-Mercury's small dealer base and striking similarity to the smaller, cheaper Mustang.
The Cougar, however, surprised Detroit by winning Motor Trend's Car of the Year award in 1967. That wasn't all, Mercury received the best award from the public: 150,000 Cougars found buyers in 1967, and 110,000 left dealerships the following year. These first generation Cougars brilliantly married the endearing qualities of both the Thunderbird and Mustang and wrapped them in an attractive shell.
As the early 70s rolled along, so did Mercury's Cat. The Cougar had lost the performance appeal of the 60s in favor of the 70s trend of land barge luxury. The car had become, like the Mustang of that era, large, more aptly, corpulent. Sales declined until 1977.
The Cougar, still massive, found the years of 1977-1979 to be some of its best ever. In 1978, the Cat basked in the warm glow of 213,000 unit sales. These years also saw the Cougar's designers develop an intense and morbid love for chrome.
The most interesting item from the next few years was the short existence of a four door Cougar station wagon. This quasi-Cougar can be seen in my "Other Peoples' Cougars" page. According to CoolCats.net, the Cougars produced from 1980- 1982 were basically Zephyrs with a Cougar emblem thrown on. Most Cougar enthusiasts will tell you that these years were, to put it mildly, pathetic for Mercury's Cat.
Still using the Fox platform it gained in 1980, the Cougar adopted a curvy aerodynamic look that pleased buyers. Sales happily rose from 1983-1988, including 5,000 20th Anniversary Edition Cats that sold before Mercury could produce them.
After a switch to its old abode, the Thunderbird frame, the Cougar adopted a supercharged 3.8 litre V6 engine, denying customers of a V8, always an option before.
Any 1993 Cougar is an XR-7, because this is the year that Mercury tossed the LS model. As for the sales, they began a happy upward trend that year.
Over the next few years, the Cougar underwent several style changes, as well as some engine changes too. All this culminated with the last rear-wheel drive Cougar rolling off the assembly line in 1997, an new breed was coming.
The new Cougars, introduced in 1999, feature 2.o litter inline four cylinder engines with optional 2.5 litre V6s. A massive style change makes this Cat quite distinguishable from its earlier brothers.
In 2002, Mercury is planning to release its, ugh, four door Cougar. I know, its sad, but at least the handles on the excess doors are hidden inside the door frame.


Mohammad plotted to kill Lynn to lay her hands on his money.
Rolfe had a strange expression on his face.
Mario didn't tell me he lived in Boston.
Jerald got off the bus and waited for Werner to come and pick him up.
I like Suresh, but I'm not really his friend.
Plastic said that Sjaak helped him.
Renu could say no more.
Pascal knew that he couldn't do what Roman was asking him to do.
Everett has done so much for us already.
Rhonda didn't even say hi to me.
Alison stole some money from Knute.
Margaret had more important things on his mind.
I'm not scared of Stanley.
Siping isn't a professional musician.
Helen's girlfriend is taller, stronger, and smarter than he is.
Bruno seems to not like you very much.
Rusty slipped into his robe.
Kelly is closing the store.
Betsy has achieved remarkable results.


text:
» Forensic Science
Identifying the Use of a Sound Suppressor
Last Updated on Tue, 10 Dec 2019 | Forensic Science
Sometimes the "backyard gunsmith" does not fully accomplish his goal of converting a semiautomatic weapon to fully automatic, resulting in a weapon that will occasionally fire in the fully automatic mode. Actual test-firing is often the only way to confirm this. The firearms examiner can load two or three rounds initially and attempt to get the weapon to fire multiple rounds with one pull of the trigger. If this is unsuccessful, a full magazine may be used. By examining the internal workings of the weapon the examiner can usually tell if there has been any attempt made to modify the weapon. Directions ammunition. According to records of the supplier, the suspect had received the ammunition several months prior to the murders. Perhaps most incriminating was an instruction sheet for a suppressor tube from a firearms accessory company.
The firearms examiner confirmed that in addition to the common shaved areas on the sides of each bullet were rifling marks consistent with a Ruger Mark II pistol. This did not mean that only a Ruger Mark II could have fired the bullets, but it did mean that a Ruger Mark II was among the possible weapons that could have fired them.
Based on his lying to investigators about being at the business the day of the shootings, his acknowledged dispute with the owner, and the circumstantial evidence to support that he acquired subsonic ammunition, a suppressor tube, and a Ruger 22 Mark II pistol, the man was convicted of first-degree murder. At trial his defense had pointed out that subsonic ammunition is available to anyone and is used for target shooting. Likewise, the Ruger Mark II pistol in 22-caliber is a common target pistol. With regard to the suppressor tube brochure it also included other products unrelated to suppressor manufacture. Furthermore, no confirmation of the defendant having ever actually purchased a suppressor or a suppressor tube was ever found. Obviously, the jury did not think there was reasonable doubt about it. What do you think?
for converting various weapons to fire fully automatic are available on the Internet.
Another modification that the firearms examiner may encounter is a sound suppressor. These are generally referred to as "silencers," although that is a misnomer. The only way to completely silence a firearm is not to fire it. Sound suppressors are only feasible with single shot, semiautomatic, or fully automatic weapons. Revolvers cannot be effectively suppressed due to the open space between the cylinder and the frame. The sources of sound involved in the discharge of a weapon are the expansion of hot gases from the powder and primer, the bullet breaking the sound barrier, and the action of the weapon (the hammer falling and slide moving back to reload). The latter two are most easily taken care of. The use of subsonic ammunition, that is bullets traveling slower than the speed of sound, eliminates the sonic boom associated with a supersonic bullet as it breaks the sound barrier. The action of the weapon can be locked so that it does not cycle.
The expanding hot gases create most of the noise associated with the discharge of a firearm. By slowing down the rate of expansion, the sound may be suppressed. Devices used for this purpose range from a two-liter plastic bottle placed over the gun muzzle to sophisticated metal expansion chambers containing baffles of various types and designs. These more sophisticated suppressors may be integral to the barrel or screw onto the end of the barrel.
In any event all that is required for there to be a violation of the National Firearms Act is for there to be any decrease in the audible report of the weapon. This may simply be determined by the examiner test-firing the weapon in question with and without the alleged suppressor and listening for a discernable decrease in the report. A more reliable method is to used a decibel meter to record the number of decibels produced with and without the device. This allows the examiner to establish a quantitative measure of the sound suppression. Again, even the slightest decrease in the audible sound constitutes a violation of federal law if the device has not been registered with the ATF. Thus, an aluminum soda can or a plastic bottle would conceivably have to be registered as a suppressor to be legally placed over the muzzle of a firearm.
The question of whether there is evidence of a weapon being fired can be answered conclusively in some instances. Many times the results of these examinations are inconclusive. The amount of time that has passed since the time of the shooting is a primary consideration. For example, if a shooting took place only a matter of hours or even days before and a suspect weapon is determined to have a barrel that is full of dust, corrosion, or other foreign material, it is extremely unlikely that the weapon was used in the shooting.
On the other hand, a thoroughly clean barrel cannot be taken as evidence of anything other than that the owner is meticulous about his or her weapon. Even finding a few gunpowder particles inside the barrel only allows an examiner to be able to say that there is evidence of firing since the last time the weapon was cleaned. In most instances there would be no way to conclusively determine when that time of last cleaning was.
When a revolver is fired, a pattern of soot is deposited around the margins of the chamber on the face of the revolver cylinder. The term halo or cylinder flare is used to identify these deposits, as shown in the photograph. This soot pattern can be correlated with the rotation direction of the cylinder, the chamber under the hammer, and the number of fired cartridge cases to help establish evidence of recent firing. For example, if only one shot was fired in a shooting incident and a revolver is suspected to be the responsible weapon, the presence of a single cylinder flare would be circumstantial evidence that this could be the responsible weapon.
Research is currently being done to use the vaporous residue present in gun barrels and fired cartridge cases to establish approximate time since firing. These residues persist for up to a day or longer, then totally dissipate. By determining the presence and quantity of these residues, researchers hope to be able to estimate reliably the time of shooting. This work may lead to a method that can be used to confirm what presently can only be speculated.
As has been previously described, the firearms examiner's most common task is to determine whether bullets, cartridge cases, and shot shells have been fired in weapons either found at crime scenes or recovered from suspects. To do this the firearms examiner must obtain ammunition similar to that in question. The reason for this is that differences in the hardness of bullets and cartridge case brass can result in differences in the markings left by firearms. For example, lead bullets and copper jacketed bullets (that is, bullets consisting of an inner core of lead with
Cylinder flare (Courtesy of the author)
an outer skin of copper) acquire significantly different markings. Primer case composition can also vary, and some primer cases are much harder than others. This can also result in significantly different marks from the same firing pins and breech faces. As in any scientifically based test, the examiner must duplicate the actual event as closely as possible in order to be able to produce any meaningful results.
The firearms examiner will typically fire a minimum of three test rounds from the suspect weapon. The water trap is used to stop the bullets and minimize their distortion and alteration of surface markings from the interior of the gun barrel. Even with water, however, highvelocity bullets can distort and even disintegrate upon impact with the surface. Anyone who has done a belly flop into water knows that water is really not that soft! The firearms examiner must sometimes reduce the powder charge in a cartridge in order to slow the bullet enough to keep it from distorting or disintegrating. To do this the examiner refers to charts found in reloading manuals for "reduced loads" and manually reduces the powder charge of a commercially produced cartridge.
First the examiner removes the bullet using a tool known as an inertia bullet puller. This resembles a plastic mallet with a hollow head. The
Bullet puller (Courtesy of the author)\
cartridge is placed into a special collet (holder) that holds it in the hollow space. The puller is then struck against a hard surface with a swinging motion, like one would strike a blow with a hammer. The inertia of the bullet causes it to dislodge from the case while the collet holds the cartridge case in place. The examiner removes the powder, weights out a lesser portion, places it back into the cartridge case, then manually reinserts the bullet into the cartridge case. The reduced load is now ready to be fired.
A potential problem with firing reduced loads is that the cartridge case may not receive markings from the chamber, breech face, and firing pin that are as prominent as those from a full powder charge. This is because less powder results in less force of expansion. With lead bullets, however, less powder can actually result in better retention of barrel markings, since the hot gases associated with a full powder charge have a tendency to erode the soft lead. Copper jacketed bullets do not exhibit this effect.
Diagram of striations as viewed through a microscope
Once the examiner has collected the fired bullets and cartridge cases, the task of comparing microscopic markings on bullets and cartridge cases begins. This involves mounting two bullets or two cartridge cases on the comparison microscope, one on each side or stage, and carefully observing as one is slowly rotated while the other remains fixed. The idea is to find that particular area where the microscopic markings are of sufficient quality and quantity to call it a match. The figure illustrates the type of markings that the examiner looks for.
To answer the last of the questions posed in this section, the muzzle-to-target distance in a shooting incident, the firearms examiner may use several different approaches depending on the type of weapon involved. For shots from any type weapon the firearms examiner will first look for the presence of gunpowder particles on skin and/or clothing. The general rule of thumb is that gunpowder will be expected to strike the target if the shot was fired within arm's length or less. When a firearm is discharged, gunpowder particles exit the muzzle in a conical distribution. The farther away the target is from the muzzle of the gun, the greater the gunpowder pattern diameter will be, as illustrated in the diagram.
Exactly how far the gunpowder particle will travel horizontally depends on three things: particle shape, gravity, and air friction. Gunpowder for handguns comes in three different shapes known as ball, flattened ball, and flake or disk. To determine which gunpowder particle shape would travel the farthest, given the same initial velocity, one need only imagine trying to throw a soccer ball versus trying to throw a dish or plate baseball style. The aerodynamic shape of the ball powder (spherical) allows it to easily outdistance the other shapes.
Gunpowder deposition with increasing distance
6 Infobase Publishing
Conical distribution of gunpowder particles
Ball Flattened ball Flake
G Infobase Publishing
Gunpowder shapes (as emitted from a handgun)
Like that for handguns, gunpowder designed for use in rifle cartridges also comes in ball, flattened ball, and flake or disk, but tubular powder particles are available as well. The reason for the different powder particle shapes, or morphologies, has to do with differences in burning rates. Gunpowder may consist of nitrocellulose or a combination of nitrocellulose and nitroglycerin (so-called single-base and double-base powder). There is actually quite a lot of physics involved in the design of a cartridge. The reason is the differences in ballistic requirements: different barrel lengths, calibers, bullet weights, and bullet designs require specific loads for optimum performance. Shotgun shells (shot shells) involve similar considerations.
In order to be sure that cartridges can be successfully and safely fired from all sorts of different weapons under a wide variety of atmospheric conditions, manufacturers put more than enough powder in
The ability of ball powder to outdistance other gunpowder shapes is not only a consideration for powder particles traveling through the air but also through bodies and other dense material. In his textbook Gunshot Wound, Vincent Dimaio notes that he has encountered cases in which victims were shot through the head at contact or near contact range, and ball powder actually passed through the skull with the bullet.
In another case familiar to this author, a very obese man was shot in the side at contact range with a 357 magnum loaded with ammunition containing ball powder. The bullet exited the man's body on the opposite side. An examination of the man's wound at autopsy revealed gunpowder particles inside the wound tract. Examination of the man's shirt revealed no gunpowder around the entrance hole but a considerable amount of gunpowder on the inside of the shirt around the exit hole. The ball powder had traveled completely through this large man's body!
The author examined a case involving an errant shot in a drive-by shooting that struck and killed a young girl who happened to be standing in the wrong place at the wrong time. Who fired the fatal shot was in dispute. The bullet passed through the victim and was never recovered, so there was no way to identify the shooter's gun. Because two particles of ball powder were found on her clothing, it was proposed that the shot had to come from the man standing in the yard within eight feet (2.4 m) of her and not from the individual who was firing from the vehicle approximately 1 5 feet (4.6 m) away. An unrelated study conducted by Dimaio, however, showed that individual particles of ball powder fired from a 38-caliber revolver could travel as far as 20 feet (6.1 m). Thus, the shot could have come from the vehicle. Since no one knew which way the little girl had been facing when she was shot and both shooters were firing 38 revolvers with ball powder, it was not possible to rule out either.
How to Defeat Gun Confiscation Schemes
Improve your Baseball Swing
Firearms Examination Equipment
Johannes purkinje and the first attempt at fingerprint classification
The Contributions of Henry Goddard in London
Firearms And Fingerprints In The Crime
Chemistry and fingerprints
Defensive Handgun Training Drills, Baseball, Handguns, Target Shooting, National Firearms Act
Can gun powder residue be found if a silencer was used?
valentino trevisani
How to tell if bullets fired through a silencer?
How does a.com suppressor affect gunpowder?
How the forensic science check if s gun is firr?
How can you telk if bullet goes through silencer?
Can ballistics tell if a suppressor was used?
Tiblets
Why use subsonic ammunition when testing silencers?
Can identify a bullet from a silencer?
Can a silencer can change the bullet forensics?
kidane
How can forensics determine gun suppressors?
Tiffany Colvin
How can a silencer change ballistic evidence?

redpajama_set_name: RedPajamaCommonCrawl


Eyebright, like the name implies, has an affinity for the eyes and occular conditions. The herb is both taken internally and applied topically to reduce redness and irritation of the eyes associated with blepharitis and conjunctivitis. Eyebright can safely be applied topically as poultice or eye drops to reduce tearing and itchiness associated with allergies and infections.
Although research is limited, eyebright appears to have antiinflammatory effects. In addition to eye conditions, it is also used for inflammation of the respiratory tract. It is sometimes used for upper respiratory tracts (URTI) to decrease congestion and especially in the sinuses. In particular it helps alleviate symptoms associated with seasonal allergies including nasal congestion, sinus pain, tearing and itchy eyes.


text:
Home News Vermont Is Sublime During the Summer Months
Vermont Is Sublime During the Summer Months
Brattleboro Country Club
Vermont can be a sublime golf experience; great courses and magical countryside that can be enjoyed for a week or more when the temperatures rise. After a round there are lots of things to do and see, including world-class fly fishing, hiking, biking, canoeing, kayaking, shopping and parks. The courses are located at resorts, so stay and play options abound.
Some of the state's courses offer hilly routings, while others combine a traditional lowland layout with some elevation, which makes for a very different, testing and scenic day on the fairways and greens.
Brattleboro Country Club (www.BrattleboroCountryClub.com) has been called "a hidden gem" and our readers simply must try out this classic New England layout.
The course measures 6,533 from the tips and is full of interesting, challenging and fair holes. Take the par-five second for instance. The hole heads up a hill, takes a right turn to a narrow strip of fairway only to head up another hill for the third shot. Then there is the drivable par-four sixth, the classic risk-reward par-five seventh, and the long par-four 11th, where bogey doesn't feel all the bad.
A number of improvements to the course and clubhouse have been made in recent years, including a fresh look in the dining room, kitchen, and bar area, irrigation, tree work, cart paths, enhanced gardens and more. The club also has a new fleet of golf carts.
Green Mountain National Golf Club (www.GMNGC.com) in Killington is in its second year under new management, Brown Golf Management Company, which is working tirelessly to enhance an already notable facility.
Green Mountain features holes that have demanding tee and approach shots and places a premium on all-around ability. The course was carved out of the mountains, and thus offers solitude and a "private" golf experience. Gently sloping fairways that feature generous landing areas, distinctive changes in elevation, and undulating greens add to the beauty. There are centuries-old rock formations carved by glaciers, and the view from 16th tee is stunning.
The seventh hole is a downhill par-three that plays shorter than its 151 yards. With a ridge in the middle of the green, put your tee shot to the side of the ridge where the pin is located. There's a bunker in the back of the green.
Stratton Mountain Golf Course (www.Stratton.com) in Stratton has 27 holes and was designed by noted architect Geoffrey Cornish. The Forest, Lake and Mountain nines offer solid challenges to players of all abilities.
The second hole on the Lake 9 is a dogleg left, 395-yard par-four that calls for a sweeping draw around trees and then a mid-iron to a green guarded by bunkers in the front. The fifth hole on the Mountain 9 is a long, 621-yard par-five that asks for three accurate shots to reach the putting surface. And the third hole on the Forest 9 is a short par-four that is reachable for big hitters, but the tee shot will have to clear trees on the left.
Stratton Mountain Golf Course, Stratton, Vermont
The Mount Snow Golf Course (www.MountSnow.com) in Dover is one of Vermont's premier "mountain" courses and has been rated one of the top five layouts in the state by Golf Digest magazine. Designed by Cornish, the 18-hole, 6,943-yard (there are three other sets of tees) championship course has also been named one of the top 10 resort courses in the country.
The track meanders through the Vermont countryside and provides views of the Green Mountains, including the peaks of Mount Snow and Haystack Mountain. Tamaracks, oaks, birches and sugar maples line fairways, while the mountains provide a majestic backdrop. The front nine is spread over scenic expanses and the back nine winds its way through wooded terrain. Water comes into play on 11 holes and 41 sand traps are strategically located on almost every hole.
Killington Resort's course (www.Killington.com ) was also designed by Cornish, and the layout takes full advantage of unique mountain terrain. Snowmelt streams, a 2,000-foot elevation, and stunning vistas create a visually sweet venue in which to enjoy the game. The routing features a pleasing mix of holes. There is water on a number of holes, and enough sand bunkers to keep your attention on tee shots and approaches to the modest-sized putting surfaces.
The second hole is a 515-yard par-five that demands a long, straight drive to set up the second shot. The green is reachable in two shots by big hitters, but there is water that fronts the putting surface, so the wiser play is layup and wedge for the third shot.
The 18th is a nice finishing hole, playing 321 yards. Be careful on your tee shot on the par-four, as water hugs the left side of the fairway.
Killington Resort Golf Course
Killington, Vermont
Robert Trent Jones, Sr. designed the golf course at Sugarbush Resort (www.Sugarbush.com) and gave the layout a natural feel, allowing the course to unfold amid the beauty that pervades this area of upper New England. The course, a 6,464-yard, par-72 layout, opened in 1961, and rolls along the hilltops of the Mad River Valley.
Sugarbush is challenging yet fair. The second hole is a par-five that measures 510 yards from the tips and allows big hitters to crush driver and go for the green in two. The smarter play may be three shots to find the green.
To take advantage of Golfing Magazine's Free Golf offer, call 860-563-1633, or visit
Previous articleLots Going on in `Little Rhody' For Our Subscribers
Next articleShuttle Meadow Country Club Roars Into a Second Century
Brattleboro Country Club in Brattleboro, VT is a Must Play
Northern Trust Figures to be One Incredible Golf Experience


1. A fingernail or toenail.
2. A painful sore or swelling around a fingernail or toenail.
6. The border of epidermal tissue surrounding a fingernail or toenail.
7. The formative cells or tissue of a fingernail, toenail, or tooth.
8. The separation or loosening of a fingernail or toenail from its nail bed.
9. The strip of hardened skin at the base and sides of a fingernail or toenail.
10. With all those scary microbes out there, it's hard to get worked up over a toenail fungus or a case of athlete's foot.


Probably everyone time of the time faces an unexpected lack of cash caused by some emergencies or sudden but necessary expenses. Lots of people take them to cover such spending like holiday bills, car repair account, back to school costs, dental work etc. Quick Cash Loan in New Jersey is good replacement for standard credit because of its simplicity and quickness.
In simple terms, payday loan is a moderate Quick Cash Funding. Because of its nature Short Term Money Loans in New Jersey is not intended to be used for a long period and is not suitable for a great purchases like a car or a house. But it is a really good way to pay for emergencies or cover some small and unexpected money spending and stretch customer's buying power. You choose the amount of money that you want to borrow and a time when you want to pay it back by yourself (of course within the prescribed).
Usually it is quite fast and easy to get amount of money you need at time you need it by dint of Legit Payday Loans Online New Jersey. You can just visit one of hundreds retail locations of different companies in New Jersey to submit an online form. Or there is other variation to get some cash – Quick Cash Loan. It is generally the same conditions that regular Quick Cash Loan in New Jersey has, except the way of applying. The advantage of online method is that you can apply for an advance 24/7 New Jersey whenever it is comfortable for you. You can do it without going out home, just fill out form and wait for an answer. New Jersey Rapid Advance allows you to get needed cash as soon as it is possible because if your application is approved most of lenders in New Jersey transfer money to your account as fast as on the same business day.
While these strategies can be a lot of work, finding rentals in this manner may be cheaper in the long run because no brokerage fee will be involved. Although the owner is responsible for paying the this fee, this cost will typically be factored into the home's rental. To get an owner's perspective on vacation homes, check out Investing In A Vacation Home. Read the Whole Contract Unfortunately, Quuck are often so happy that they landed the vacation home they wanted and so eager to start having fun that they overlook the importance of the contract. But, this document shouldn't be ignored, as it explains what you are on the hook for. It will outline not only your payment schedule, but also your liability in case of damages or if extra cleaning is needed. Keep in mind that the costs involved in air conditioning or heating a vacation rental can be sizable, so be sure to factor those into Quck budget if the owner has not already included them in the rent.
What does "Quick Cash Loan in New Jersey" stand for?
Unlike long-term loans, these deals are meant to help people who need small sums of money and are able to return the money in a short period of time. As mentioned above, the sum of the loan is relatively slow (up to $1,000) so it can't help one to cover college expenses, to start a business or to buy a house. Commonly Quick Cash Loan in New Jersey used to pay bills and taxes, buy presents before salary day, etc.
What is the qualification for Quick Cash Loan in New Jersey & Quick Cash Funding?
Most of the procedures required to check applicant's personal information, make a decision and lend the money are performed online. This option helps to make Quick Cash Loan the fastest type of credits. You can fill and send your application anytime, because online services work 24/7 in New Jersey. Filling out the form doesn't take much time, too: due to small amount of required information, one can finish the form in a couple of minutes. Then it takes about an hour to connect the perspective client with a lender in New Jersey.
The loan agreement is provided as soon as the final decision on the Legit Payday Loans Online. After that the client can read the offer and decide whether to agree on the credit terms or to reject them. Rejecting the credit doesn't require any special procedures: one should just ignore the offer. In future the request can be easily repeated if necessary. If one does agree on the terms of the loan, the next step is signing the agreement with an e-sign. After that, it only takes about one business day to transfer the money to the borrower's bank account. If the direct deposit option is unavailable, but other criteria match, the experts can offer some other options. In most cases, it doesn't take more than one business day to receive the money after filling up and sending the form.
Since Rapid Advance in New Jersey are secured by the regular income of the borrower, bad credit history doesn't affect much on credit decisions. Though some lenders prefer to work in traditional ways and need to perform verifications on every credit with traditional bureaus, others only check if the perspective applicant has no enormous debts with other lenders or is not a bankrupt. That doesn't mean the credit history doesn't matter at all: low credit score can affect the terms and amounts of loan offers. But it doesn't prevent an applicant from being approved to get a loan.
There are a lot of unforeseeable circumstances which can prevent borrowers from covering their debts in time. Most of the lenders easily accept this if the borrower keeps in touch and propose to renew Quick Cash Funding in New Jersey for additional interest that is added to the total. One should know that this is not a cheap option. It can increase a small credit debt to the sizes which will be much harder for the borrower to repay. Please make sure to prevent these circumstances by contacting the lenders as soon as you can and informing them that you've got unexpected problems. One should also know that not all states allow renewals. Check the laws of your state on Quick Cash Loan in New Jersey before trying to renew your loan.
Applicable penalties, collection practices and all the additional fees for failing to pay off in time are explained in every individual loan agreement together with the cases of defaulted payment terms. This agreement should be read carefully and attentively by every applicant who wants to get a Rapid Advance. It is highly not recommended to sign the agreement without checking the terms. If one feels the penalties are too harsh, it may be a better choice to refuse from taking the loan. All of our New Jersey lenders are known for the most honest and soft conditions on the Quick Cash Loan in New Jersey, but that doesn't mean one shouldn't take own responsibility and think about consequences before signing the agreement. Additional fees and penalties can vary from deal to deal, so one should carefully read contract every time before accepting it, not only the first one.
New Jersey Quick Cash Loan - a Reliable Financial Support. Have once felt temporary financial insecurity? Now you must know the right solution because today there exist special Quick Cash Loan in New Jersey that you can get almost without hard attempts. They are called 'Quick Cash Loan' or 'Short Term Money Loans' and they offer good benefits. Either you need to cope with your medical bills or emergent car repair, Pay Advance will provide you with the fastest solution of your temporary financial trouble. Such loans are pretty convenient due to the possibility of online service. The clients should not get out of their homes but just use their mobiles or Internet for getting the needed sum on their accounts. The sum of money varies from $100 to $1000. The New Jersey loan is given on the day of your application and can last up to 30 days. Another factor to consider is the distance between your home and the store. The name of the loan itself means that money is given to your next salary.