<commit_before>#include "interaction_window.h"
#include "../components/equipment_component.h"
#include "../components/key_component.h"
#include "../components/player_component.h"
#include "../core/component_manager.h"
#include "../core/entity_manager.h"
#include "../core/event_manager.h"
#include "../widgets/frame.h"
#include "../widgets/label.h"
#include "../widgets/listbox.h"
#include "dialog_window.h"
#include "inspection_window.h"

void InteractionWindow::setup() {
    setTitle("Interact");
    setEscapeBehaviour(Window::EscapeBehaviour::CloseWindow);
}

void InteractionWindow::registerWidgets() {
    const unsigned int descriptionWidth = 15;
    const unsigned int commandWidth = 10;
    const unsigned int windowHeight = 10;

    getWidget<Frame>("frmBase")->setMergeBorders();

    Frame* frmEntityList = createWidget<Frame>("frmEntityList", 0, 0);
    frmEntityList->setMargin()
        ->setBorder()
        ->setWidth(descriptionWidth)
        ->setHeight(windowHeight);

    ListBox* lstEntities =
        createWidget<ListBox>("lstEntities", 0, 0, frmEntityList);
    lstEntities->setItemSelectedCallback(std::bind(
        &InteractionWindow::listSelection, this, std::placeholders::_1));
    lstEntities->setWidthStretchMargin(0)->setHeightStretchMargin(0);

    createWidget<Label>("txtInspect", descriptionWidth, 1)
        ->setText("inspect")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            events()->raise(std::make_shared<RegisterWindowEvent>(
                std::make_shared<InspectionWindow>(entity)));
        })
        ->setSensitive(false);
    createWidget<Label>("txtOpen", descriptionWidth, 2)
        ->setText("open")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            ComponentStore& store = m_components[lstEntities->getSelection()];

            if (store.open->open) {
                events()->raise(std::make_shared<CloseEntityEvent>(entity));
            } else if (store.open->locked) {
                events()->raise(
                    std::make_shared<AddLogMessageEvent>("It's locked!"));
            } else {
                events()->raise(std::make_shared<OpenEntityEvent>(entity));
            }
            events()->raise(std::make_shared<EndTurnEvent>());
        })
        ->setSensitive(false);
    createWidget<Label>("txtTalk", descriptionWidth, 3)
        ->setText("talk")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            events()->raise(
                std::make_shared<StartConversationEvent>(player.id, entity));
        })
        ->setSensitive(false);
    createWidget<Label>("txtDrop", descriptionWidth, 4)
        ->setText("pickup")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            events()->raise(
                std::make_shared<PickupEquipmentEvent>(player.id, entity));
            events()->raise(std::make_shared<EndTurnEvent>());
        })
        ->setSensitive(false);
    createWidget<Label>("txtLock", descriptionWidth, 5)
        ->setText("lock")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            Defer d([this]() {
                this->events()->raise(std::make_shared<EndTurnEvent>());
            });
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId lock = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            auto equipment = components()->get<EquipmentComponent>(player.id);
            if (!equipment) {
                events()->raise(std::make_shared<AddLogMessageEvent>(
                    "You don't carry any equipement"));
                return;
            }
            ComponentStore& store = m_components[lstEntities->getSelection()];

            for (auto item : equipment->carriedEquipment) {
                if (components()->get<KeyComponent>(item)) {
                    if (store.open->locked) {
                        events()->raise(
                            std::make_shared<UnlockEntityEvent>(item, lock));
                    } else {
                        events()->raise(
                            std::make_shared<LockEntityEvent>(item, lock));
                    }
                    return;
                }
            }
            events()->raise(std::make_shared<AddLogMessageEvent>(
                "None of your equipment can be used as a key"));
        })
        ->setSensitive(false);

    setHeight(windowHeight);
    setWidth(descriptionWidth + commandWidth);
    lstEntities->clearItems();
    for (EntityId entity : m_inputEntities) {
        ComponentStore store;
        store.desc = components()->get<DescriptionComponent>(entity);
        store.open = components()->get<OpenableComponent>(entity);
        store.drop = components()->get<DroppableComponent>(entity);
        store.npc = components()->get<NpcComponent>(entity);

        ListBoxItem item;
        item.setText(store.desc ? store.desc->title : "<Unknown>");
        lstEntities->addItem(item);
        m_entities.push_back(entity);
        m_components.push_back(store);
    }
    lstEntities->setSelection(0);
}

void InteractionWindow::updateScreen() {
    ListBox* lstEntities = getWidget<ListBox>("lstEntities");
    Label* txtInspect = getWidget<Label>("txtInspect");
    Label* txtOpen = getWidget<Label>("txtOpen");
    Label* txtDrop = getWidget<Label>("txtDrop");
    Label* txtTalk = getWidget<Label>("txtTalk");
    Label* txtLock = getWidget<Label>("txtLock");

    ComponentStore& store = m_components[lstEntities->getSelection()];

    txtInspect->setSensitive(store.desc != nullptr);
    txtOpen->setSensitive(store.open != nullptr);
    txtDrop->setSensitive(store.drop != nullptr);
    txtTalk->setSensitive(store.npc == nullptr);
    txtLock->setSensitive(store.open != nullptr);

    if (store.desc) {
        setTitle(store.desc->title);
    }
    if (store.open) {
        txtOpen->setText(store.open->open ? "close" : "open");
        txtLock->setText(store.open->locked ? "unlock" : "lock");
    }
}

void InteractionWindow::listSelection(ListBox* box) { updateScreen(); }

void InteractionWindow::nextTurn() { updateScreen(); }<commit_msg>Fix bug where talk command was inverted<commit_after>#include "interaction_window.h"
#include "../components/equipment_component.h"
#include "../components/key_component.h"
#include "../components/player_component.h"
#include "../core/component_manager.h"
#include "../core/entity_manager.h"
#include "../core/event_manager.h"
#include "../widgets/frame.h"
#include "../widgets/label.h"
#include "../widgets/listbox.h"
#include "dialog_window.h"
#include "inspection_window.h"

void InteractionWindow::setup() {
    setTitle("Interact");
    setEscapeBehaviour(Window::EscapeBehaviour::CloseWindow);
}

void InteractionWindow::registerWidgets() {
    const unsigned int descriptionWidth = 15;
    const unsigned int commandWidth = 10;
    const unsigned int windowHeight = 10;

    getWidget<Frame>("frmBase")->setMergeBorders();

    Frame* frmEntityList = createWidget<Frame>("frmEntityList", 0, 0);
    frmEntityList->setMargin()
        ->setBorder()
        ->setWidth(descriptionWidth)
        ->setHeight(windowHeight);

    ListBox* lstEntities =
        createWidget<ListBox>("lstEntities", 0, 0, frmEntityList);
    lstEntities->setItemSelectedCallback(std::bind(
        &InteractionWindow::listSelection, this, std::placeholders::_1));
    lstEntities->setWidthStretchMargin(0)->setHeightStretchMargin(0);

    createWidget<Label>("txtInspect", descriptionWidth, 1)
        ->setText("inspect")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            events()->raise(std::make_shared<RegisterWindowEvent>(
                std::make_shared<InspectionWindow>(entity)));
        })
        ->setSensitive(false);
    createWidget<Label>("txtOpen", descriptionWidth, 2)
        ->setText("open")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            ComponentStore& store = m_components[lstEntities->getSelection()];

            if (store.open->open) {
                events()->raise(std::make_shared<CloseEntityEvent>(entity));
            } else if (store.open->locked) {
                events()->raise(
                    std::make_shared<AddLogMessageEvent>("It's locked!"));
            } else {
                events()->raise(std::make_shared<OpenEntityEvent>(entity));
            }
            events()->raise(std::make_shared<EndTurnEvent>());
        })
        ->setSensitive(false);
    createWidget<Label>("txtTalk", descriptionWidth, 3)
        ->setText("talk")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            events()->raise(
                std::make_shared<StartConversationEvent>(player.id, entity));
        })
        ->setSensitive(false);
    createWidget<Label>("txtDrop", descriptionWidth, 4)
        ->setText("pickup")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId entity = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            events()->raise(
                std::make_shared<PickupEquipmentEvent>(player.id, entity));
            events()->raise(std::make_shared<EndTurnEvent>());
        })
        ->setSensitive(false);
    createWidget<Label>("txtLock", descriptionWidth, 5)
        ->setText("lock")
        ->setCommandChar(1)
        ->setCommandCharCallback([&](Label* l) {
            Defer d([this]() {
                this->events()->raise(std::make_shared<EndTurnEvent>());
            });
            ListBox* lstEntities = this->getWidget<ListBox>("lstEntities");
            EntityId lock = m_entities[lstEntities->getSelection()];
            auto player = components()->getUnique<PlayerComponent>();
            auto equipment = components()->get<EquipmentComponent>(player.id);
            if (!equipment) {
                events()->raise(std::make_shared<AddLogMessageEvent>(
                    "You don't carry any equipement"));
                return;
            }
            ComponentStore& store = m_components[lstEntities->getSelection()];

            for (auto item : equipment->carriedEquipment) {
                if (components()->get<KeyComponent>(item)) {
                    if (store.open->locked) {
                        events()->raise(
                            std::make_shared<UnlockEntityEvent>(item, lock));
                    } else {
                        events()->raise(
                            std::make_shared<LockEntityEvent>(item, lock));
                    }
                    return;
                }
            }
            events()->raise(std::make_shared<AddLogMessageEvent>(
                "None of your equipment can be used as a key"));
        })
        ->setSensitive(false);

    setHeight(windowHeight);
    setWidth(descriptionWidth + commandWidth);
    lstEntities->clearItems();
    for (EntityId entity : m_inputEntities) {
        ComponentStore store;
        store.desc = components()->get<DescriptionComponent>(entity);
        store.open = components()->get<OpenableComponent>(entity);
        store.drop = components()->get<DroppableComponent>(entity);
        store.npc = components()->get<NpcComponent>(entity);

        ListBoxItem item;
        item.setText(store.desc ? store.desc->title : "<Unknown>");
        lstEntities->addItem(item);
        m_entities.push_back(entity);
        m_components.push_back(store);
    }
    lstEntities->setSelection(0);
}

void InteractionWindow::updateScreen() {
    ListBox* lstEntities = getWidget<ListBox>("lstEntities");
    Label* txtInspect = getWidget<Label>("txtInspect");
    Label* txtOpen = getWidget<Label>("txtOpen");
    Label* txtDrop = getWidget<Label>("txtDrop");
    Label* txtTalk = getWidget<Label>("txtTalk");
    Label* txtLock = getWidget<Label>("txtLock");

    ComponentStore& store = m_components[lstEntities->getSelection()];

    txtInspect->setSensitive(store.desc != nullptr);
    txtOpen->setSensitive(store.open != nullptr);
    txtDrop->setSensitive(store.drop != nullptr);
    txtTalk->setSensitive(store.npc != nullptr);
    txtLock->setSensitive(store.open != nullptr);

    if (store.desc) {
        setTitle(store.desc->title);
    }
    if (store.open) {
        txtOpen->setText(store.open->open ? "close" : "open");
        txtLock->setText(store.open->locked ? "unlock" : "lock");
    }
}

void InteractionWindow::listSelection(ListBox* box) { updateScreen(); }

void InteractionWindow::nextTurn() { updateScreen(); }<|endoftext|>


<commit_before>#include "event_handler.h"

#include <string>
#include <vector>
#include <utility>
#include <iostream>
#include <iomanip>
#include <errno.h>
#include <sys/stat.h>
#include <CoreServices/CoreServices.h>

#include "flags.h"
#include "../../message.h"
#include "../../log.h"

using std::vector;
using std::string;
using std::move;
using std::ostream;
using std::hex;
using std::dec;
using std::endl;

class EventFunctor {
public:
  EventFunctor(EventHandler &handler, string &event_path, FSEventStreamEventFlags flags) :
    handler{handler},
    event_path{event_path},
    flags{flags},
    stat_performed{false}
  {
    flag_created = (flags & CREATE_FLAGS) != 0;
    flag_deleted = (flags & DELETED_FLAGS) != 0;
    flag_modified = (flags & MODIFY_FLAGS) != 0;
    flag_renamed = (flags & RENAME_FLAGS) != 0;
    flag_file = (flags & IS_FILE) != 0;
    flag_directory = (flags & IS_DIRECTORY) != 0;
  }

  void operator()()
  {
    report();
    determine_entry_kinds();
    LOGGER
      << "Entry kinds: current_kind=" << current_kind
      << " former_kind=" << former_kind << "." << endl;
    check_cache();
    LOGGER
      << "Cache status: seen_before=" << seen_before
      << " was_different_entry=" << was_different_entry << "." << endl;

    if (emit_if_unambiguous()) return;
    if (emit_if_absent()) return;
    emit_if_present();
  }

private:
  // Log the raw and interpreted flag information.
  void report()
  {
    ostream &logline = LOGGER;
    logline << "Native event received at [" << event_path << "]:" << endl;

    logline << "  event flags " << hex << flags << dec << " =";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagUserDropped) != 0) logline << " UserDropped";
    if ((flags & kFSEventStreamEventFlagKernelDropped) != 0) logline << " KernelDropped";
    if ((flags & kFSEventStreamEventFlagEventIdsWrapped) != 0) logline << " EventIdsWrapped";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagHistoryDone) != 0) logline << " HistoryDone";
    if ((flags & kFSEventStreamEventFlagRootChanged) != 0) logline << " RootChanged";
    if ((flags & kFSEventStreamEventFlagMount) != 0) logline << " Mount";
    if ((flags & kFSEventStreamEventFlagUnmount) != 0) logline << " Unmount";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagItemCreated) != 0) logline << " ItemCreated";
    if ((flags & kFSEventStreamEventFlagItemRemoved) != 0) logline << " ItemRemoved";
    if ((flags & kFSEventStreamEventFlagItemInodeMetaMod) != 0) logline << " ItemInodeMetaMod";
    if ((flags & kFSEventStreamEventFlagItemRenamed) != 0) logline << " ItemRenamed";
    if ((flags & kFSEventStreamEventFlagItemModified) != 0) logline << " ItemModified";
    if ((flags & kFSEventStreamEventFlagItemFinderInfoMod) != 0) logline << " ItemFinderInfoMod";
    if ((flags & kFSEventStreamEventFlagItemChangeOwner) != 0) logline << " ItemChangeOwner";
    if ((flags & kFSEventStreamEventFlagItemXattrMod) != 0) logline << " ItemXattrMod";
    if ((flags & kFSEventStreamEventFlagItemIsFile) != 0) logline << " ItemIsFile";
    if ((flags & kFSEventStreamEventFlagItemIsDir) != 0) logline << " ItemIsDir";
    if ((flags & kFSEventStreamEventFlagItemIsSymlink) != 0) logline << " ItemIsSymlink";
    if ((flags & kFSEventStreamEventFlagOwnEvent) != 0) logline << " OwnEvent";
    if ((flags & kFSEventStreamEventFlagItemIsHardlink) != 0) logline << " ItemIsHardlink";
    if ((flags & kFSEventStreamEventFlagItemIsLastHardlink) != 0) logline << " ItemIsLastHardlink";
    logline << endl;

    logline << "  interpreted as"
      << " file=" << flag_file
      << " directory=" << flag_directory
      << " created=" << flag_created
      << " deleted=" << flag_deleted
      << " modified=" << flag_modified
      << " renamed=" << flag_renamed
      << endl;
  }

  // Use the event flags and, if necessary, lstat() result to determine the current and previous kinds of
  // this entry.
  void determine_entry_kinds()
  {
    if (flag_file && !flag_directory) {
      former_kind = current_kind = KIND_FILE;
      return;
    }

    if (flag_directory && !flag_file) {
      former_kind = current_kind = KIND_DIRECTORY;
      return;
    }

    // Flags are ambiguous. Try to check lstat().
    ensure_lstat();
    if (!is_present) {
      // Check the cache to see what this entry was the last time it produced an event.
      former_kind = handler.cache.last_known_kind(event_path);

      // Because both flags are set on the event, it must have changed from one to the other over the lifespan
      // of this entry.
      if (former_kind == KIND_FILE) current_kind = KIND_DIRECTORY;
      if (former_kind == KIND_DIRECTORY) current_kind = KIND_FILE;

      return;
    }

    // We know what the entry is now. Because both flags have been set on the event, it must have been different before.
    if ((path_stat.st_mode & S_IFREG) != 0) {
      former_kind = KIND_DIRECTORY;
      current_kind = KIND_FILE;
    } else if ((path_stat.st_mode & S_IFDIR) != 0) {
      former_kind = KIND_FILE;
      current_kind = KIND_DIRECTORY;
    }

    // Leave both as KIND_UNKNOWN.
  }

  // Check the recently-seen entry cache for this entry.
  void check_cache()
  {
    seen_before = handler.cache.has_been_seen(event_path, current_kind);
    was_different_entry = current_kind != former_kind && handler.cache.has_been_seen(event_path, former_kind);
  }

  // Emit messages for events that have unambiguous flags.
  bool emit_if_unambiguous()
  {
    if (flag_created && !(flag_deleted || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous creation." << endl;
      handler.cache.does_exist(event_path, current_kind);
      handler.enqueue_creation(event_path, current_kind);
      return true;
    }

    if (flag_deleted && (!flag_created || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous deletion." << endl;
      handler.cache.does_not_exist(event_path);
      handler.enqueue_deletion(event_path, current_kind);
      return true;
    }

    if (flag_modified && !(flag_created || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous modification." << endl;
      handler.cache.does_exist(event_path, current_kind);
      handler.enqueue_modification(event_path, current_kind);
      return true;
    }

    return false;
  }

  // Emit messages based on the last observed state of this entry if it no longer exists.
  bool emit_if_absent()
  {
    ensure_lstat();
    if (is_present) return false;

    handler.cache.does_not_exist(event_path);

    if (flag_renamed) {
      handler.rename_old_path = event_path;
      return true;
    }

    if (!seen_before) {
      if (was_different_entry) {
        // Entry was last seen as a directory, but the latest event has it flagged as a file (or vice versa).
        // The directory must have been deleted.
        handler.enqueue_deletion(event_path, former_kind);
      }

      // Entry has not been seen before, so we must have missed its creation event.
      handler.enqueue_creation(event_path, former_kind);
    }

    // It isn't there now, so it must have been deleted.
    handler.enqueue_deletion(event_path, current_kind);
    return true;
  }

  // Emit messages based on the event flags and the current lstat() output.
  bool emit_if_present()
  {
    ensure_lstat();
    if (!is_present) return false;

    handler.cache.does_exist(event_path, current_kind);

    if (seen_before) {
      // This is *not* the first time an event at this path has been seen.
      if (flag_renamed && !handler.rename_old_path.empty()) {
        // The existing entry must have been deleted and a new entry renamed in its place.
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_rename(handler.rename_old_path, event_path, current_kind);

        handler.rename_old_path.clear();
      } else if (flag_deleted) {
        // Rapid creation and deletion. There may be a lost modification event just before deletion or just after
        // recreation.
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_creation(event_path, current_kind);
      } else {
        // Modification of an existing entry.
        handler.enqueue_modification(event_path, current_kind);
      }
    } else {
      // This *is* the first time an event has been seen at this path.
      if (flag_renamed && !handler.rename_old_path.empty()) {
        // The other half of an existing rename.
        handler.enqueue_rename(handler.rename_old_path, event_path, current_kind);

        handler.rename_old_path.clear();
      } else if (flag_deleted) {
        // The only way for the deletion flag to be set on an entry we haven't seen before is for the entry to
        // be rapidly created, deleted, and created again.
        handler.enqueue_creation(event_path, former_kind);
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_creation(event_path, current_kind);
      } else {
        // Otherwise, it must have been created. This may conceal a separate modification event just after
        // the entry's creation.
        handler.enqueue_creation(event_path, current_kind);
      }
    }

    return true;
  }

  // Call lstat() on the entry path if it has not already been called. After this function returns,
  // path_stat and is_present will be populated.
  void ensure_lstat()
  {
    if (stat_performed) return;

    if (lstat(event_path.c_str(), &path_stat) != 0) {
      errno_t stat_errno = errno;

      if (stat_errno == ENOENT) {
        is_present = false;
      }

      // Ignore lstat() errors on entries that:
      // (a) we aren't allowed to see
      // (b) are at paths with too many symlinks or looping symlinks
      // (c) have names that are too long
      // (d) have a path component that is (no longer) a directory
      // Log any other errno that we see.
      if (stat_errno != ENOENT &&
          stat_errno != EACCES &&
          stat_errno != ELOOP &&
          stat_errno != ENAMETOOLONG &&
          stat_errno != ENOTDIR) {
        LOGGER << "lstat(" << event_path << ") failed with errno " << errno << "." << endl;
      }
    } else {
      is_present = true;
    }

    stat_performed = true;
  }

  EventHandler &handler;

  string &event_path;
  FSEventStreamEventFlags flags;

  bool flag_created;
  bool flag_deleted;
  bool flag_modified;
  bool flag_renamed;
  bool flag_file;
  bool flag_directory;

  bool stat_performed;
  struct stat path_stat;
  bool is_present;

  EntryKind former_kind = KIND_UNKNOWN;
  EntryKind current_kind = KIND_UNKNOWN;

  bool seen_before;
  bool was_different_entry;
};

EventHandler::EventHandler(vector<Message> &messages, RecentFileCache &cache, ChannelID channel_id) :
  messages{messages},
  cache{cache},
  channel_id{channel_id}
{
  //
}

void EventHandler::handle(string &event_path, FSEventStreamEventFlags flags)
{
  EventFunctor callable(*this, event_path, flags);
  callable();
}

void EventHandler::enqueue_creation(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_CREATED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_modification(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_MODIFIED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_deletion(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_DELETED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_rename(string old_path, string new_path, const EntryKind &kind)
{
  FileSystemPayload payload(channel_id, ACTION_RENAMED, kind, move(old_path), move(new_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}
<commit_msg>Misplaced !<commit_after>#include "event_handler.h"

#include <string>
#include <vector>
#include <utility>
#include <iostream>
#include <iomanip>
#include <errno.h>
#include <sys/stat.h>
#include <CoreServices/CoreServices.h>

#include "flags.h"
#include "../../message.h"
#include "../../log.h"

using std::vector;
using std::string;
using std::move;
using std::ostream;
using std::hex;
using std::dec;
using std::endl;

class EventFunctor {
public:
  EventFunctor(EventHandler &handler, string &event_path, FSEventStreamEventFlags flags) :
    handler{handler},
    event_path{event_path},
    flags{flags},
    stat_performed{false}
  {
    flag_created = (flags & CREATE_FLAGS) != 0;
    flag_deleted = (flags & DELETED_FLAGS) != 0;
    flag_modified = (flags & MODIFY_FLAGS) != 0;
    flag_renamed = (flags & RENAME_FLAGS) != 0;
    flag_file = (flags & IS_FILE) != 0;
    flag_directory = (flags & IS_DIRECTORY) != 0;
  }

  void operator()()
  {
    report();
    determine_entry_kinds();
    LOGGER
      << "Entry kinds: current_kind=" << current_kind
      << " former_kind=" << former_kind << "." << endl;
    check_cache();
    LOGGER
      << "Cache status: seen_before=" << seen_before
      << " was_different_entry=" << was_different_entry << "." << endl;

    if (emit_if_unambiguous()) return;
    if (emit_if_absent()) return;
    emit_if_present();
  }

private:
  // Log the raw and interpreted flag information.
  void report()
  {
    ostream &logline = LOGGER;
    logline << "Native event received at [" << event_path << "]:" << endl;

    logline << "  event flags " << hex << flags << dec << " =";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagUserDropped) != 0) logline << " UserDropped";
    if ((flags & kFSEventStreamEventFlagKernelDropped) != 0) logline << " KernelDropped";
    if ((flags & kFSEventStreamEventFlagEventIdsWrapped) != 0) logline << " EventIdsWrapped";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagHistoryDone) != 0) logline << " HistoryDone";
    if ((flags & kFSEventStreamEventFlagRootChanged) != 0) logline << " RootChanged";
    if ((flags & kFSEventStreamEventFlagMount) != 0) logline << " Mount";
    if ((flags & kFSEventStreamEventFlagUnmount) != 0) logline << " Unmount";
    if ((flags & kFSEventStreamEventFlagMustScanSubDirs) != 0) logline << " MustScanSubDirs";
    if ((flags & kFSEventStreamEventFlagItemCreated) != 0) logline << " ItemCreated";
    if ((flags & kFSEventStreamEventFlagItemRemoved) != 0) logline << " ItemRemoved";
    if ((flags & kFSEventStreamEventFlagItemInodeMetaMod) != 0) logline << " ItemInodeMetaMod";
    if ((flags & kFSEventStreamEventFlagItemRenamed) != 0) logline << " ItemRenamed";
    if ((flags & kFSEventStreamEventFlagItemModified) != 0) logline << " ItemModified";
    if ((flags & kFSEventStreamEventFlagItemFinderInfoMod) != 0) logline << " ItemFinderInfoMod";
    if ((flags & kFSEventStreamEventFlagItemChangeOwner) != 0) logline << " ItemChangeOwner";
    if ((flags & kFSEventStreamEventFlagItemXattrMod) != 0) logline << " ItemXattrMod";
    if ((flags & kFSEventStreamEventFlagItemIsFile) != 0) logline << " ItemIsFile";
    if ((flags & kFSEventStreamEventFlagItemIsDir) != 0) logline << " ItemIsDir";
    if ((flags & kFSEventStreamEventFlagItemIsSymlink) != 0) logline << " ItemIsSymlink";
    if ((flags & kFSEventStreamEventFlagOwnEvent) != 0) logline << " OwnEvent";
    if ((flags & kFSEventStreamEventFlagItemIsHardlink) != 0) logline << " ItemIsHardlink";
    if ((flags & kFSEventStreamEventFlagItemIsLastHardlink) != 0) logline << " ItemIsLastHardlink";
    logline << endl;

    logline << "  interpreted as"
      << " file=" << flag_file
      << " directory=" << flag_directory
      << " created=" << flag_created
      << " deleted=" << flag_deleted
      << " modified=" << flag_modified
      << " renamed=" << flag_renamed
      << endl;
  }

  // Use the event flags and, if necessary, lstat() result to determine the current and previous kinds of
  // this entry.
  void determine_entry_kinds()
  {
    if (flag_file && !flag_directory) {
      former_kind = current_kind = KIND_FILE;
      return;
    }

    if (flag_directory && !flag_file) {
      former_kind = current_kind = KIND_DIRECTORY;
      return;
    }

    // Flags are ambiguous. Try to check lstat().
    ensure_lstat();
    if (!is_present) {
      // Check the cache to see what this entry was the last time it produced an event.
      former_kind = handler.cache.last_known_kind(event_path);

      // Because both flags are set on the event, it must have changed from one to the other over the lifespan
      // of this entry.
      if (former_kind == KIND_FILE) current_kind = KIND_DIRECTORY;
      if (former_kind == KIND_DIRECTORY) current_kind = KIND_FILE;

      return;
    }

    // We know what the entry is now. Because both flags have been set on the event, it must have been different before.
    if ((path_stat.st_mode & S_IFREG) != 0) {
      former_kind = KIND_DIRECTORY;
      current_kind = KIND_FILE;
    } else if ((path_stat.st_mode & S_IFDIR) != 0) {
      former_kind = KIND_FILE;
      current_kind = KIND_DIRECTORY;
    }

    // Leave both as KIND_UNKNOWN.
  }

  // Check the recently-seen entry cache for this entry.
  void check_cache()
  {
    seen_before = handler.cache.has_been_seen(event_path, current_kind);
    was_different_entry = current_kind != former_kind && handler.cache.has_been_seen(event_path, former_kind);
  }

  // Emit messages for events that have unambiguous flags.
  bool emit_if_unambiguous()
  {
    if (flag_created && !(flag_deleted || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous creation." << endl;
      handler.cache.does_exist(event_path, current_kind);
      handler.enqueue_creation(event_path, current_kind);
      return true;
    }

    if (flag_deleted && !(flag_created || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous deletion." << endl;
      handler.cache.does_not_exist(event_path);
      handler.enqueue_deletion(event_path, current_kind);
      return true;
    }

    if (flag_modified && !(flag_created || flag_modified || flag_renamed)) {
      LOGGER << "Unambiguous modification." << endl;
      handler.cache.does_exist(event_path, current_kind);
      handler.enqueue_modification(event_path, current_kind);
      return true;
    }

    return false;
  }

  // Emit messages based on the last observed state of this entry if it no longer exists.
  bool emit_if_absent()
  {
    ensure_lstat();
    if (is_present) return false;

    handler.cache.does_not_exist(event_path);

    if (flag_renamed) {
      handler.rename_old_path = event_path;
      return true;
    }

    if (!seen_before) {
      if (was_different_entry) {
        // Entry was last seen as a directory, but the latest event has it flagged as a file (or vice versa).
        // The directory must have been deleted.
        handler.enqueue_deletion(event_path, former_kind);
      }

      // Entry has not been seen before, so we must have missed its creation event.
      handler.enqueue_creation(event_path, former_kind);
    }

    // It isn't there now, so it must have been deleted.
    handler.enqueue_deletion(event_path, current_kind);
    return true;
  }

  // Emit messages based on the event flags and the current lstat() output.
  bool emit_if_present()
  {
    ensure_lstat();
    if (!is_present) return false;

    handler.cache.does_exist(event_path, current_kind);

    if (seen_before) {
      // This is *not* the first time an event at this path has been seen.
      if (flag_renamed && !handler.rename_old_path.empty()) {
        // The existing entry must have been deleted and a new entry renamed in its place.
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_rename(handler.rename_old_path, event_path, current_kind);

        handler.rename_old_path.clear();
      } else if (flag_deleted) {
        // Rapid creation and deletion. There may be a lost modification event just before deletion or just after
        // recreation.
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_creation(event_path, current_kind);
      } else {
        // Modification of an existing entry.
        handler.enqueue_modification(event_path, current_kind);
      }
    } else {
      // This *is* the first time an event has been seen at this path.
      if (flag_renamed && !handler.rename_old_path.empty()) {
        // The other half of an existing rename.
        handler.enqueue_rename(handler.rename_old_path, event_path, current_kind);

        handler.rename_old_path.clear();
      } else if (flag_deleted) {
        // The only way for the deletion flag to be set on an entry we haven't seen before is for the entry to
        // be rapidly created, deleted, and created again.
        handler.enqueue_creation(event_path, former_kind);
        handler.enqueue_deletion(event_path, former_kind);
        handler.enqueue_creation(event_path, current_kind);
      } else {
        // Otherwise, it must have been created. This may conceal a separate modification event just after
        // the entry's creation.
        handler.enqueue_creation(event_path, current_kind);
      }
    }

    return true;
  }

  // Call lstat() on the entry path if it has not already been called. After this function returns,
  // path_stat and is_present will be populated.
  void ensure_lstat()
  {
    if (stat_performed) return;

    if (lstat(event_path.c_str(), &path_stat) != 0) {
      errno_t stat_errno = errno;

      if (stat_errno == ENOENT) {
        is_present = false;
      }

      // Ignore lstat() errors on entries that:
      // (a) we aren't allowed to see
      // (b) are at paths with too many symlinks or looping symlinks
      // (c) have names that are too long
      // (d) have a path component that is (no longer) a directory
      // Log any other errno that we see.
      if (stat_errno != ENOENT &&
          stat_errno != EACCES &&
          stat_errno != ELOOP &&
          stat_errno != ENAMETOOLONG &&
          stat_errno != ENOTDIR) {
        LOGGER << "lstat(" << event_path << ") failed with errno " << errno << "." << endl;
      }
    } else {
      is_present = true;
    }

    stat_performed = true;
  }

  EventHandler &handler;

  string &event_path;
  FSEventStreamEventFlags flags;

  bool flag_created;
  bool flag_deleted;
  bool flag_modified;
  bool flag_renamed;
  bool flag_file;
  bool flag_directory;

  bool stat_performed;
  struct stat path_stat;
  bool is_present;

  EntryKind former_kind = KIND_UNKNOWN;
  EntryKind current_kind = KIND_UNKNOWN;

  bool seen_before;
  bool was_different_entry;
};

EventHandler::EventHandler(vector<Message> &messages, RecentFileCache &cache, ChannelID channel_id) :
  messages{messages},
  cache{cache},
  channel_id{channel_id}
{
  //
}

void EventHandler::handle(string &event_path, FSEventStreamEventFlags flags)
{
  EventFunctor callable(*this, event_path, flags);
  callable();
}

void EventHandler::enqueue_creation(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_CREATED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_modification(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_MODIFIED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_deletion(string event_path, const EntryKind &kind)
{
  string empty_path;

  FileSystemPayload payload(channel_id, ACTION_DELETED, kind, move(event_path), move(empty_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}

void EventHandler::enqueue_rename(string old_path, string new_path, const EntryKind &kind)
{
  FileSystemPayload payload(channel_id, ACTION_RENAMED, kind, move(old_path), move(new_path));
  Message event_message(move(payload));

  LOGGER << "Emitting filesystem message " << event_message << endl;

  messages.push_back(move(event_message));
}
<|endoftext|>


<commit_before>#ifndef STAN_MATH_OPENCL_ERR_CHECK_NAN_HPP
#define STAN_MATH_OPENCL_ERR_CHECK_NAN_HPP
#ifdef STAN_OPENCL
#include <stan/math/opencl/constants.hpp>
#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/matrix_cl_view.hpp>
#include <stan/math/opencl/copy.hpp>
#include <stan/math/opencl/kernels/check_nan.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>

#include <vector>

namespace stan {
namespace math {
/**
 * Check if the matrix_cl has NaN values
 *
 * @param function Function name (for error messages)
 * @param name Variable name (for error messages)
 * @param y matrix_cl to test
 *
 * @throw std::domain_error if
 *    any element of the matrix is NaN.
 */
template <typename T, typename = enable_if_floating_point<T>>
inline void check_nan(const char* function, const char* name,
                      const matrix_cl<T>& y) {
  if (y.size() == 0)
    return;
  try {
    int nan_flag = 0;
    matrix_cl<int> nan_chk(1, 1);
    nan_chk = to_matrix_cl(nan_flag);
    opencl_kernels::check_nan(cl::NDRange(y.rows(), y.cols()), y, nan_chk,
                              y.rows(), y.cols());
    nan_flag = from_matrix_cl_error_code(nan_chk);
    if (nan_flag) {
      domain_error(function, name, "has NaN values", "");
    }
  } catch (const cl::Error& e) {
    check_opencl_error("nan_check", e);
  }
}

}  // namespace math
}  // namespace stan
#endif
#endif
<commit_msg>post-merge fix<commit_after>#ifndef STAN_MATH_OPENCL_ERR_CHECK_NAN_HPP
#define STAN_MATH_OPENCL_ERR_CHECK_NAN_HPP
#ifdef STAN_OPENCL
#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/matrix_cl_view.hpp>
#include <stan/math/opencl/copy.hpp>
#include <stan/math/opencl/kernels/check_nan.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/scal/err/domain_error.hpp>

#include <vector>

namespace stan {
namespace math {
/**
 * Check if the matrix_cl has NaN values
 *
 * @param function Function name (for error messages)
 * @param name Variable name (for error messages)
 * @param y matrix_cl to test
 *
 * @throw std::domain_error if
 *    any element of the matrix is NaN.
 */
template <typename T, typename = enable_if_floating_point<T>>
inline void check_nan(const char* function, const char* name,
                      const matrix_cl<T>& y) {
  if (y.size() == 0)
    return;
  try {
    int nan_flag = 0;
    matrix_cl<int> nan_chk(1, 1);
    nan_chk = to_matrix_cl(nan_flag);
    opencl_kernels::check_nan(cl::NDRange(y.rows(), y.cols()), y, nan_chk,
                              y.rows(), y.cols());
    nan_flag = from_matrix_cl_error_code(nan_chk);
    if (nan_flag) {
      domain_error(function, name, "has NaN values", "");
    }
  } catch (const cl::Error& e) {
    check_opencl_error("nan_check", e);
  }
}

}  // namespace math
}  // namespace stan
#endif
#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_SCAL_FUN_CHOOSE_HPP
#define STAN_MATH_PRIM_SCAL_FUN_CHOOSE_HPP

#include <stan/math/prim/scal/err/check_nonnegative.hpp>
#include <stan/math/prim/scal/err/check_less_or_equal.hpp>
#include <boost/math/special_functions/binomial.hpp>
#include <limits>

namespace stan {
  namespace math {

    /**
     * Return the binomial coefficient for the specified integer
     * arguments.
     *
     * The binomial coefficient, \f${n \choose k}\f$, read "n choose k", is
     * defined for \f$0 \leq k \leq n\f$ (otherwise return 0) by
     *
     * \f${n \choose k} = \frac{n!}{k! (n-k)!}\f$.
     *
     * @param n total number of objects
     * @param k number of objects chosen
     * @return n choose k or 0 iff k > n
     * @throw std::domain_error if either argument is negative or the
     * result will not fit in an int type
     */
    inline int choose(int n, int k) {
      using stan::math::check_nonnegative;
      using stan::math::check_less_or_equal;
      check_nonnegative("choose", "n", n);
      check_nonnegative("choose", "k", k);
      if (k > n)
        return 0;
      const double choices = boost::math::binomial_coefficient<double>(n, k);
      check_less_or_equal("choose", "n choose k", choices,
                          std::numeric_limits<int>::max());
      // won't get proper round until C++11
      return static_cast<int>(choices < 0 ? choices - 0.5 : choices + 0.5);
    }

  }
}
#endif
<commit_msg>use std::round<commit_after>#ifndef STAN_MATH_PRIM_SCAL_FUN_CHOOSE_HPP
#define STAN_MATH_PRIM_SCAL_FUN_CHOOSE_HPP

#include <stan/math/prim/scal/err/check_nonnegative.hpp>
#include <stan/math/prim/scal/err/check_less_or_equal.hpp>
#include <boost/math/special_functions/binomial.hpp>
#include <limits>
#include <cmath>

namespace stan {
  namespace math {

    /**
     * Return the binomial coefficient for the specified integer
     * arguments.
     *
     * The binomial coefficient, \f${n \choose k}\f$, read "n choose k", is
     * defined for \f$0 \leq k \leq n\f$ (otherwise return 0) by
     *
     * \f${n \choose k} = \frac{n!}{k! (n-k)!}\f$.
     *
     * @param n total number of objects
     * @param k number of objects chosen
     * @return n choose k or 0 iff k > n
     * @throw std::domain_error if either argument is negative or the
     * result will not fit in an int type
     */
    inline int choose(int n, int k) {
      using stan::math::check_nonnegative;
      using stan::math::check_less_or_equal;
      check_nonnegative("choose", "n", n);
      check_nonnegative("choose", "k", k);
      if (k > n)
        return 0;
      const double choices = boost::math::binomial_coefficient<double>(n, k);
      check_less_or_equal("choose", "n choose k", choices,
                          std::numeric_limits<int>::max());
      return static_cast<int>(std::round(choices));
    }

  }
}
#endif
<|endoftext|>


<commit_before>//Adapted from sites.google.com/site/stevenhalim/home/material
//or cpbook.net
#include <cmath>
#include <vector>
#include <stack>
#include <algorithm>
#include <iostream>
#include <cfloat>

#include <cstdio>
#include <cstdlib>
#include <ctime>

#define COLLINEAR 0
#define LEFT 1
#define RIGHT -1
#define polygon vector<point>

using namespace std;
const double EPS = 0.000000001;

bool equal(double a, double b) { return fabs(a-b) < EPS; }

struct point;
struct line;
struct vec;
struct ray;

// use this whenever possible
//struct point { int x, y
struct point {
  double x,y;
  point();
  point(double _x, double _y);
  point(pair<double,double> p);
  bool operator== (const point& o) const;
  bool operator< (const point& other) const;
  vec operator- (const point& other);
  point operator+ (const vec& v);
};
bool sortPtsY(point a, point b){
  if (fabs(a.y - b.y) > EPS) return a.y < b.y;
  return a.x < b.x;
}

struct line {
  double a, b, c;
  line (const point& p1, const point& p2);
  bool equivalent(const line& other) const;
  bool operator== (const line& other) const;
  //are they parallel
  bool parallel(const line& other) const;
  bool operator|| (const line& other) const;
};

//struct vec { int dx, dy;
struct vec {
  double dx, dy, mag;
  vec(double x, double y);
  vec(const point& from, const point& to); // convert 2 points to vector
  vec(pair<double,double> p);

  vec normalize();

  //give the vector pointing to the left
  vec perpendicular();

  //vector addition
  vec operator+ (const vec& other);

  //scale
  vec operator* (double s);

  //dot product
  double operator* (const vec& other);
};

struct ray : public line {
  point origin, dest;
  ray (const point& p1, const point& p2);
};

point::point() :x(0), y(0) {}
point::point(double _x, double _y)
  :x(_x), y(_y)
{}
point::point(pair<double,double> p)
  :x(p.first), y(p.second)
{}
bool point::operator== (const point& o) const
{ return equal(x,o.x) && equal(y,o.y); }
bool point::operator< (const point& other) const{
  if (fabs(x - other.x) > EPS) return x < other.x;
  return y < other.y;
}
vec point::operator- (const point& other){ return vec(other,*this); }
point point::operator+ (const vec& v){ return point(x+v.dx,y+v.dy); }
double distance(const point& p1, const point& p2) {
  return hypot(p1.x - p2.x, p1.y - p2.y);
}

line::line (const point& p1, const point& p2) {
  // vertical line is handled nicely below
  //if (p1.x == p2.x) {
  if (equal(p1.x, p2.x)) {
    a = 1.0;
    b = 0.0;
    c = -p1.x;
  }

  else {
    a = -(double)(p1.y - p2.y) / (p1.x - p2.x);
    b = 1.0;
    c = -(double)(a * p1.x) - (b * p1.y);
  }
}

bool line::parallel(const line& other) const {
  // check coefficient a + b
  return (fabs(a-other.a) < EPS) && (fabs(b-other.b) < EPS);
}

bool line::operator|| (const line& other) const {
  return parallel(other);
}

bool line::equivalent(const line& other) const {
  return parallel(other) && (fabs(c - other.c) < EPS);
}

bool line::operator== (const line& other) const {
  return equivalent(other);
}

ray::ray(const point& p1, const point& p2)
  :line(p1,p2), origin(p1), dest(p2)
{}

bool intersect(const line& l1, const line& l2, point& p) {
  // all points same
  if (l1 == l2) { return false; }
  // no intersection
  if (l1 || l2) { return false; }

  // solve system of 2 linear algebraic equations with 2 unknowns
  p.x = (double)(l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);

  // test for vertical line (avoid div by zero)
  if (fabs(l1.b) > EPS) { p.y = - (l1.a * p.x + l1.c) / l1.b; }
  else { p.y = - (l2.a * p.x + l2.c) / l2.b; }

  return true;
}

vec::vec(double deltaX, double deltaY)
  : dx(deltaX), dy(deltaY)
{
  double magX = fabs(dx);
  double magY = fabs(dy);
  if (magX > EPS && magY > EPS) { mag = hypot(magX, magY); }
  else if (magX < EPS) { mag = magY; }
  else if (magY < EPS) { mag = magX; }
  else { mag = 0; }
}

vec::vec(const point& from, const point& to)
  :vec(to.x - from.x, to.y - from.y)
{}
vec::vec(pair<double,double> p)
  :vec(p.first, p.second)
{}
vec vec::normalize() { return vec(dx / mag, dy / mag); }
vec vec::operator+ (const vec & other){
  return vec(dx + other.dx, dy + other.dy);
}
vec vec::operator* (double s){ return vec(s * dx, s * dy); }
double vec::operator* (const vec & other){
  return dx * other.dx + dy * other.dy;
}
vec vec::perpendicular(){
  return vec(-dy,dx);
}

//square of triangle area
/*
int area2(point a, point b, point c) {
  return a.x * b.y - a.y * b.x + b.x * c.y - b.y * c.x + c.x * a.y - c.y * a.x;
}
*/

// square of distance between 2 points
int dist2(point a, point b) {
  int dx = a.x - b.x, dy = a.y - b.y; return dx * dx + dy * dy;
}

int turn(const point& a, const point& b, const point& c) {
  double result = (c.x - b.x) * (a.y - b.y) - (c.y - b.y) * (a.x - b.x);

  if (result < 0) return RIGHT; // a->B->C is a right turn
  if (result > 0) return LEFT; // a->B->C is a left turn

  return COLLINEAR; // a->B->C is a straight line, i.e. a, B, C are collinear
}

//useful for ray casting
//a & b are endpoints on the line segment in question
//assume that they are neither r.origin nor r.dest
bool rayIntersect(const ray& r, point& a, point& b, point& p) {
  line l(a,b);
  if (intersect(r,l,p)){
    point o = r.origin;
    point d = r.dest;

    //if we follow the ray's line and turn at the "dest" point to a
    int oda = turn(o,d,a);

    //if we follow the ray's line and turn at the "dest" point to b
    int odb = turn(o,d,b);

    //weird cases: pass thru an endpoint
    if (p == a) { return odb == turn(o,a,b); }
    if (p == b) { return oda == turn(o,b,a); }

    //if we follow the ray's line and turn at the intersection point to a
    int opa = turn(o,p,a);

    //if we cut through segment ab,
    //turning to a at either d or p should be the same direction
    //and turning to a should be different from turning to b
    return oda == opa && oda != odb;
  }

  return false;
}

/* The following code assumes CLOCKWISE or COUNTERCLOCKWISE ORDER! */

double perimeter(polygon& p) {
  double result = 0.0;

  //double x1, y1, x2, y2, dx, dy;
  for (int i = 0; i < p.size(); i++) {
    result += distance(p[i],p[(i+1)%p.size()]);
  }

  return result;
}

double determinant(polygon& p) {
  double result = 0;

  double x1, y1, x2, y2;
  for (int i = 0; i < p.size(); i++) {
    x1 = p[i].x; x2 = p[(i + 1) % p.size()].x;
    y1 = p[i].y; y2 = p[(i + 1) % p.size()].y;
    result += (x1 * y2 - x2 * y1);
  }

  return result;
}

// area is half of the determinant and the result may be a non-integer
double area(polygon& p)
{ return fabs(determinant(p)) / 2.0; }

//important angle-sorting functor for convex hull
class LeftTurnCmp{
private:
  point pivot;
public:
  LeftTurnCmp(const point& pivot) :pivot(pivot) {}
  bool operator()(const point& a, const point& b){
    if (turn(pivot, a, b) == COLLINEAR)
      return dist2(pivot, a) < dist2(pivot, b); // which one closer
    int d1x = a.x - pivot.x, d1y = a.y - pivot.y;
    int d2x = b.x - pivot.x, d2y = b.y - pivot.y;
    return (atan2((double)d1y, (double)d1x)
	    - atan2((double)d2y, (double)d2x)) < 0;
  }
};

void orderByAngle(polygon& p){
  // first, find p0 = point with lowest Y and if tie: rightmost X
  int lowestIndex = 0;
  int n = p.size();

  for (int i = 1; i < n; i++) {
    if (p[i].y < p[lowestIndex].y ||
	(p[i].y == p[lowestIndex].y && p[i].x > p[lowestIndex].x))
      { lowestIndex = i; }
  }

  swap(p[0],p[lowestIndex]);

  // second, sort points by angle w.r.t. lowest
  LeftTurnCmp angle_cmp(p[0]);
  sort(++p.begin(), p.end(), angle_cmp);
}

//n must be >= 3 for this method to work
void getConvexHull(polygon& p, polygon& convexHull){
  int n = p.size();

  stack<point> S;
  point prev, now;
  S.push(p[n - 1]); // put two starting vertices into stack S
  S.push(p[0]);

  int i = 1; // and start checking the rest

  while (i < n) {
    // get the 2nd item from top of S
    now = S.top();
    S.pop();
    prev = S.top();
    S.push(now);

    if (turn(prev, now, p[i]) == LEFT) {
      S.push(p[i]); // accept
      i++;
    }

    // otherwise pop this point until we have a left turn
    else { S.pop(); }
  }

  while (!S.empty()) { // from stack back to vector
    convexHull.push_back(S.top());
    S.pop();
  }

  convexHull.pop_back(); // the last one is a duplicate of first one
}

//ray-casting
bool inPolygon(polygon& p, point& pt){
  //ensure that we'll hit an edge by picking a midpoint
  point alt((p[0].x + p[1].x) / 2, (p[0].y + p[1].y) / 2);
  ray r(pt,alt);

  int edgesHit = 0;

  for(int i = 0; i < p.size(); i++){
    point contact;
    point thisPoint = p[i];
    point nextPoint = p[(i+1)%p.size()];

    if (rayIntersect(r, thisPoint, nextPoint, contact)) {
      edgesHit++;
    }
  }

  return (edgesHit % 2);
}

void closestDist(vector<point> pts_x, int left, int right,
		   vector<point> pts_y,
		 point& a, point& b, double& minD){
  if (left-right == 1) { return; }
  if (left-right == 2) {
    double d = distance(pts_x[left],pts_x[left+1]);
    if (d < minD) {
      a = pts_x[left];
      b = pts_x[left+1];
      minD = d;
    }
    return;
  }

  //double ans = DBL_MAX;

  //recurse
  int mid = (left+right)/2;
  int mid_x = pts_x[mid].x;
  closestDist(pts_x,left,mid,pts_y,a,b,minD);
  closestDist(pts_x,mid,right,pts_y,a,b,minD);

  //make strip
  vector<point> strip;
  for(auto pt: pts_y){
    if (pt.x > mid_x-minD && pt.x < mid_x+minD) { strip.push_back(pt); }
  }

  //check strip
  for(int i = 0; i < strip.size(); i++){

    //we'll only check from left side to right side
    if (strip[i].x >= mid_x) { continue; }

    for(int j = 0; j < 4; j++){
      //don't go overboard
      if (i+j >= strip.size()) { break; }

      double d = distance(strip[i],strip[j]);
      if (d < minD) {
	minD = d;
	a = strip[i];
	b = strip[j];
      }
    }
  }

  return;
}

double closestDist(vector<point> pts, point& a, point& b){
  sort(pts.begin(), pts.end());

  vector<point> pts_y;
  copy(pts.begin(), pts.end(), pts_y.begin());
  sort(pts_y.begin(), pts_y.end(), sortPtsY);

  double minD = DBL_MAX;
  closestDist(pts,0,pts.size(),pts_y, a,b, minD);
  return minD;
}

int main(){
  polygon p = {{0,0}, {5,0}, {0,5}, {2,7}, {5,5} };
  orderByAngle(p);
  cout << perimeter(p) << ' ' << area(p) << endl;
}
<commit_msg>More improvements to raycasting<commit_after>//Adapted from sites.google.com/site/stevenhalim/home/material
//or cpbook.net
#include <cmath>
#include <vector>
#include <stack>
#include <algorithm>
#include <iostream>
#include <cfloat>

#include <cstdio>
#include <cstdlib>
#include <ctime>

#define COLLINEAR 0
#define LEFT 1
#define RIGHT -1
#define polygon vector<point>

using namespace std;
const double EPS = 0.000000001;
const double PI = 3.141592654;

bool equal(double a, double b) { return fabs(a-b) < EPS; }

struct point;
struct line;
struct vec;
struct ray;

// use this whenever possible
//struct point { int x, y
struct point {
  double x,y;
  point();
  point(double _x, double _y);
  point(pair<double,double> p);
  bool operator== (const point& o) const;
  bool operator< (const point& other) const;
  vec operator- (const point& other);
  point operator+ (const vec& v);
};
bool sortPtsY(point a, point b){
  if (fabs(a.y - b.y) > EPS) return a.y < b.y;
  return a.x < b.x;
}

struct line {
  double a, b, c;
  line (const point& p1, const point& p2);
  bool equivalent(const line& other) const;
  bool operator== (const line& other) const;
  //are they parallel
  bool parallel(const line& other) const;
  bool operator|| (const line& other) const;
  bool has(const point& p) const;
};

//struct vec { int dx, dy;
struct vec {
  double dx, dy, mag;
  vec(double x, double y);
  vec(const point& from, const point& to); // convert 2 points to vector
  vec(pair<double,double> p);

  vec normalize();

  //give the vector pointing to the left
  vec perpendicular();

  //vector addition
  vec operator+ (const vec& other);

  //scale
  vec operator* (double s);

  //dot product
  double operator* (const vec& other);
};

struct ray : public line {
  point origin, dest;
  ray (const point& p1, const point& p2);
};

point::point() :x(0), y(0) {}
point::point(double _x, double _y)
  :x(_x), y(_y)
{}
point::point(pair<double,double> p)
  :x(p.first), y(p.second)
{}
bool point::operator== (const point& o) const
{ return equal(x,o.x) && equal(y,o.y); }
bool point::operator< (const point& other) const{
  if (fabs(x - other.x) > EPS) return x < other.x;
  return y < other.y;
}
vec point::operator- (const point& other){ return vec(other,*this); }
point point::operator+ (const vec& v){ return point(x+v.dx,y+v.dy); }
double distance(const point& p1, const point& p2) {
  return hypot(p1.x - p2.x, p1.y - p2.y);
}

line::line (const point& p1, const point& p2) {
  // vertical line is handled nicely below
  //if (p1.x == p2.x) {
  if (equal(p1.x, p2.x)) {
    a = 1.0;
    b = 0.0;
    c = -p1.x;
  }

  else {
    a = -(double)(p1.y - p2.y) / (p1.x - p2.x);
    b = 1.0;
    c = -(double)(a * p1.x) - (b * p1.y);
  }
}

bool line::parallel(const line& other) const {
  // check coefficient a + b
  return (fabs(a-other.a) < EPS) && (fabs(b-other.b) < EPS);
}

bool line::operator|| (const line& other) const {
  return parallel(other);
}

bool line::equivalent(const line& other) const {
  return parallel(other) && (fabs(c - other.c) < EPS);
}

bool line::operator== (const line& other) const {
  return equivalent(other);
}

bool line::has(const point& p) const { return equal(a*p.x + b*p.y + c, 0); }

ray::ray(const point& p1, const point& p2)
  :line(p1,p2), origin(p1), dest(p2)
{}

bool intersect(const line& l1, const line& l2, point& p) {
  // all points same
  if (l1 == l2) { return false; }
  // no intersection
  if (l1 || l2) { return false; }

  // solve system of 2 linear algebraic equations with 2 unknowns
  p.x = (double)(l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);

  // test for vertical line (avoid div by zero)
  if (fabs(l1.b) > EPS) { p.y = - (l1.a * p.x + l1.c) / l1.b; }
  else { p.y = - (l2.a * p.x + l2.c) / l2.b; }

  return true;
}

vec::vec(double deltaX, double deltaY)
  : dx(deltaX), dy(deltaY)
{
  double magX = fabs(dx);
  double magY = fabs(dy);
  if (magX > EPS && magY > EPS) { mag = hypot(magX, magY); }
  else if (magX < EPS) { mag = magY; }
  else if (magY < EPS) { mag = magX; }
  else { mag = 0; }
}

vec::vec(const point& from, const point& to)
  :vec(to.x - from.x, to.y - from.y)
{}
vec::vec(pair<double,double> p)
  :vec(p.first, p.second)
{}
vec vec::normalize() { return vec(dx / mag, dy / mag); }
vec vec::operator+ (const vec & other){
  return vec(dx + other.dx, dy + other.dy);
}
vec vec::operator* (double s){ return vec(s * dx, s * dy); }
double vec::operator* (const vec & other){
  return dx * other.dx + dy * other.dy;
}
vec vec::perpendicular(){
  return vec(-dy,dx);
}

//square of triangle area
/*
int area2(point a, point b, point c) {
  return a.x * b.y - a.y * b.x + b.x * c.y - b.y * c.x + c.x * a.y - c.y * a.x;
}
*/

// square of distance between 2 points
int dist2(point a, point b) {
  int dx = a.x - b.x, dy = a.y - b.y; return dx * dx + dy * dy;
}

int turn(const point& a, const point& b, const point& c) {
  double result = (c.x - b.x) * (a.y - b.y) - (c.y - b.y) * (a.x - b.x);

  if (result < 0) return RIGHT; // a->B->C is a right turn
  if (result > 0) return LEFT; // a->B->C is a left turn

  return COLLINEAR; // a->B->C is a straight line, i.e. a, B, C are collinear
}

//useful for ray casting
//a & b are endpoints on the line segment in question
//assume that they are neither r.origin nor r.dest
bool rayIntersect(const ray& r, point& a, point& b, point& p) {
  line l(a,b);
  if (intersect(r,l,p)){
    point o = r.origin;
    point d = r.dest;

    //if we follow the ray's line and turn at the "dest" point to a
    int oda = turn(o,d,a);

    //if we follow the ray's line and turn at the "dest" point to b
    int odb = turn(o,d,b);

    //weird cases: pass thru an endpoint
    if (p == a) { return odb == turn(o,a,b); }
    if (p == b) { return oda == turn(o,b,a); }

    //if we follow the ray's line and turn at the intersection point to a
    int opa = turn(o,p,a);

    //if we cut through segment ab,
    //turning to a at either d or p should be the same direction
    //and turning to a should be different from turning to b
    return oda == opa && oda != odb;
  }

  return false;
}

/* The following code assumes CLOCKWISE or COUNTERCLOCKWISE ORDER! */

double perimeter(polygon& p) {
  double result = 0.0;

  //double x1, y1, x2, y2, dx, dy;
  for (int i = 0; i < p.size(); i++) {
    result += distance(p[i],p[(i+1)%p.size()]);
  }

  return result;
}

double determinant(polygon& p) {
  double result = 0;

  double x1, y1, x2, y2;
  for (int i = 0; i < p.size(); i++) {
    x1 = p[i].x; x2 = p[(i + 1) % p.size()].x;
    y1 = p[i].y; y2 = p[(i + 1) % p.size()].y;
    result += (x1 * y2 - x2 * y1);
  }

  return result;
}

// area is half of the determinant and the result may be a non-integer
double area(polygon& p)
{ return fabs(determinant(p)) / 2.0; }

double angle(point a, point pivot, point b){
  return (atan2(a.y-pivot.y, a.x-pivot.x) - atan2(b.y-pivot.y, b.x-pivot.x));
}

//important angle-sorting functor for convex hull
class AngleCmp{
private:
  point pivot;
public:
  AngleCmp(const point& pivot) :pivot(pivot) {}
  bool operator()(const point& a, const point& b){

    if (turn(pivot, a, b) == COLLINEAR) {
      return dist2(pivot, a) < dist2(pivot, b); // which one closer
    }

    return angle(a,pivot,b) < 0;
  }
};

void orderByAngle(polygon& p){
  // first, find p0 = point with lowest Y and if tie: rightmost X
  int lowestIndex = 0;
  int n = p.size();

  for (int i = 1; i < n; i++) {
    if (p[i].y < p[lowestIndex].y ||
	(p[i].y == p[lowestIndex].y && p[i].x > p[lowestIndex].x))
      { lowestIndex = i; }
  }

  swap(p[0],p[lowestIndex]);

  // second, sort points by angle w.r.t. lowest
  AngleCmp ac(p[0]);
  sort(++p.begin(), p.end(), ac);
}

//n must be >= 3 for this method to work
void getConvexHull(polygon& p, polygon& convexHull){
  int n = p.size();

  stack<point> S;
  point prev, now;
  S.push(p[n - 1]); // put two starting vertices into stack S
  S.push(p[0]);

  int i = 1; // and start checking the rest

  while (i < n) {
    // get the 2nd item from top of S
    now = S.top();
    S.pop();
    prev = S.top();
    S.push(now);

    if (turn(prev, now, p[i]) == LEFT) {
      S.push(p[i]); // accept
      i++;
    }

    // otherwise pop this point until we have a left turn
    else { S.pop(); }
  }

  while (!S.empty()) { // from stack back to vector
    convexHull.push_back(S.top());
    S.pop();
  }

  convexHull.pop_back(); // the last one is a duplicate of first one
}

//ray-casting
bool inPolygon(polygon& p, point& pt){
  //stupid case
  if (pt == p[0]) { return true; }

  //pick arbitrary vertex u
  point u = p[0];
  point v = p[0];
  double minAngle = DBL_MAX;

  //find the vertex v s.t. (angle u-pt-v) is minimal
  //this ensures there are no vertices in between
  for(int i = 1; i < p.size(); i++){
    //stupid case again
    if (p[i] == pt) { return true; }
    double theta = abs(angle(u,pt,p[i]));
    if (theta < minAngle) {
      minAngle = theta;
      v = p[i];
    }
  }

  point alt((u.x + v.x)/2, (u.y + v.y)/2);
  ray r(pt,alt);

  int edgesHit = 0;

  for(int i = 0; i < p.size(); i++){
    point contact;
    point thisPoint = p[i];
    point nextPoint = p[(i+1)%p.size()];

    if (rayIntersect(r, thisPoint, nextPoint, contact)) {
      edgesHit++;
    }
  }

  return (edgesHit % 2);
}

void closestDist(vector<point> pts_x, int left, int right,
		   vector<point> pts_y,
		 point& a, point& b, double& minD){
  if (left-right == 1) { return; }
  if (left-right == 2) {
    double d = distance(pts_x[left],pts_x[left+1]);
    if (d < minD) {
      a = pts_x[left];
      b = pts_x[left+1];
      minD = d;
    }
    return;
  }

  //double ans = DBL_MAX;

  //recurse
  int mid = (left+right)/2;
  int mid_x = pts_x[mid].x;
  closestDist(pts_x,left,mid,pts_y,a,b,minD);
  closestDist(pts_x,mid,right,pts_y,a,b,minD);

  //make strip
  vector<point> strip;
  for(auto pt: pts_y){
    if (pt.x > mid_x-minD && pt.x < mid_x+minD) { strip.push_back(pt); }
  }

  //check strip
  for(int i = 0; i < strip.size(); i++){

    //we'll only check from left side to right side
    if (strip[i].x >= mid_x) { continue; }

    for(int j = 0; j < 4; j++){
      //don't go overboard
      if (i+j >= strip.size()) { break; }

      double d = distance(strip[i],strip[j]);
      if (d < minD) {
	minD = d;
	a = strip[i];
	b = strip[j];
      }
    }
  }

  return;
}

double closestDist(vector<point> pts, point& a, point& b){
  sort(pts.begin(), pts.end());

  vector<point> pts_y;
  copy(pts.begin(), pts.end(), pts_y.begin());
  sort(pts_y.begin(), pts_y.end(), sortPtsY);

  double minD = DBL_MAX;
  closestDist(pts,0,pts.size(),pts_y, a,b, minD);
  return minD;
}

int main(){
  polygon p = {{0,0}, {5,0}, {0,5}, {2,7}, {5,5} };
  orderByAngle(p);
  cout << perimeter(p) << ' ' << area(p) << endl;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>
#endif

#include "base/environment.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/win/scoped_com_initializer.h"
#include "build/build_config.h"
#include "content/common/content_switches.h"
#include "content/common/gpu/gpu_config.h"
#include "content/common/main_function_params.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "ui/gfx/gl/gl_surface.h"

#if defined(OS_MACOSX)
#include "content/common/chrome_application_mac.h"
#elif defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#endif

#if defined(USE_X11)
#include "ui/base/x/x11_util.h"
#endif

// Main function for starting the Gpu process.
int GpuMain(const MainFunctionParams& parameters) {
  base::Time start_time = base::Time::Now();

  const CommandLine& command_line = parameters.command_line_;
  if (command_line.HasSwitch(switches::kGpuStartupDialog)) {
    ChildProcess::WaitForDebugger("Gpu");
  }

  // Initialization of the OpenGL bindings may fail, in which case we
  // will need to tear down this process. However, we can not do so
  // safely until the IPC channel is set up, because the detection of
  // early return of a child process is implemented using an IPC
  // channel error. If the IPC channel is not fully set up between the
  // browser and GPU process, and the GPU process crashes or exits
  // early, the browser process will never detect it.  For this reason
  // we defer tearing down the GPU process until receiving the
  // GpuMsg_Initialize message from the browser.
  bool dead_on_arrival = false;

#if defined(OS_WIN)
  sandbox::TargetServices* target_services =
      parameters.sandbox_info_.TargetServices();
  // For windows, if the target_services interface is not zero, the process
  // is sandboxed and we must call LowerToken() before rendering untrusted
  // content.
  if (target_services)
    target_services->LowerToken();
#endif

  // Load the GL implementation and locate the bindings before starting the GPU
  // watchdog because this can take a lot of time and the GPU watchdog might
  // terminate the GPU process.
  if (!gfx::GLSurface::InitializeOneOff()) {
    LOG(INFO) << "GLContext::InitializeOneOff failed";
    dead_on_arrival = true;
  }

#if defined(OS_MACOSX)
  chrome_application_mac::RegisterCrApp();
#endif

  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
  base::PlatformThread::SetName("CrGpuMain");

  if (!command_line.HasSwitch(switches::kSingleProcess)) {
#if defined(OS_WIN)
    // Prevent Windows from displaying a modal dialog on failures like not being
    // able to load a DLL.
    SetErrorMode(
        SEM_FAILCRITICALERRORS |
        SEM_NOGPFAULTERRORBOX |
        SEM_NOOPENFILEERRORBOX);
#elif defined(USE_X11)
    ui::SetDefaultX11ErrorHandlers();
#endif
  }

  base::win::ScopedCOMInitializer com_initializer;

  GpuProcess gpu_process;

  GpuChildThread* child_thread = new GpuChildThread(dead_on_arrival);

  child_thread->Init(start_time);

  gpu_process.set_main_thread(child_thread);

  main_message_loop.Run();

  child_thread->StopWatchdog();

  return 0;
}
<commit_msg>Initialize the GL bindings before sandboxing the GPU process on Windows. This is an attempt to fix a regression. Unfortunately, the problem does not manifest with a local Chromium Release build, only those coming from the waterfall, so this fix has not yet been verified.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>
#endif

#include "base/environment.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/win/scoped_com_initializer.h"
#include "build/build_config.h"
#include "content/common/content_switches.h"
#include "content/common/gpu/gpu_config.h"
#include "content/common/main_function_params.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "ui/gfx/gl/gl_surface.h"

#if defined(OS_MACOSX)
#include "content/common/chrome_application_mac.h"
#elif defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#endif

#if defined(USE_X11)
#include "ui/base/x/x11_util.h"
#endif

// Main function for starting the Gpu process.
int GpuMain(const MainFunctionParams& parameters) {
  base::Time start_time = base::Time::Now();

  const CommandLine& command_line = parameters.command_line_;
  if (command_line.HasSwitch(switches::kGpuStartupDialog)) {
    ChildProcess::WaitForDebugger("Gpu");
  }

  // Initialization of the OpenGL bindings may fail, in which case we
  // will need to tear down this process. However, we can not do so
  // safely until the IPC channel is set up, because the detection of
  // early return of a child process is implemented using an IPC
  // channel error. If the IPC channel is not fully set up between the
  // browser and GPU process, and the GPU process crashes or exits
  // early, the browser process will never detect it.  For this reason
  // we defer tearing down the GPU process until receiving the
  // GpuMsg_Initialize message from the browser.
  bool dead_on_arrival = false;

  // Load the GL implementation and locate the bindings before starting the GPU
  // watchdog because this can take a lot of time and the GPU watchdog might
  // terminate the GPU process.
  if (!gfx::GLSurface::InitializeOneOff()) {
    LOG(INFO) << "GLContext::InitializeOneOff failed";
    dead_on_arrival = true;
  }

#if defined(OS_WIN)
  sandbox::TargetServices* target_services =
      parameters.sandbox_info_.TargetServices();
  // For windows, if the target_services interface is not zero, the process
  // is sandboxed and we must call LowerToken() before rendering untrusted
  // content.
  if (target_services)
    target_services->LowerToken();
#endif

#if defined(OS_MACOSX)
  chrome_application_mac::RegisterCrApp();
#endif

  MessageLoop main_message_loop(MessageLoop::TYPE_UI);
  base::PlatformThread::SetName("CrGpuMain");

  if (!command_line.HasSwitch(switches::kSingleProcess)) {
#if defined(OS_WIN)
    // Prevent Windows from displaying a modal dialog on failures like not being
    // able to load a DLL.
    SetErrorMode(
        SEM_FAILCRITICALERRORS |
        SEM_NOGPFAULTERRORBOX |
        SEM_NOOPENFILEERRORBOX);
#elif defined(USE_X11)
    ui::SetDefaultX11ErrorHandlers();
#endif
  }

  base::win::ScopedCOMInitializer com_initializer;

  GpuProcess gpu_process;

  GpuChildThread* child_thread = new GpuChildThread(dead_on_arrival);

  child_thread->Init(start_time);

  gpu_process.set_main_thread(child_thread);

  main_message_loop.Run();

  child_thread->StopWatchdog();

  return 0;
}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------
/// \file   VertexStats.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 24 July 2016
// -------------------------------------------------------------------

#include <TChain.h>
#include <TGeoManager.h>
#include <TGeoNode.h>
#include <TGeoVolume.h>
#include <TLorentzVector.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>

#include <iostream>
#include <getopt.h>

namespace {
  std::string geometry_file_("");
  std::string genie_files_("");
  struct DetVol {
    std::string name;
    TVector3 position;
    int num_vertices;
  };
}

void ParseCmdLineOptions(int argc, char** argv)
{
  int c;

  while (true) {
    static struct option long_options[] =
    {
      {"geometry",    required_argument, 0, 'g'},
      {"genie_files", required_argument, 0, 'i'},
      {0, 0, 0, 0}
    };

    int option_index = 0;

    c = getopt_long(argc, argv, "g:i:", long_options, &option_index);

    if (c == -1) break;

    switch (c) {
      case 'g':
        geometry_file_ = std::string(optarg);
        break;
      case 'i':
        genie_files_ = std::string(optarg);
        break;
      case '?':
        exit(EXIT_FAILURE);
        break;
      default:
        exit(EXIT_FAILURE);
    }
  }
}

TGeoManager* LoadGeometry(const std::string& filename)
{
  TGeoManager* gm = new TGeoManager();
  gm->Import(filename.c_str());
  if (!(gm->GetTopNode())) {
    std::cerr << "ERROR: Failed to open geometry file." << std::endl;
    exit(EXIT_FAILURE);
  }
  return gm;
}

TChain* OpenGenieFiles(const std::string& filename)
{
  TChain* chain = new TChain("gtree");
  int num_files;
  num_files = chain->Add(filename.c_str());
  std::cout << num_files << std::endl;
  return chain;
}

int main(int argc, char** argv)
{
  ParseCmdLineOptions(argc, argv);
  TGeoManager* geomgr = LoadGeometry(geometry_file_);
  TChain* chain = OpenGenieFiles(genie_files_);

  genie::NtpMCEventRecord* mcrec = 0;
  chain->SetBranchAddress("gmcrec", &mcrec);

  std::cout << "Loaded geometry" << std::endl;

  TFile* current_file = 0;
  double total_pot = 0.;

  std::cout << "Number of entries in TChain: " << chain->GetEntries() << std::endl;

  std::map<TGeoNode*, DetVol> node_map;

  for (int i=0; i<chain->GetEntries(); i++) {

    // Load a new entry from the chain
    chain->GetEntry(i);
    genie::EventRecord* record = mcrec->event;

    // Locate the interaction vertex in the geometry.
    // (Quantities stored by GENIE are expressed in the SI, while ROOT's
    // TGeoManager uses the CGS. Therefore, we multiply the vertex position
    // by a factor of 100 to transform from m to cm.)
    TGeoNode* node = geomgr->FindNode(record->Vertex()->X() * 100.,
                                      record->Vertex()->Y() * 100.,
                                      record->Vertex()->Z() * 100.);

    if (geomgr->GetLevel() > 2) {
      geomgr->CdUp();
      node = geomgr->GetCurrentNode();
    }

    auto it = node_map.find(node);
    if (it == node_map.end()) {
      DetVol dv;
      dv.name = std::string(node->GetName());
      const Double_t* xyz = node->GetMatrix()->GetTranslation();
      dv.position.SetXYZ(xyz[0], xyz[1], xyz[2]);
      dv.num_vertices = 1;
    }
    else {
      (*it).second.num_vertices++;
    }

  }

  for (auto kv: node_map) {
    std::cout << "Name: " << kv.second.name << std::endl;
  }

  return 0;
}
<commit_msg>Corrections to VertexStats.<commit_after>// -------------------------------------------------------------------
/// \file   VertexStats.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 24 July 2016
// -------------------------------------------------------------------

#include <TChain.h>
#include <TGeoManager.h>
#include <TGeoNode.h>
#include <TGeoVolume.h>
#include <TLorentzVector.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>

#include <iostream>
#include <getopt.h>

namespace {
  std::string geometry_file_("");
  std::string genie_files_("");
  struct DetVol {
    std::string name;
    TVector3 position;
    int num_vertices;
  };
}

void ParseCmdLineOptions(int argc, char** argv)
{
  int c;

  while (true) {
    static struct option long_options[] =
    {
      {"geometry",    required_argument, 0, 'g'},
      {"genie_files", required_argument, 0, 'i'},
      {0, 0, 0, 0}
    };

    int option_index = 0;

    c = getopt_long(argc, argv, "g:i:", long_options, &option_index);

    if (c == -1) break;

    switch (c) {
      case 'g':
        geometry_file_ = std::string(optarg);
        break;
      case 'i':
        genie_files_ = std::string(optarg);
        break;
      case '?':
        exit(EXIT_FAILURE);
        break;
      default:
        exit(EXIT_FAILURE);
    }
  }
}

TGeoManager* LoadGeometry(const std::string& filename)
{
  TGeoManager* gm = new TGeoManager();
  gm->Import(filename.c_str());
  if (!(gm->GetTopNode())) {
    std::cerr << "ERROR: Failed to open geometry file." << std::endl;
    exit(EXIT_FAILURE);
  }
  return gm;
}

TChain* OpenGenieFiles(const std::string& filename)
{
  TChain* chain = new TChain("gtree");
  int num_files;
  num_files = chain->Add(filename.c_str());
  std::cout << num_files << std::endl;
  return chain;
}

int main(int argc, char** argv)
{
  ParseCmdLineOptions(argc, argv);
  TGeoManager* geomgr = LoadGeometry(geometry_file_);
  TChain* chain = OpenGenieFiles(genie_files_);

  genie::NtpMCEventRecord* mcrec = 0;
  chain->SetBranchAddress("gmcrec", &mcrec);

  std::cout << "Loaded geometry" << std::endl;

  TFile* current_file = 0;
  double total_pot = 0.;

  std::cout << "Number of entries in TChain: " << chain->GetEntries() << std::endl;

  std::map<TGeoNode*, DetVol> node_map;

  for (int i=0; i<chain->GetEntries(); i++) {

    // Load a new entry from the chain
    chain->GetEntry(i);
    genie::EventRecord* record = mcrec->event;

    // Locate the interaction vertex in the geometry.
    // (Quantities stored by GENIE are expressed in the SI, while ROOT's
    // TGeoManager uses the CGS. Therefore, we multiply the vertex position
    // by a factor of 100 to transform from m to cm.)
    TGeoNode* node = geomgr->FindNode(record->Vertex()->X() * 100.,
                                      record->Vertex()->Y() * 100.,
                                      record->Vertex()->Z() * 100.);

    if (geomgr->GetLevel() > 2) {
      geomgr->CdUp();
      node = geomgr->GetCurrentNode();
    }

    auto it = node_map.find(node);
    if (it == node_map.end()) {
      DetVol dv;
      dv.name = std::string(node->GetName());
      const Double_t* xyz = node->GetMatrix()->GetTranslation();
      dv.position.SetXYZ(xyz[0], xyz[1], xyz[2]);
      dv.num_vertices = 1;
      node_map[node] = dv;
    }
    else {
      (*it).second.num_vertices++;
    }

  }

  for (auto kv: node_map) {
    std::cout << "----------" << std::endl;
    std::cout << " Name: " << kv.second.name << std::endl;
    std::cout << " Position (cm) = (" << kv.second.position.x() << ", "
	      << kv.second.position.y() << ", " << kv.second.position.z() << ")" << std::endl;
    std::cout << " Num. vertices: " << kv.second.num_vertices << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>#include <gecode/search/connector.hh>
#include <iostream>
#include <unistd.h>
#include <ctime>
#include <sstream>

template <typename T>
std::string NumberToString ( T Number )
{
  std::ostringstream ss;
  ss << Number;
    return ss.str();
}

namespace Profiling {

  Node::Node(int sid, int pid, int alt, int kids, NodeStatus status, Connector& c) : _c(c) {

    _node.set_type(message::Node::NODE);

    _node.set_sid(sid);
    _node.set_pid(pid);
    _node.set_alt(alt);
    _node.set_kids(kids);
    _node.set_status(static_cast<message::Node::NodeStatus>(status));
    _node.set_thread_id(-1); /// -1 is default for thread id
  }

  Node::~Node() {

  }

}

namespace Profiling {

  Connector::Connector(unsigned int port, unsigned int tid)
  : port(port), _thread_id(tid), context(1), socket(context, ZMQ_PUSH) {
    // begin_time = system_clock::now();
  }

  void Connector::sendOverSocket(const message::Node &msg) {
    std::string msg_str;
    msg.SerializeToString(&msg_str);

    zmq::message_t request(msg_str.size());
    memcpy((void*)request.data(), msg_str.c_str(), msg_str.size());

    // Sometimes sending will fail with EINTR.  In this case, we try to
    // send the message again.
    while (true) {
      int failed_attempts = 0;
      try {
        bool sentOK = socket.send(request);
        // If sentOK is false, there was an EAGAIN.  We handle this the
        // same as EINTR.
        if (!sentOK) {
          failed_attempts++;
          if (failed_attempts > 10) abort();
          continue;
        }
        // Success: stop the loop.
        break;
      } catch (zmq::error_t &e) {
        failed_attempts++;
        if (failed_attempts > 10) abort();
        if (e.num() == EINTR) {
          continue;
        }
        // If it was something other than EINTR, rethrow the exception.
        throw e;
      }
    }
  }

  void Connector::sendNode(int sid, int pid, int alt, int kids,
                           NodeStatus status, const char* label, unsigned int thread, int restart,
                           float domain, const std::string& nogood, const std::string& info) {

    // current_time = system_clock::now();
    // unsigned long long timestamp = static_cast<long long>(duration_cast<microseconds>(current_time - begin_time).count());

    message::Node node;

    node.set_type(message::Node::NODE);

    node.set_sid(sid);
    node.set_pid(pid);
    node.set_alt(alt);
    node.set_kids(kids);

    node.set_status(static_cast<message::Node::NodeStatus>(status));
    node.set_label(label);
    node.set_thread_id(thread);
    node.set_restart_id(restart);
    node.set_domain_size(domain);
    // node.set_solution(solution);
    node.set_nogood(nogood);
    node.set_info(info);

    sendOverSocket(node);
  }

  Node Connector::createNode(int sid, int pid, int alt, int kids, NodeStatus status) {
    return Node(sid, pid, alt, kids, status, *this);
  }

  void Connector::sendNode(const Profiling::Node& node) {
    sendOverSocket(node.get_node());
  }

  void Connector::restart(const std::string& file_path, int restart_id) {
    // std::cerr << "restarting gist, restart_id: " << restart_id << "\n";

    message::Node dummy_node;
    dummy_node.set_type(message::Node::START);

    /// should it be restart_id instead?
    dummy_node.set_restart_id(-1);

    /// extract fzn file name
    std::string name(file_path);
    int pos = name.find_last_of('/');
    if (pos > 0) {
      name = name.substr(pos + 1, name.length() - pos - 1);
    }

    dummy_node.set_label(name);

    sendOverSocket(dummy_node);
  }

  void Connector::connect() {
    std::string address = "tcp://localhost:" + NumberToString(port);
    socket.connect(address.c_str());
    std::cout << "sending over port: " << port << "\n";
  }

  void Connector::done() {
    message::Node dummy_node;
    dummy_node.set_type(message::Node::DONE);
    sendOverSocket(dummy_node);
  }

  void Connector::disconnect() {
    socket.close();
  }

}

namespace Profiling {

  void Node::send() {
    this->_c.sendNode(*this);
  }<commit_msg>tiny fix<commit_after>#include <gecode/search/connector.hh>
#include <iostream>
#include <unistd.h>
#include <ctime>
#include <sstream>

template <typename T>
std::string NumberToString ( T Number )
{
  std::ostringstream ss;
  ss << Number;
    return ss.str();
}

namespace Profiling {

  Node::Node(int sid, int pid, int alt, int kids, NodeStatus status, Connector& c) : _c(c) {

    _node.set_type(message::Node::NODE);

    _node.set_sid(sid);
    _node.set_pid(pid);
    _node.set_alt(alt);
    _node.set_kids(kids);
    _node.set_status(static_cast<message::Node::NodeStatus>(status));
    _node.set_thread_id(-1); /// -1 is default for thread id
  }

  Node::~Node() {

  }

}

namespace Profiling {

  Connector::Connector(unsigned int port, unsigned int tid)
  : port(port), _thread_id(tid), context(1), socket(context, ZMQ_PUSH) {
    // begin_time = system_clock::now();
  }

  void Connector::sendOverSocket(const message::Node &msg) {
    std::string msg_str;
    msg.SerializeToString(&msg_str);

    zmq::message_t request(msg_str.size());
    memcpy((void*)request.data(), msg_str.c_str(), msg_str.size());

    // Sometimes sending will fail with EINTR.  In this case, we try to
    // send the message again.
    while (true) {
      int failed_attempts = 0;
      try {
        bool sentOK = socket.send(request);
        // If sentOK is false, there was an EAGAIN.  We handle this the
        // same as EINTR.
        if (!sentOK) {
          failed_attempts++;
          if (failed_attempts > 10) abort();
          continue;
        }
        // Success: stop the loop.
        break;
      } catch (zmq::error_t &e) {
        failed_attempts++;
        if (failed_attempts > 10) abort();
        if (e.num() == EINTR) {
          continue;
        }
        // If it was something other than EINTR, rethrow the exception.
        throw e;
      }
    }
  }

  void Connector::sendNode(int sid, int pid, int alt, int kids,
                           NodeStatus status, const char* label, unsigned int thread, int restart,
                           float domain, const std::string& nogood, const std::string& info) {

    // current_time = system_clock::now();
    // unsigned long long timestamp = static_cast<long long>(duration_cast<microseconds>(current_time - begin_time).count());

    message::Node node;

    node.set_type(message::Node::NODE);

    node.set_sid(sid);
    node.set_pid(pid);
    node.set_alt(alt);
    node.set_kids(kids);

    node.set_status(static_cast<message::Node::NodeStatus>(status));
    node.set_label(label);
    node.set_thread_id(thread);
    node.set_restart_id(restart);
    node.set_domain_size(domain);
    // node.set_solution(solution);
    node.set_nogood(nogood);
    node.set_info(info);

    sendOverSocket(node);
  }

  Node Connector::createNode(int sid, int pid, int alt, int kids, NodeStatus status) {
    return Node(sid, pid, alt, kids, status, *this);
  }

  void Connector::sendNode(const Profiling::Node& node) {
    sendOverSocket(node.get_node());
  }

  void Connector::restart(const std::string& file_path, int restart_id) {
    // std::cerr << "restarting gist, restart_id: " << restart_id << "\n";

    message::Node dummy_node;
    dummy_node.set_type(message::Node::START);

    /// should it be restart_id instead?
    dummy_node.set_restart_id(-1);

    /// extract fzn file name
    std::string name(file_path);
    int pos = name.find_last_of('/');
    if (pos > 0) {
      name = name.substr(pos + 1, name.length() - pos - 1);
    }

    dummy_node.set_label(name);

    sendOverSocket(dummy_node);
  }

  void Connector::connect() {
    std::string address = "tcp://localhost:" + NumberToString(port);
    socket.connect(address.c_str());
    std::cout << "sending over port: " << port << "\n";
  }

  void Connector::done() {
    message::Node dummy_node;
    dummy_node.set_type(message::Node::DONE);
    sendOverSocket(dummy_node);
  }

  void Connector::disconnect() {
    socket.close();
  }

}

namespace Profiling {

  void Node::send() {
    this->_c.sendNode(*this);
  }

}<|endoftext|>


<commit_before>#ifndef STAN_MATH_REV_MAT_FUN_LOG_DETERMINANT_SPD_HPP
#define STAN_MATH_REV_MAT_FUN_LOG_DETERMINANT_SPD_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/mat/err/check_square.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/rev/core.hpp>

namespace stan {
  namespace math {

    template <int R, int C>
    inline var log_determinant_spd(const Eigen::Matrix<var, R, C>& m) {
      using Eigen::Matrix;

      check_square("log_determinant_spd", "m", m);

      Matrix<double, R, C> m_d(m.rows(), m.cols());
      for (int i = 0; i < m.size(); ++i)
        m_d(i) = m(i).val();

      Eigen::LDLT<Matrix<double, R, C> > ldlt(m_d);
      if (ldlt.info() != Eigen::Success) {
        double y = 0;
        domain_error("log_determinant_spd",
                "matrix argument", y,
                "failed LDLT factorization");
      }

      // compute the inverse of A (needed for the derivative)
      m_d.setIdentity(m.rows(), m.cols());
      ldlt.solveInPlace(m_d);

      if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) {
        double y = 0;
        domain_error("log_determinant_spd",
                "matrix argument", y,
                "matrix is negative definite");
      }

      double val = ldlt.vectorD().array().log().sum();

      check_finite("log_determinant_spd", "log determininant of the matrix argument", val);

      vari** operands = ChainableStack::memalloc_
        .alloc_array<vari*>(m.size());
      for (int i = 0; i < m.size(); ++i)
        operands[i] = m(i).vi_;

      double* gradients = ChainableStack::memalloc_
        .alloc_array<double>(m.size());
      for (int i = 0; i < m.size(); ++i)
        gradients[i] = m_d(i);

      return var(new precomputed_gradients_vari(val, m.size(),
                                                operands, gradients));
    }

  }

}
#endif
<commit_msg>cpplint<commit_after>#ifndef STAN_MATH_REV_MAT_FUN_LOG_DETERMINANT_SPD_HPP
#define STAN_MATH_REV_MAT_FUN_LOG_DETERMINANT_SPD_HPP

#include <stan/math/prim/scal/err/domain_error.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/mat/err/check_square.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/rev/core.hpp>

namespace stan {
  namespace math {

    template <int R, int C>
    inline var log_determinant_spd(const Eigen::Matrix<var, R, C>& m) {
      using Eigen::Matrix;

      check_square("log_determinant_spd", "m", m);

      Matrix<double, R, C> m_d(m.rows(), m.cols());
      for (int i = 0; i < m.size(); ++i)
        m_d(i) = m(i).val();

      Eigen::LDLT<Matrix<double, R, C> > ldlt(m_d);
      if (ldlt.info() != Eigen::Success) {
        double y = 0;
        domain_error("log_determinant_spd",
                "matrix argument", y,
                "failed LDLT factorization");
      }

      // compute the inverse of A (needed for the derivative)
      m_d.setIdentity(m.rows(), m.cols());
      ldlt.solveInPlace(m_d);

      if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) {
        double y = 0;
        domain_error("log_determinant_spd",
                "matrix argument", y,
                "matrix is negative definite");
      }

      double val = ldlt.vectorD().array().log().sum();

      check_finite("log_determinant_spd",
                   "log determininant of the matrix argument", val);

      vari** operands = ChainableStack::memalloc_
        .alloc_array<vari*>(m.size());
      for (int i = 0; i < m.size(); ++i)
        operands[i] = m(i).vi_;

      double* gradients = ChainableStack::memalloc_
        .alloc_array<double>(m.size());
      for (int i = 0; i < m.size(); ++i)
        gradients[i] = m_d(i);

      return var(new precomputed_gradients_vari(val, m.size(),
                                                operands, gradients));
    }

  }

}
#endif
<|endoftext|>