<commit_before>#include "recent_file_cache.h"

#include <cerrno>
#include <chrono>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <memory>
#include <queue>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <unordered_map>
#include <utility>

#include "../../helper/common.h"
#include "../../log.h"

using std::chrono::minutes;
using std::chrono::steady_clock;
using std::chrono::time_point;
using std::endl;
using std::move;
using std::ostream;
using std::ostringstream;
using std::queue;
using std::shared_ptr;
using std::static_pointer_cast;
using std::string;

// If the cache contains more than this many entries, any entries older than CACHE_AGEOFF will be purged.
static const size_t CACHE_WATERMARK = 4096;

// Entries older than this duration will be purged once the cache grows beyond CACHE_WATERMARK entries.
static const minutes CACHE_AGEOFF = minutes(5);

shared_ptr<StatResult> StatResult::at(string &&path, bool file_hint, bool directory_hint)
{
  struct stat path_stat
  {};

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

    // 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(" << path << ") failed: " << strerror(stat_errno) << "." << endl;
    }

    EntryKind guessed_kind = KIND_UNKNOWN;
    if (file_hint && !directory_hint) guessed_kind = KIND_FILE;
    if (!file_hint && directory_hint) guessed_kind = KIND_DIRECTORY;

    return shared_ptr<StatResult>(new AbsentEntry(move(path), guessed_kind));
  }

  // Derive the entry kind from the lstat() results.
  EntryKind entry_kind = KIND_UNKNOWN;
  if ((path_stat.st_mode & S_IFREG) != 0) {
    entry_kind = KIND_FILE;
  }
  if ((path_stat.st_mode & S_IFDIR) != 0) {
    entry_kind = KIND_DIRECTORY;
  }

  return shared_ptr<StatResult>(new PresentEntry(move(path), entry_kind, path_stat.st_ino, path_stat.st_size));
}

bool StatResult::has_changed_from(const StatResult &other) const
{
  return entry_kind != other.entry_kind || path != other.path;
}

bool StatResult::could_be_rename_of(const StatResult &other) const
{
  return !kinds_are_different(entry_kind, other.entry_kind);
}

const string &StatResult::get_path() const
{
  return path;
}

EntryKind StatResult::get_entry_kind() const
{
  return entry_kind;
}

ostream &operator<<(ostream &out, const StatResult &result)
{
  out << result.to_string(true);
  return out;
}

PresentEntry::PresentEntry(std::string &&path, EntryKind entry_kind, ino_t inode, off_t size) :
  StatResult(move(path), entry_kind),
  inode{inode},
  size{size},
  last_seen{steady_clock::now()}
{
  //
}

bool PresentEntry::is_present() const
{
  return true;
}

bool PresentEntry::has_changed_from(const StatResult &other) const
{
  if (StatResult::has_changed_from(other)) return true;
  if (other.is_absent()) return true;

  const auto &casted = static_cast<const PresentEntry &>(other);  // NOLINT
  return inode != casted.get_inode() || get_path() != casted.get_path();
}

bool PresentEntry::could_be_rename_of(const StatResult &other) const
{
  if (!StatResult::could_be_rename_of(other)) return false;
  if (other.is_absent()) return false;

  const auto &casted = static_cast<const PresentEntry &>(other);  // NOLINT
  return inode == casted.get_inode();
}

ino_t PresentEntry::get_inode() const
{
  return inode;
}

off_t PresentEntry::get_size() const
{
  return size;
}

const time_point<steady_clock> &PresentEntry::get_last_seen() const
{
  return last_seen;
}

string PresentEntry::to_string(bool verbose) const
{
  ostringstream result;

  result << "[present " << get_entry_kind();
  if (verbose) result << " (" << get_path() << ")";
  result << " inode=" << inode << " size=" << size << "]";

  return result.str();
}

bool AbsentEntry::is_present() const
{
  return false;
}

bool AbsentEntry::has_changed_from(const StatResult &other) const
{
  if (StatResult::has_changed_from(other)) return true;
  if (other.is_present()) return true;

  return false;
}

bool AbsentEntry::could_be_rename_of(const StatResult &other) const
{
  if (!StatResult::could_be_rename_of(other)) return false;
  if (other.is_present()) return false;

  return true;
}

string AbsentEntry::to_string(bool verbose) const
{
  ostringstream result;

  result << "[absent " << get_entry_kind();
  if (verbose) result << " (" << get_path() << ")";
  result << "]";

  return result.str();
}

shared_ptr<StatResult> RecentFileCache::current_at_path(const string &path, bool file_hint, bool directory_hint)
{
  auto maybe_pending = pending.find(path);
  if (maybe_pending != pending.end()) {
    return maybe_pending->second;
  }

  shared_ptr<StatResult> stat_result = StatResult::at(string(path), file_hint, directory_hint);
  if (stat_result->is_present()) {
    pending.emplace(path, static_pointer_cast<PresentEntry>(stat_result));
  }
  return stat_result;
}

shared_ptr<StatResult> RecentFileCache::former_at_path(const string &path, bool file_hint, bool directory_hint)
{
  auto maybe = by_path.find(path);
  if (maybe == by_path.end()) {
    EntryKind kind = KIND_UNKNOWN;
    if (file_hint && !directory_hint) kind = KIND_FILE;
    if (!file_hint && directory_hint) kind = KIND_DIRECTORY;

    return shared_ptr<StatResult>(new AbsentEntry(string(path), kind));
  }

  return maybe->second;
}

void RecentFileCache::evict(const string &path)
{
  auto maybe = by_path.find(path);
  if (maybe != by_path.end()) {
    shared_ptr<PresentEntry> existing = maybe->second;

    auto range = by_timestamp.equal_range(existing->get_last_seen());
    auto to_erase = by_timestamp.end();
    for (auto it = range.first; it != range.second; ++it) {
      if (it->second == existing) {
        to_erase = it;
      }
    }
    if (to_erase != by_timestamp.end()) {
      by_timestamp.erase(to_erase);
    }

    by_path.erase(maybe);
  }
}

void RecentFileCache::evict(const shared_ptr<PresentEntry> entry)
{
  auto maybe = by_path.find(entry->get_path());
  if (maybe != by_path.end() && maybe->second == entry) {
    evict(entry->get_path());
  }
}

void RecentFileCache::apply()
{
  for (auto &pair : pending) {
    shared_ptr<PresentEntry> &present = pair.second;

    // Clear an existing entry at the same path if one exists
    evict(present->get_path());

    // Add the new PresentEntry
    by_path.emplace(present->get_path(), present);
    by_timestamp.emplace(present->get_last_seen(), present);
  }
  pending.clear();
}

void RecentFileCache::prune()
{
  if (by_path.size() <= CACHE_WATERMARK) {
    return;
  }

  LOGGER << "Cache currently contains " << plural(by_path.size(), "entry", "entries") << ". Pruning triggered." << endl;

  time_point<steady_clock> oldest = steady_clock::now() - CACHE_AGEOFF;

  auto to_keep = by_timestamp.upper_bound(oldest);
  size_t prune_count = 0;
  for (auto it = by_timestamp.begin(); it != to_keep && it != by_timestamp.end(); ++it) {
    shared_ptr<PresentEntry> entry = it->second;
    by_path.erase(entry->get_path());

    prune_count++;
  }

  if (to_keep != by_timestamp.begin()) {
    by_timestamp.erase(by_timestamp.begin(), to_keep);
  }

  LOGGER << "Pruned " << plural(prune_count, "entry", "entries") << ". " << plural(by_path.size(), "entry", "entries")
         << " remain." << endl;
}

void RecentFileCache::prepopulate(const string &root, size_t max)
{
  size_t count = 0;
  size_t entries = 0;
  queue<string> next_roots;
  next_roots.push(root);

  while (count < max && !next_roots.empty()) {
    string current_root(next_roots.front());
    next_roots.pop();

    DIR *dir = opendir(current_root.c_str());
    if (dir == nullptr) {
      errno_t opendir_errno = errno;
      LOGGER << "Unable to open directory " << root << ": " << strerror(opendir_errno) << "." << endl;
      LOGGER << "Incompletely pre-populated cache with " << entries << " entries." << endl;
      return;
    }

    errno = 0;
    dirent *entry = readdir(dir);
    while (entry != nullptr) {
      string entry_name(entry->d_name, entry->d_namlen);

      if (entry_name != "." && entry_name != "..") {
        string entry_path(path_join(current_root, entry_name));

        bool file_hint = (entry->d_type & DT_REG) == DT_REG;
        bool dir_hint = (entry->d_type & DT_DIR) == DT_DIR;

        shared_ptr<StatResult> r = current_at_path(entry_path, file_hint, dir_hint);
        if (r->is_present()) {
          entries++;
          if (r->get_entry_kind() == KIND_DIRECTORY) next_roots.push(entry_path);
        }

        count++;
        if (count >= max) {
          LOGGER << "Incompletely pre-populated cache with " << entries << " entries." << endl;
          return;
        }
      }

      errno = 0;
      entry = readdir(dir);
    }
    errno_t readdir_errno = errno;
    if (readdir_errno != 0) {
      LOGGER << "Unable to read directory entry within " << root << ": " << strerror(readdir_errno) << "." << endl;
    }

    if (closedir(dir) != 0) {
      errno_t closedir_errno = errno;
      LOGGER << "Unable to close directory " << root << ": " << strerror(closedir_errno) << "." << endl;
    }
  }
  apply();

  LOGGER << "Pre-populated cache with " << entries << " entries." << endl;
}
<commit_msg>Consider inode and entry kind in could_be_rename_of()<commit_after>#include "recent_file_cache.h"

#include <cerrno>
#include <chrono>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <memory>
#include <queue>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <unordered_map>
#include <utility>

#include "../../helper/common.h"
#include "../../log.h"

using std::chrono::minutes;
using std::chrono::steady_clock;
using std::chrono::time_point;
using std::endl;
using std::move;
using std::ostream;
using std::ostringstream;
using std::queue;
using std::shared_ptr;
using std::static_pointer_cast;
using std::string;

// If the cache contains more than this many entries, any entries older than CACHE_AGEOFF will be purged.
static const size_t CACHE_WATERMARK = 4096;

// Entries older than this duration will be purged once the cache grows beyond CACHE_WATERMARK entries.
static const minutes CACHE_AGEOFF = minutes(5);

shared_ptr<StatResult> StatResult::at(string &&path, bool file_hint, bool directory_hint)
{
  struct stat path_stat
  {};

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

    // 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(" << path << ") failed: " << strerror(stat_errno) << "." << endl;
    }

    EntryKind guessed_kind = KIND_UNKNOWN;
    if (file_hint && !directory_hint) guessed_kind = KIND_FILE;
    if (!file_hint && directory_hint) guessed_kind = KIND_DIRECTORY;

    return shared_ptr<StatResult>(new AbsentEntry(move(path), guessed_kind));
  }

  // Derive the entry kind from the lstat() results.
  EntryKind entry_kind = KIND_UNKNOWN;
  if ((path_stat.st_mode & S_IFREG) != 0) {
    entry_kind = KIND_FILE;
  }
  if ((path_stat.st_mode & S_IFDIR) != 0) {
    entry_kind = KIND_DIRECTORY;
  }

  return shared_ptr<StatResult>(new PresentEntry(move(path), entry_kind, path_stat.st_ino, path_stat.st_size));
}

bool StatResult::has_changed_from(const StatResult &other) const
{
  return entry_kind != other.entry_kind || path != other.path;
}

bool StatResult::could_be_rename_of(const StatResult &other) const
{
  return !kinds_are_different(entry_kind, other.entry_kind);
}

const string &StatResult::get_path() const
{
  return path;
}

EntryKind StatResult::get_entry_kind() const
{
  return entry_kind;
}

ostream &operator<<(ostream &out, const StatResult &result)
{
  out << result.to_string(true);
  return out;
}

PresentEntry::PresentEntry(std::string &&path, EntryKind entry_kind, ino_t inode, off_t size) :
  StatResult(move(path), entry_kind),
  inode{inode},
  size{size},
  last_seen{steady_clock::now()}
{
  //
}

bool PresentEntry::is_present() const
{
  return true;
}

bool PresentEntry::has_changed_from(const StatResult &other) const
{
  if (StatResult::has_changed_from(other)) return true;
  if (other.is_absent()) return true;

  const auto &casted = static_cast<const PresentEntry &>(other);  // NOLINT
  return inode != casted.get_inode() || get_path() != casted.get_path();
}

bool PresentEntry::could_be_rename_of(const StatResult &other) const
{
  if (!StatResult::could_be_rename_of(other)) return false;
  if (other.is_absent()) return false;

  const auto &casted = static_cast<const PresentEntry &>(other);  // NOLINT
  return inode == casted.get_inode() && !kinds_are_different(get_entry_kind(), casted.get_entry_kind());
}

ino_t PresentEntry::get_inode() const
{
  return inode;
}

off_t PresentEntry::get_size() const
{
  return size;
}

const time_point<steady_clock> &PresentEntry::get_last_seen() const
{
  return last_seen;
}

string PresentEntry::to_string(bool verbose) const
{
  ostringstream result;

  result << "[present " << get_entry_kind();
  if (verbose) result << " (" << get_path() << ")";
  result << " inode=" << inode << " size=" << size << "]";

  return result.str();
}

bool AbsentEntry::is_present() const
{
  return false;
}

bool AbsentEntry::has_changed_from(const StatResult &other) const
{
  if (StatResult::has_changed_from(other)) return true;
  if (other.is_present()) return true;

  return false;
}

bool AbsentEntry::could_be_rename_of(const StatResult &other) const
{
  if (!StatResult::could_be_rename_of(other)) return false;
  if (other.is_present()) return false;

  return true;
}

string AbsentEntry::to_string(bool verbose) const
{
  ostringstream result;

  result << "[absent " << get_entry_kind();
  if (verbose) result << " (" << get_path() << ")";
  result << "]";

  return result.str();
}

shared_ptr<StatResult> RecentFileCache::current_at_path(const string &path, bool file_hint, bool directory_hint)
{
  auto maybe_pending = pending.find(path);
  if (maybe_pending != pending.end()) {
    return maybe_pending->second;
  }

  shared_ptr<StatResult> stat_result = StatResult::at(string(path), file_hint, directory_hint);
  if (stat_result->is_present()) {
    pending.emplace(path, static_pointer_cast<PresentEntry>(stat_result));
  }
  return stat_result;
}

shared_ptr<StatResult> RecentFileCache::former_at_path(const string &path, bool file_hint, bool directory_hint)
{
  auto maybe = by_path.find(path);
  if (maybe == by_path.end()) {
    EntryKind kind = KIND_UNKNOWN;
    if (file_hint && !directory_hint) kind = KIND_FILE;
    if (!file_hint && directory_hint) kind = KIND_DIRECTORY;

    return shared_ptr<StatResult>(new AbsentEntry(string(path), kind));
  }

  return maybe->second;
}

void RecentFileCache::evict(const string &path)
{
  auto maybe = by_path.find(path);
  if (maybe != by_path.end()) {
    shared_ptr<PresentEntry> existing = maybe->second;

    auto range = by_timestamp.equal_range(existing->get_last_seen());
    auto to_erase = by_timestamp.end();
    for (auto it = range.first; it != range.second; ++it) {
      if (it->second == existing) {
        to_erase = it;
      }
    }
    if (to_erase != by_timestamp.end()) {
      by_timestamp.erase(to_erase);
    }

    by_path.erase(maybe);
  }
}

void RecentFileCache::evict(const shared_ptr<PresentEntry> entry)
{
  auto maybe = by_path.find(entry->get_path());
  if (maybe != by_path.end() && maybe->second == entry) {
    evict(entry->get_path());
  }
}

void RecentFileCache::apply()
{
  for (auto &pair : pending) {
    shared_ptr<PresentEntry> &present = pair.second;

    // Clear an existing entry at the same path if one exists
    evict(present->get_path());

    // Add the new PresentEntry
    by_path.emplace(present->get_path(), present);
    by_timestamp.emplace(present->get_last_seen(), present);
  }
  pending.clear();
}

void RecentFileCache::prune()
{
  if (by_path.size() <= CACHE_WATERMARK) {
    return;
  }

  LOGGER << "Cache currently contains " << plural(by_path.size(), "entry", "entries") << ". Pruning triggered." << endl;

  time_point<steady_clock> oldest = steady_clock::now() - CACHE_AGEOFF;

  auto to_keep = by_timestamp.upper_bound(oldest);
  size_t prune_count = 0;
  for (auto it = by_timestamp.begin(); it != to_keep && it != by_timestamp.end(); ++it) {
    shared_ptr<PresentEntry> entry = it->second;
    by_path.erase(entry->get_path());

    prune_count++;
  }

  if (to_keep != by_timestamp.begin()) {
    by_timestamp.erase(by_timestamp.begin(), to_keep);
  }

  LOGGER << "Pruned " << plural(prune_count, "entry", "entries") << ". " << plural(by_path.size(), "entry", "entries")
         << " remain." << endl;
}

void RecentFileCache::prepopulate(const string &root, size_t max)
{
  size_t count = 0;
  size_t entries = 0;
  queue<string> next_roots;
  next_roots.push(root);

  while (count < max && !next_roots.empty()) {
    string current_root(next_roots.front());
    next_roots.pop();

    DIR *dir = opendir(current_root.c_str());
    if (dir == nullptr) {
      errno_t opendir_errno = errno;
      LOGGER << "Unable to open directory " << root << ": " << strerror(opendir_errno) << "." << endl;
      LOGGER << "Incompletely pre-populated cache with " << entries << " entries." << endl;
      return;
    }

    errno = 0;
    dirent *entry = readdir(dir);
    while (entry != nullptr) {
      string entry_name(entry->d_name, entry->d_namlen);

      if (entry_name != "." && entry_name != "..") {
        string entry_path(path_join(current_root, entry_name));

        bool file_hint = (entry->d_type & DT_REG) == DT_REG;
        bool dir_hint = (entry->d_type & DT_DIR) == DT_DIR;

        shared_ptr<StatResult> r = current_at_path(entry_path, file_hint, dir_hint);
        if (r->is_present()) {
          entries++;
          if (r->get_entry_kind() == KIND_DIRECTORY) next_roots.push(entry_path);
        }

        count++;
        if (count >= max) {
          LOGGER << "Incompletely pre-populated cache with " << entries << " entries." << endl;
          return;
        }
      }

      errno = 0;
      entry = readdir(dir);
    }
    errno_t readdir_errno = errno;
    if (readdir_errno != 0) {
      LOGGER << "Unable to read directory entry within " << root << ": " << strerror(readdir_errno) << "." << endl;
    }

    if (closedir(dir) != 0) {
      errno_t closedir_errno = errno;
      LOGGER << "Unable to close directory " << root << ": " << strerror(closedir_errno) << "." << endl;
    }
  }
  apply();

  LOGGER << "Pre-populated cache with " << entries << " entries." << endl;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
 * License: https://github.com/taylor001/crown/blob/master/LICENSE
 */

#include "gui.h"
#include "lua_environment.h"
#include "lua_stack.h"
#include "vector3.h"
#include "quaternion.h"
#include "color4.h"
#include "device.h"
#include "resource_manager.h"
#include "font_resource.h"

namespace crown
{

static int gui_resolution(lua_State* L)
{
	LuaStack stack(L);
	const Vector2 resolution = stack.get_gui(1)->resolution();
	stack.push_int32((uint32_t)resolution.x);
	stack.push_int32((uint32_t)resolution.y);
	return 2;
}

static int gui_move(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->move(stack.get_vector2(2));
	return 0;
}

static int gui_screen_to_gui(lua_State* L)
{
	LuaStack stack(L);
	stack.push_vector2(stack.get_gui(1)->screen_to_gui(stack.get_vector2(2)));
	return 1;
}

static int gui_draw_rectangle(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_rectangle(stack.get_vector3(2), stack.get_vector2(3),
		stack.get_color4(4));
	return 0;
}

static int gui_draw_image(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_image(stack.get_string(2), stack.get_vector3(3),
		stack.get_vector2(4), stack.get_color4(5));
	return 0;
}

static int gui_draw_image_uv(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_image_uv(stack.get_string(2), stack.get_vector3(3),
		stack.get_vector2(4), stack.get_vector2(5), stack.get_vector2(6), stack.get_color4(7));
	return 0;
}

static int gui_draw_text(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_text(stack.get_string(2), stack.get_string(3), stack.get_int(4),
		stack.get_vector3(5), stack.get_color4(6));
	return 0;
}

void load_gui(LuaEnvironment& env)
{
	env.load_module_function("Gui", "resolution",     gui_resolution);
	env.load_module_function("Gui", "move",           gui_move);
	env.load_module_function("Gui", "screen_to_gui",  gui_screen_to_gui);
	env.load_module_function("Gui", "draw_rectangle", gui_draw_rectangle);
	env.load_module_function("Gui", "draw_image",     gui_draw_image);
	env.load_module_function("Gui", "draw_image_uv",  gui_draw_image_uv);
	env.load_module_function("Gui", "draw_text",      gui_draw_text);
}

} // namespace crown
<commit_msg>Cleanup<commit_after>/*
 * Copyright (c) 2012-2015 Daniele Bartolini and individual contributors.
 * License: https://github.com/taylor001/crown/blob/master/LICENSE
 */

#include "gui.h"
#include "lua_environment.h"
#include "lua_stack.h"
#include "vector3.h"
#include "quaternion.h"
#include "color4.h"
#include "resource_manager.h"
#include "font_resource.h"

namespace crown
{

static int gui_resolution(lua_State* L)
{
	LuaStack stack(L);
	const Vector2 resolution = stack.get_gui(1)->resolution();
	stack.push_int32((uint32_t)resolution.x);
	stack.push_int32((uint32_t)resolution.y);
	return 2;
}

static int gui_move(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->move(stack.get_vector2(2));
	return 0;
}

static int gui_screen_to_gui(lua_State* L)
{
	LuaStack stack(L);
	stack.push_vector2(stack.get_gui(1)->screen_to_gui(stack.get_vector2(2)));
	return 1;
}

static int gui_draw_rectangle(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_rectangle(stack.get_vector3(2), stack.get_vector2(3),
		stack.get_color4(4));
	return 0;
}

static int gui_draw_image(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_image(stack.get_string(2), stack.get_vector3(3),
		stack.get_vector2(4), stack.get_color4(5));
	return 0;
}

static int gui_draw_image_uv(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_image_uv(stack.get_string(2), stack.get_vector3(3),
		stack.get_vector2(4), stack.get_vector2(5), stack.get_vector2(6), stack.get_color4(7));
	return 0;
}

static int gui_draw_text(lua_State* L)
{
	LuaStack stack(L);
	stack.get_gui(1)->draw_text(stack.get_string(2), stack.get_string(3), stack.get_int(4),
		stack.get_vector3(5), stack.get_color4(6));
	return 0;
}

void load_gui(LuaEnvironment& env)
{
	env.load_module_function("Gui", "resolution",     gui_resolution);
	env.load_module_function("Gui", "move",           gui_move);
	env.load_module_function("Gui", "screen_to_gui",  gui_screen_to_gui);
	env.load_module_function("Gui", "draw_rectangle", gui_draw_rectangle);
	env.load_module_function("Gui", "draw_image",     gui_draw_image);
	env.load_module_function("Gui", "draw_image_uv",  gui_draw_image_uv);
	env.load_module_function("Gui", "draw_text",      gui_draw_text);
}

} // namespace crown
<|endoftext|>


<commit_before>/*!
@file

@copyright Edouard Alligand and Joel Falcou 2015-2017
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BRIGAND_ALGORITHMS_DETAIL_NON_NULL_HPP
#define BOOST_BRIGAND_ALGORITHMS_DETAIL_NON_NULL_HPP

#include <brigand/types/bool.hpp>
#include <brigand/types/args.hpp>

namespace brigand
{
namespace detail
{
    // Default find-like predicate

    template <typename Args>
  struct non_null_impl : bool_<Args::value != 0>{};
    using non_null = non_null_impl<_1>;
}
}
#endif
<commit_msg>Delete non_null.hpp<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __INTMATH_HH__
#define __INTMATH_HH__

#include <assert.h>

#include "sim/host.hh"

// Returns the prime number one less than n.
int PrevPrime(int n);

// Determine if a number is prime
template <class T>
inline bool
IsPrime(T n)
{
    T i;

    if (n == 2 || n == 3)
        return true;

    // Don't try every odd number to prove if it is a prime.
    // Toggle between every 2nd and 4th number.
    // (This is because every 6th odd number is divisible by 3.)
    for (i = 5; i*i <= n; i += 6) {
        if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
            return false;
        }
    }

    return true;
}

template <class T>
inline T
LeastSigBit(T n)
{
    return n & ~(n - 1);
}

template <class T>
inline bool
IsPowerOf2(T n)
{
    return n != 0 && LeastSigBit(n) == n;
}

inline int
FloorLog2(uint32_t x)
{
    assert(x > 0);

    int y = 0;

    if (x & 0xffff0000) { y += 16; x >>= 16; }
    if (x & 0x0000ff00) { y +=  8; x >>=  8; }
    if (x & 0x000000f0) { y +=  4; x >>=  4; }
    if (x & 0x0000000c) { y +=  2; x >>=  2; }
    if (x & 0x00000002) { y +=  1; }

    return y;
}

inline int
FloorLog2(uint64_t x)
{
    assert(x > 0);

    int y = 0;

    if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
    if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
    if (x & ULL(0x000000000000ff00)) { y +=  8; x >>=  8; }
    if (x & ULL(0x00000000000000f0)) { y +=  4; x >>=  4; }
    if (x & ULL(0x000000000000000c)) { y +=  2; x >>=  2; }
    if (x & ULL(0x0000000000000002)) { y +=  1; }

    return y;
}

inline int
FloorLog2(int32_t x)
{
    assert(x > 0);
    return FloorLog2(x);
}

inline int
FloorLog2(int64_t x)
{
    assert(x > 0);
    return FloorLog2(x);
}

template <class T>
inline int
CeilLog2(T n)
{
    if (n == 1)
        return 0;

    return FloorLog2(n - (T)1) + 1;
}

template <class T>
inline T
FloorPow2(T n)
{
    return (T)1 << FloorLog2(n);
}

template <class T>
inline T
CeilPow2(T n)
{
    return (T)1 << CeilLog2(n);
}

template <class T>
inline T
DivCeil(T a, T b)
{
    return (a + b - 1) / b;
}

template <class T>
inline T
RoundUp(T val, T align)
{
    T mask = align - 1;
    return (val + mask) & ~mask;
}

template <class T>
inline T
RoundDown(T val, T align)
{
    T mask = align - 1;
    return val & ~mask;
}

inline bool
IsHex(char c)
{
    return c >= '0' && c <= '9' ||
        c >= 'A' && c <= 'F' ||
        c >= 'a' && c <= 'f';
}

inline bool
IsOct(char c)
{
    return c >= '0' && c <= '7';
}

inline bool
IsDec(char c)
{
    return c >= '0' && c <= '9';
}

inline int
Hex2Int(char c)
{
  if (c >= '0' && c <= '9')
    return (c - '0');

  if (c >= 'A' && c <= 'F')
    return (c - 'A') + 10;

  if (c >= 'a' && c <= 'f')
    return (c - 'a') + 10;

  return 0;
}

#endif // __INTMATH_HH__
<commit_msg>Need to cast to avoid infinite recursion.<commit_after>/*
 * Copyright (c) 2003 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __INTMATH_HH__
#define __INTMATH_HH__

#include <assert.h>

#include "sim/host.hh"

// Returns the prime number one less than n.
int PrevPrime(int n);

// Determine if a number is prime
template <class T>
inline bool
IsPrime(T n)
{
    T i;

    if (n == 2 || n == 3)
        return true;

    // Don't try every odd number to prove if it is a prime.
    // Toggle between every 2nd and 4th number.
    // (This is because every 6th odd number is divisible by 3.)
    for (i = 5; i*i <= n; i += 6) {
        if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
            return false;
        }
    }

    return true;
}

template <class T>
inline T
LeastSigBit(T n)
{
    return n & ~(n - 1);
}

template <class T>
inline bool
IsPowerOf2(T n)
{
    return n != 0 && LeastSigBit(n) == n;
}

inline int
FloorLog2(uint32_t x)
{
    assert(x > 0);

    int y = 0;

    if (x & 0xffff0000) { y += 16; x >>= 16; }
    if (x & 0x0000ff00) { y +=  8; x >>=  8; }
    if (x & 0x000000f0) { y +=  4; x >>=  4; }
    if (x & 0x0000000c) { y +=  2; x >>=  2; }
    if (x & 0x00000002) { y +=  1; }

    return y;
}

inline int
FloorLog2(uint64_t x)
{
    assert(x > 0);

    int y = 0;

    if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
    if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
    if (x & ULL(0x000000000000ff00)) { y +=  8; x >>=  8; }
    if (x & ULL(0x00000000000000f0)) { y +=  4; x >>=  4; }
    if (x & ULL(0x000000000000000c)) { y +=  2; x >>=  2; }
    if (x & ULL(0x0000000000000002)) { y +=  1; }

    return y;
}

inline int
FloorLog2(int32_t x)
{
    assert(x > 0);
    return FloorLog2((uint32_t)x);
}

inline int
FloorLog2(int64_t x)
{
    assert(x > 0);
    return FloorLog2((uint64_t)x);
}

template <class T>
inline int
CeilLog2(T n)
{
    if (n == 1)
        return 0;

    return FloorLog2(n - (T)1) + 1;
}

template <class T>
inline T
FloorPow2(T n)
{
    return (T)1 << FloorLog2(n);
}

template <class T>
inline T
CeilPow2(T n)
{
    return (T)1 << CeilLog2(n);
}

template <class T>
inline T
DivCeil(T a, T b)
{
    return (a + b - 1) / b;
}

template <class T>
inline T
RoundUp(T val, T align)
{
    T mask = align - 1;
    return (val + mask) & ~mask;
}

template <class T>
inline T
RoundDown(T val, T align)
{
    T mask = align - 1;
    return val & ~mask;
}

inline bool
IsHex(char c)
{
    return c >= '0' && c <= '9' ||
        c >= 'A' && c <= 'F' ||
        c >= 'a' && c <= 'f';
}

inline bool
IsOct(char c)
{
    return c >= '0' && c <= '7';
}

inline bool
IsDec(char c)
{
    return c >= '0' && c <= '9';
}

inline int
Hex2Int(char c)
{
  if (c >= '0' && c <= '9')
    return (c - '0');

  if (c >= 'A' && c <= 'F')
    return (c - 'A') + 10;

  if (c >= 'a' && c <= 'f')
    return (c - 'a') + 10;

  return 0;
}

#endif // __INTMATH_HH__
<|endoftext|>


<commit_before>#include "LikelihoodProfiler.h"

// from STL
#include <set>

// from ROOT
#include "TCanvas.h"
#include "TGraph.h"
#include "TH2D.h"
#include "TAxis.h"
#include "TStyle.h"

// from RooFit
#include "RooFitResult.h"

// from DooCore
#include <doocore/io/MsgStream.h>
#include <doocore/io/Progress.h>
#include <doocore/lutils/lutils.h>

// from DooFit
#include "doofit/fitter/AbsFitter.h"
#include "doofit/toy/ToyStudyStd/ToyStudyStd.h"

doofit::plotting::profiles::LikelihoodProfiler::LikelihoodProfiler()
: num_samples_(30)
{}

std::vector<double> doofit::plotting::profiles::LikelihoodProfiler::SetSamplePoint(unsigned int step) {
  using namespace doocore::io;

  std::vector<double> sample_vals;
  int i(scan_vars_.size() - 1);

  //sdebug << "step = " << step << endmsg;

  for (auto var : scan_vars_) {
    int step_this = step/std::pow(num_samples_,i);
    step -= step_this*std::pow(num_samples_,i);
    --i;

    double val(start_vals_[var->GetName()] + 3*var->getError()*(-1.0 + 2.0/static_cast<double>(num_samples_)*step_this));
    var->setVal(val);
    var->setConstant(true);

    sample_vals.push_back(val);
    //sdebug << "  " << var->GetName() << " = " << step_this << " @ " << var->getVal() << endmsg;
  }

  return sample_vals;
}

void doofit::plotting::profiles::LikelihoodProfiler::Scan() {
  using namespace doocore::io;

  //RooRealVar* parameter_scan = scan_vars_.front();

  //num_samples_                   = 12;
  unsigned int num_dimensions    = scan_vars_.size();
  unsigned int num_total_samples = std::pow(num_samples_,num_dimensions);
  unsigned int step              = 0;

  // double value_start = parameter_scan->getVal();
  // double value_scan  = value_start - 5.0*parameter_scan->getError();

  for (auto var : scan_vars_) {
    start_vals_[var->GetName()] = var->getVal();
  }

  Progress p("Sampling likelihood", num_total_samples);
  while (step < num_total_samples) {
    //parameter_scan->setVal(value_scan);
    //parameter_scan->setConstant(true);

    //sinfo << "PROFILE: " << value_scan << endmsg;

    std::vector<double> sample_vals(SetSamplePoint(step));

    fitter_->set_shutup(true);
    fitter_->Fit();

    fit_results_.push_back(fitter_->fit_result());

    //sinfo << fitter_->NegativeLogLikelihood() << endmsg;
    //value_scan += 1*parameter_scan->getError();
    ++step;
    ++p;
  }
  p.Finish();
}

void doofit::plotting::profiles::LikelihoodProfiler::ReadFitResults(doofit::toy::ToyStudyStd& toy_study) {
  using namespace doofit::toy;

  FitResultContainer fit_result_container(toy_study.GetFitResult());
  const RooFitResult* fit_result(std::get<0>(fit_result_container));

  while (fit_result != nullptr) {
    fit_results_.push_back(fit_result);

    fit_result_container = toy_study.GetFitResult();
    fit_result = std::get<0>(fit_result_container);
  }
}

bool doofit::plotting::profiles::LikelihoodProfiler::FitResultOkay(const RooFitResult& fit_result) const {
  using namespace doocore::io;
  if (fit_result.covQual() < 2) {
    return false;
  } else if (fit_result.statusCodeHistory(0) < 0) {
    return false;
  } else {
    return true;
  }
}

void doofit::plotting::profiles::LikelihoodProfiler::PlotHandler(const std::string& plot_path) {
  using namespace doocore::io;

  std::map<std::string, std::vector<double>> val_scan;
  std::vector<double> val_nll;

  if (val_scan.size() == 1) {
    doocore::lutils::setStyle();
  } else if (val_scan.size() == 2) {
    doocore::lutils::setStyle("2d");
    gStyle->SetNumberContours(999);
    gStyle->SetPadRightMargin(0.16);
    gStyle->SetTitleOffset(0.75, "z");
  }

  for (auto var : scan_vars_) {
    RooRealVar* var_fixed = dynamic_cast<RooRealVar*>(fit_results_.front()->constPars().find(var->GetName()));
    scan_vars_titles_.push_back(var_fixed->GetTitle());
  }

  double min_nll(0.0);
  for (auto result : fit_results_) {
    if (FitResultOkay(*result)) {
      for (auto var : scan_vars_) {
        RooRealVar* var_fixed = dynamic_cast<RooRealVar*>(result->constPars().find(var->GetName()));

        if (var_fixed == nullptr) {
          serr << "Error in LikelihoodProfiler::PlotHandler(): Cannot find fixed parameter "
               << var->GetName() << " in fit result!" << endmsg;
          throw;
        }

        val_scan[var->GetName()].push_back(var_fixed->getVal());
      }

      if (min_nll == 0.0 || min_nll > result->minNll()) {
        min_nll = result->minNll();
      }
      val_nll.push_back(result->minNll());
    }
  }

  for (auto &nll : val_nll) {
    if (nll != 0.0) {
      nll -= min_nll;
    }
  }

  TCanvas c("c", "c", 800, 600);

  if (val_scan.size() == 1) {
    const std::vector<double>& val_x = val_scan.begin()->second;

    TGraph graph(val_nll.size(), &val_x[0], &val_nll[0]);
    graph.Draw("AP");
    graph.GetXaxis()->SetTitle(scan_vars_titles_.at(0).c_str());
    graph.GetYaxis()->SetTitle("#DeltaLL");
    //c.SaveAs("profile.pdf");
    doocore::lutils::printPlot(&c, "profile", plot_path);
  } else if (val_scan.size() == 2) {
    const std::vector<double>& val_x = val_scan.begin()->second;
    const std::vector<double>& val_y = val_scan.rbegin()->second;

    auto minmax_x = std::minmax_element(val_x.begin(), val_x.end());
    auto minmax_y = std::minmax_element(val_y.begin(), val_y.end());

    std::set<double> distinct_x, distinct_y;
    for (auto x : val_x) {
      distinct_x.insert(x);
    }
    for (auto y : val_y) {
      distinct_y.insert(y);
    }

    double min_nll(0.0), max_nll(0.0);
    for (auto nll : val_nll) {
      if (nll != 0 && (min_nll == 0.0 || nll < min_nll)) {
        min_nll = nll;
      }
      if (nll != 0 && (max_nll == 0.0 || nll > max_nll)) {
        max_nll = nll;
      }
    }

    double min_x = *minmax_x.first  - (*minmax_x.second-*minmax_x.first)/(distinct_x.size()-1)*0.5;
    double max_x = *minmax_x.second + (*minmax_x.second-*minmax_x.first)/(distinct_x.size()-1)*0.5;
    double min_y = *minmax_y.first  - (*minmax_y.second-*minmax_y.first)/(distinct_y.size()-1)*0.5;
    double max_y = *minmax_y.second + (*minmax_y.second-*minmax_y.first)/(distinct_y.size()-1)*0.5;

    TH2D histogram("histogram", "histogram", distinct_x.size(), min_x, max_x, distinct_y.size(), min_y, max_y);

    // sdebug << "histogram x: " << *minmax_x.first << " - " <<  *minmax_x.second << endmsg;
    // sdebug << "histogram y: " << *minmax_y.first << " - " <<  *minmax_y.second << endmsg;

    for (int i=0; i<val_nll.size(); ++i) {
      // sdebug << val_x.at(i) << ", " << val_y.at(i) << " - " << val_nll.at(i) << endmsg;
      // sdebug << "Bin: " << histogram.FindBin(val_x.at(i), val_y.at(i)) << endmsg;

      int nbin_x, nbin_y, nbin_z;
      histogram.GetBinXYZ(histogram.FindBin(val_x.at(i), val_y.at(i)), nbin_x, nbin_y, nbin_z);

      // sdebug << "Bin center x: " << histogram.GetXaxis()->GetBinCenter(nbin_x) << endmsg;
      // sdebug << "Bin center y: " << histogram.GetYaxis()->GetBinCenter(nbin_y) << endmsg;

      histogram.SetBinContent(histogram.FindBin(val_x.at(i), val_y.at(i)), val_nll.at(i));
    }

    histogram.Draw("COLZ");
    histogram.GetZaxis()->SetRangeUser(min_nll, max_nll);
    histogram.SetXTitle(scan_vars_titles_.at(0).c_str());
    histogram.SetYTitle(scan_vars_titles_.at(1).c_str());
    histogram.SetZTitle("#DeltaLL");

    //c.SaveAs("profile.pdf");
    doocore::lutils::printPlot(&c, "profile", plot_path);
  } else {
    serr << "Error in LikelihoodProfiler::PlotHandler(): Cannot (yet) plot 3D likelihood." << endmsg;
    throw;
  }

}

<commit_msg>LikelihoodProfiler: plotting cosmetics<commit_after>#include "LikelihoodProfiler.h"

// from STL
#include <set>

// from ROOT
#include "TCanvas.h"
#include "TGraph.h"
#include "TH2D.h"
#include "TAxis.h"
#include "TStyle.h"

// from RooFit
#include "RooFitResult.h"

// from DooCore
#include <doocore/io/MsgStream.h>
#include <doocore/io/Progress.h>
#include <doocore/lutils/lutils.h>

// from DooFit
#include "doofit/fitter/AbsFitter.h"
#include "doofit/toy/ToyStudyStd/ToyStudyStd.h"

doofit::plotting::profiles::LikelihoodProfiler::LikelihoodProfiler()
: num_samples_(30)
{}

std::vector<double> doofit::plotting::profiles::LikelihoodProfiler::SetSamplePoint(unsigned int step) {
  using namespace doocore::io;

  std::vector<double> sample_vals;
  int i(scan_vars_.size() - 1);

  //sdebug << "step = " << step << endmsg;

  for (auto var : scan_vars_) {
    int step_this = step/std::pow(num_samples_,i);
    step -= step_this*std::pow(num_samples_,i);
    --i;

    double val(start_vals_[var->GetName()] + 3*var->getError()*(-1.0 + 2.0/static_cast<double>(num_samples_)*step_this));
    var->setVal(val);
    var->setConstant(true);

    sample_vals.push_back(val);
    //sdebug << "  " << var->GetName() << " = " << step_this << " @ " << var->getVal() << endmsg;
  }

  return sample_vals;
}

void doofit::plotting::profiles::LikelihoodProfiler::Scan() {
  using namespace doocore::io;

  //RooRealVar* parameter_scan = scan_vars_.front();

  //num_samples_                   = 12;
  unsigned int num_dimensions    = scan_vars_.size();
  unsigned int num_total_samples = std::pow(num_samples_,num_dimensions);
  unsigned int step              = 0;

  // double value_start = parameter_scan->getVal();
  // double value_scan  = value_start - 5.0*parameter_scan->getError();

  for (auto var : scan_vars_) {
    start_vals_[var->GetName()] = var->getVal();
  }

  Progress p("Sampling likelihood", num_total_samples);
  while (step < num_total_samples) {
    //parameter_scan->setVal(value_scan);
    //parameter_scan->setConstant(true);

    //sinfo << "PROFILE: " << value_scan << endmsg;

    std::vector<double> sample_vals(SetSamplePoint(step));

    fitter_->set_shutup(true);
    fitter_->Fit();

    fit_results_.push_back(fitter_->fit_result());

    //sinfo << fitter_->NegativeLogLikelihood() << endmsg;
    //value_scan += 1*parameter_scan->getError();
    ++step;
    ++p;
  }
  p.Finish();
}

void doofit::plotting::profiles::LikelihoodProfiler::ReadFitResults(doofit::toy::ToyStudyStd& toy_study) {
  using namespace doofit::toy;

  FitResultContainer fit_result_container(toy_study.GetFitResult());
  const RooFitResult* fit_result(std::get<0>(fit_result_container));

  while (fit_result != nullptr) {
    fit_results_.push_back(fit_result);

    fit_result_container = toy_study.GetFitResult();
    fit_result = std::get<0>(fit_result_container);
  }
}

bool doofit::plotting::profiles::LikelihoodProfiler::FitResultOkay(const RooFitResult& fit_result) const {
  using namespace doocore::io;
  if (fit_result.covQual() < 2) {
    return false;
  } else if (fit_result.statusCodeHistory(0) < 0) {
    return false;
  } else {
    return true;
  }
}

void doofit::plotting::profiles::LikelihoodProfiler::PlotHandler(const std::string& plot_path) {
  using namespace doocore::io;

  std::map<std::string, std::vector<double>> val_scan;
  std::vector<double> val_nll;

  if (val_scan.size() == 1) {
    doocore::lutils::setStyle();
  } else if (val_scan.size() == 2) {
    doocore::lutils::setStyle("2d");
    gStyle->SetNumberContours(999);
    gStyle->SetPadRightMargin(0.16);
    gStyle->SetTitleOffset(0.75, "z");
  }

  for (auto var : scan_vars_) {
    RooRealVar* var_fixed = dynamic_cast<RooRealVar*>(fit_results_.front()->constPars().find(var->GetName()));
    scan_vars_titles_.push_back(var_fixed->GetTitle());
  }

  double min_nll(0.0);
  for (auto result : fit_results_) {
    if (FitResultOkay(*result)) {
      for (auto var : scan_vars_) {
        RooRealVar* var_fixed = dynamic_cast<RooRealVar*>(result->constPars().find(var->GetName()));

        if (var_fixed == nullptr) {
          serr << "Error in LikelihoodProfiler::PlotHandler(): Cannot find fixed parameter "
               << var->GetName() << " in fit result!" << endmsg;
          throw;
        }

        val_scan[var->GetName()].push_back(var_fixed->getVal());
      }

      if (min_nll == 0.0 || min_nll > result->minNll()) {
        min_nll = result->minNll();
      }
      val_nll.push_back(result->minNll());
    }
  }

  for (auto &nll : val_nll) {
    if (nll != 0.0) {
      nll -= min_nll;
    }
  }

  TCanvas c("c", "c", 800, 600);

  if (val_scan.size() == 1) {
    const std::vector<double>& val_x = val_scan.begin()->second;

    TGraph graph(val_nll.size(), &val_x[0], &val_nll[0]);
    graph.Draw("AP");
    graph.GetXaxis()->SetTitle(scan_vars_titles_.at(0).c_str());
    graph.GetYaxis()->SetTitle("#DeltaLL");
    graph.SetMarkerStyle(1);
    graph.SetMarkerSize(10);

    //c.SaveAs("profile.pdf");
    doocore::lutils::printPlot(&c, "profile", plot_path);
  } else if (val_scan.size() == 2) {
    const std::vector<double>& val_x = val_scan.begin()->second;
    const std::vector<double>& val_y = val_scan.rbegin()->second;

    auto minmax_x = std::minmax_element(val_x.begin(), val_x.end());
    auto minmax_y = std::minmax_element(val_y.begin(), val_y.end());

    std::set<double> distinct_x, distinct_y;
    for (auto x : val_x) {
      distinct_x.insert(x);
    }
    for (auto y : val_y) {
      distinct_y.insert(y);
    }

    double min_nll(0.0), max_nll(0.0);
    for (auto nll : val_nll) {
      if (nll != 0 && (min_nll == 0.0 || nll < min_nll)) {
        min_nll = nll;
      }
      if (nll != 0 && (max_nll == 0.0 || nll > max_nll)) {
        max_nll = nll;
      }
    }

    double min_x = *minmax_x.first  - (*minmax_x.second-*minmax_x.first)/(distinct_x.size()-1)*0.5;
    double max_x = *minmax_x.second + (*minmax_x.second-*minmax_x.first)/(distinct_x.size()-1)*0.5;
    double min_y = *minmax_y.first  - (*minmax_y.second-*minmax_y.first)/(distinct_y.size()-1)*0.5;
    double max_y = *minmax_y.second + (*minmax_y.second-*minmax_y.first)/(distinct_y.size()-1)*0.5;

    TH2D histogram("histogram", "histogram", distinct_x.size(), min_x, max_x, distinct_y.size(), min_y, max_y);

    // sdebug << "histogram x: " << *minmax_x.first << " - " <<  *minmax_x.second << endmsg;
    // sdebug << "histogram y: " << *minmax_y.first << " - " <<  *minmax_y.second << endmsg;

    for (int i=0; i<val_nll.size(); ++i) {
      // sdebug << val_x.at(i) << ", " << val_y.at(i) << " - " << val_nll.at(i) << endmsg;
      // sdebug << "Bin: " << histogram.FindBin(val_x.at(i), val_y.at(i)) << endmsg;

      int nbin_x, nbin_y, nbin_z;
      histogram.GetBinXYZ(histogram.FindBin(val_x.at(i), val_y.at(i)), nbin_x, nbin_y, nbin_z);

      // sdebug << "Bin center x: " << histogram.GetXaxis()->GetBinCenter(nbin_x) << endmsg;
      // sdebug << "Bin center y: " << histogram.GetYaxis()->GetBinCenter(nbin_y) << endmsg;

      histogram.SetBinContent(histogram.FindBin(val_x.at(i), val_y.at(i)), val_nll.at(i));
    }

    histogram.Draw("COLZ");
    histogram.GetZaxis()->SetRangeUser(min_nll, max_nll);
    histogram.SetXTitle(scan_vars_titles_.at(0).c_str());
    histogram.SetYTitle(scan_vars_titles_.at(1).c_str());
    histogram.SetZTitle("#DeltaLL");

    //c.SaveAs("profile.pdf");
    doocore::lutils::printPlot(&c, "profile", plot_path);
  } else {
    serr << "Error in LikelihoodProfiler::PlotHandler(): Cannot (yet) plot 3D likelihood." << endmsg;
    throw;
  }

}

<|endoftext|>


<commit_before>///
/// @file  pi_lmo_parallel1.cpp
/// @brief Parallel implementation of the Lagarias-Miller-Odlyzko
///        prime counting algorithm using OpenMP. This implementation
///        is based on pi_lmo4(x).
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <tos_counters.hpp>
#include <utils.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// For each prime calculate its first multiple >= low.
template <typename T1, typename T2>
void init_next_multiples(T1& next, T2& primes, int64_t size, int64_t low)
{
  next.reserve(size);
  next.push_back(0);

  for (int64_t b = 1; b < size; b++)
  {
    int64_t prime = primes[b];
    int64_t next_multiple = ((low + prime - 1) / prime) * prime;
    next.push_back(next_multiple);
  }
}

template <typename T1, typename T2>
void cross_off(int64_t prime, int64_t low, int64_t high, int64_t& next_multiple, T1& sieve, T2& counters)
{
  int64_t segment_size = sieve.size();
  int64_t k = next_multiple + prime * (~next_multiple & 1);

  for (; k < high; k += prime * 2)
  {
    if (sieve[k - low])
    {
      sieve[k - low] = 0;
      cnt_update(counters, k - low, segment_size);
    }
  }
  next_multiple = k;
}

/// Compute the S2 contribution for the interval
/// [low_thread, low_thread + segments * segment_size[.
/// The missing special leaf contributions for the interval
/// [1, low_thread[ are later reconstructed and added in
/// the calling (parent) S2 function.
///
int64_t S2_thread(int64_t x,
                  int64_t y,
                  int64_t c,
                  int64_t pi_y,
                  int64_t segment_size,
                  int64_t segments_per_thread,
                  int64_t thread_num,
                  int64_t limit,
                  vector<int32_t>& pi,
                  vector<int32_t>& primes,
                  vector<int32_t>& lpf,
                  vector<int32_t>& mu,
                  vector<int64_t>& mu_sum,
                  vector<int64_t>& phi)
{
  int64_t low = 1 + segment_size * segments_per_thread * thread_num;
  limit = min(low + segment_size * segments_per_thread, limit);
  int64_t size = pi[min(isqrt(x / low), y)] + 1;
  int64_t S2_thread = 0;

  if (c >= size - 1)
    return 0;

  vector<char> sieve(segment_size);
  vector<int32_t> counters(segment_size);
  vector<int64_t> next;
  init_next_multiples(next, primes, size, low);
  phi.resize(size, 0);
  mu_sum.resize(size, 0);

  // Process the segments assigned to the current thread
  for (; low < limit; low += segment_size)
  {
    fill(sieve.begin(), sieve.end(), 1);

    // Current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t b = 1;

    // phi(y, b) nodes with b <= c do not contribute to S2, so we
    // simply sieve out the multiples of the first c primes
    for (; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime)
        sieve[k - low] = 0;
      next[b] = k;
    }

    // Initialize special tree data structure from sieve
    cnt_finit(sieve, counters, segment_size);

    // For c + 1 <= b < pi_sqrty
    // Find all special leaves: n = primes[b] * m
    // which satisfy:  mu[m] != 0 && primes[b] < lpf[m], low <= (x / n) < high
    for (; b < min(pi_y, size); b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);

      if (prime >= max_m)
        break;

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (mu[m] != 0 && prime < lpf[m])
        {
          int64_t n = prime * m;
          int64_t count = cnt_query(counters, (x / n) - low);
          int64_t phi_xn = phi[b] + count;
          S2_thread -= mu[m] * phi_xn;
          mu_sum[b] -= mu[m];
        }
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }
  }

  return S2_thread;
}

/// Calculate the contribution of the special leaves.
/// This is a parallel implementation without load balancing.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t pi_y,
           int64_t c,
           vector<int32_t>& primes,
           vector<int32_t>& lpf,
           vector<int32_t>& mu,
           int threads)
{
  int64_t limit = x / y + 1;
  threads = validate_threads(threads, limit);

  int64_t S2_total = 0;
  int64_t segment_size = next_power_of_2(isqrt(limit));
  int64_t segments = (limit + segment_size - 1) / segment_size;
  threads = in_between(1, threads, segments);
  int64_t segments_per_thread = (segments + threads - 1) / threads;

  vector<int32_t> pi = make_pi(y);
  aligned_vector<vector<int64_t> > phi(threads);
  aligned_vector<vector<int64_t> > mu_sum(threads);

  #pragma omp parallel for num_threads(threads) reduction(+: S2_total)
  for (int i = 0; i < threads; i++)
    S2_total += S2_thread(x, y, c, pi_y, segment_size, segments_per_thread,
        i, limit, pi, primes, lpf, mu, mu_sum[i], phi[i]);

  // Once all threads have finished reconstruct and add the
  // missing contribution of all special leaves. This must
  // be done in order as each thread (i) requires the sum of
  // the phi values from the previous threads.
  //
  for (int i = 1; i < threads; i++)
  {
    for (size_t j = 0; j < phi[i].size(); j++)
    {
      S2_total += phi[i - 1][j] * mu_sum[i][j];
      phi[i][j] += phi[i - 1][j];
    }
  }

  return S2_total;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3)) operations, O(x^(1/3) * log log x) space.
///
int64_t pi_lmo_parallel1(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  // alpha is a tuning factor
  double alpha = in_between(1, log(log((double) x)) * 0.6, iroot<6>(x));
  int64_t x13 = iroot<3>(x);
  int64_t y = (int64_t) (x13 * alpha);

  vector<int32_t> mu = make_moebius(y);
  vector<int32_t> lpf = make_least_prime_factor(y);
  vector<int32_t> primes;
  primes.push_back(0);
  primesieve::generate_primes(y, &primes);

  int64_t pi_y = primes.size() - 1;
  int64_t c = min<int64_t>(PhiTiny::MAX_A, pi_y);
  int64_t s1 = S1(x, y, c, primes, lpf , mu);
  int64_t s2 = S2(x, y, pi_y, c, primes, lpf , mu, threads);
  int64_t p2 = P2(x, y, threads);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<commit_msg>Refactoring<commit_after>///
/// @file  pi_lmo_parallel1.cpp
/// @brief Parallel implementation of the Lagarias-Miller-Odlyzko
///        prime counting algorithm using OpenMP. This implementation
///        is based on pi_lmo4(x).
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <tos_counters.hpp>
#include <utils.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

#ifdef _OPENMP
  #include <omp.h>
#endif

using namespace std;
using namespace primecount;

namespace {

/// For each prime calculate its first multiple >= low.
template <typename T1, typename T2>
void init_next_multiples(T1& next, T2& primes, int64_t size, int64_t low)
{
  next.reserve(size);
  next.push_back(0);

  for (int64_t b = 1; b < size; b++)
  {
    int64_t prime = primes[b];
    int64_t next_multiple = ((low + prime - 1) / prime) * prime;
    next.push_back(next_multiple);
  }
}

template <typename T1, typename T2>
void cross_off(int64_t prime, int64_t low, int64_t high, int64_t& next_multiple, T1& sieve, T2& counters)
{
  int64_t segment_size = sieve.size();
  int64_t k = next_multiple + prime * (~next_multiple & 1);

  for (; k < high; k += prime * 2)
  {
    if (sieve[k - low])
    {
      sieve[k - low] = 0;
      cnt_update(counters, k - low, segment_size);
    }
  }
  next_multiple = k;
}

/// Compute the S2 contribution for the interval
/// [low_thread, low_thread + segments * segment_size[.
/// The missing special leaf contributions for the interval
/// [1, low_thread[ are later reconstructed and added in
/// the calling (parent) S2 function.
///
int64_t S2_thread(int64_t x,
                  int64_t y,
                  int64_t c,
                  int64_t segment_size,
                  int64_t segments_per_thread,
                  int64_t thread_num,
                  int64_t limit,
                  vector<int32_t>& pi,
                  vector<int32_t>& primes,
                  vector<int32_t>& lpf,
                  vector<int32_t>& mu,
                  vector<int64_t>& mu_sum,
                  vector<int64_t>& phi)
{
  int64_t low = 1 + segment_size * segments_per_thread * thread_num;
  limit = min(low + segment_size * segments_per_thread, limit);
  int64_t size = pi[min(isqrt(x / low), y)] + 1;
  int64_t pi_y = pi[y];

  if (c >= size - 1)
    return 0;

  int64_t S2_thread = 0;
  vector<char> sieve(segment_size);
  vector<int32_t> counters(segment_size);
  vector<int64_t> next;
  init_next_multiples(next, primes, size, low);
  phi.resize(size, 0);
  mu_sum.resize(size, 0);

  // Process the segments assigned to the current thread
  for (; low < limit; low += segment_size)
  {
    fill(sieve.begin(), sieve.end(), 1);

    // Current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t b = 1;

    // phi(y, b) nodes with b <= c do not contribute to S2, so we
    // simply sieve out the multiples of the first c primes
    for (; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime)
        sieve[k - low] = 0;
      next[b] = k;
    }

    // Initialize special tree data structure from sieve
    cnt_finit(sieve, counters, segment_size);

    // For c + 1 <= b < pi_sqrty
    // Find all special leaves: n = primes[b] * m
    // which satisfy:  mu[m] != 0 && primes[b] < lpf[m], low <= (x / n) < high
    for (; b < min(pi_y, size); b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);

      if (prime >= max_m)
        break;

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (mu[m] != 0 && prime < lpf[m])
        {
          int64_t n = prime * m;
          int64_t count = cnt_query(counters, (x / n) - low);
          int64_t phi_xn = phi[b] + count;
          S2_thread -= mu[m] * phi_xn;
          mu_sum[b] -= mu[m];
        }
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }
  }

  return S2_thread;
}

/// Calculate the contribution of the special leaves.
/// This is a parallel implementation without load balancing.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t c,
           vector<int32_t>& primes,
           vector<int32_t>& lpf,
           vector<int32_t>& mu,
           int threads)
{
  int64_t limit = x / y + 1;
  threads = validate_threads(threads, limit);

  int64_t S2_total = 0;
  int64_t segment_size = next_power_of_2(isqrt(limit));
  int64_t segments = (limit + segment_size - 1) / segment_size;
  threads = in_between(1, threads, segments);
  int64_t segments_per_thread = (segments + threads - 1) / threads;

  vector<int32_t> pi = make_pi(y);
  aligned_vector<vector<int64_t> > phi(threads);
  aligned_vector<vector<int64_t> > mu_sum(threads);

  #pragma omp parallel for num_threads(threads) reduction(+: S2_total)
  for (int i = 0; i < threads; i++)
    S2_total += S2_thread(x, y, c, segment_size, segments_per_thread,
        i, limit, pi, primes, lpf, mu, mu_sum[i], phi[i]);

  // Once all threads have finished reconstruct and add the
  // missing contribution of all special leaves. This must
  // be done in order as each thread (i) requires the sum of
  // the phi values from the previous threads.
  //
  for (int i = 1; i < threads; i++)
  {
    for (size_t j = 0; j < phi[i].size(); j++)
    {
      S2_total += phi[i - 1][j] * mu_sum[i][j];
      phi[i][j] += phi[i - 1][j];
    }
  }

  return S2_total;
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Lagarias-Miller-Odlyzko algorithm.
/// Run time: O(x^(2/3)) operations, O(x^(1/3) * log log x) space.
///
int64_t pi_lmo_parallel1(int64_t x, int threads)
{
  if (x < 2)
    return 0;

  // alpha is a tuning factor
  double alpha = in_between(1, log(log((double) x)) * 0.6, iroot<6>(x));
  int64_t x13 = iroot<3>(x);
  int64_t y = (int64_t) (x13 * alpha);

  vector<int32_t> mu = make_moebius(y);
  vector<int32_t> lpf = make_least_prime_factor(y);
  vector<int32_t> primes;
  primes.push_back(0);
  primesieve::generate_primes(y, &primes);

  int64_t pi_y = primes.size() - 1;
  int64_t c = min<int64_t>(PhiTiny::MAX_A, pi_y);
  int64_t s1 = S1(x, y, c, primes, lpf , mu);
  int64_t s2 = S2(x, y, c, primes, lpf , mu, threads);
  int64_t p2 = P2(x, y, threads);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<|endoftext|>


<commit_before>
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoaddress.h"
#include "qgeoaddress_p.h"

#ifdef QGEOADDRESS_DEBUG
#include <QDebug>
#endif

QTM_BEGIN_NAMESPACE

QGeoAddressPrivate::QGeoAddressPrivate()
        : QSharedData()
{
}

QGeoAddressPrivate::QGeoAddressPrivate(const QGeoAddressPrivate &other)
        : QSharedData(other),
        sCountry(other.sCountry),
        sCountryCode(other.sCountryCode),
        sState(other.sState),
        sCounty(other.sCounty),
        sCity(other.sCity),
        sDistrict(other.sDistrict),
        sStreet(other.sStreet),
        sPostCode(other.sPostCode)
{
}

QGeoAddressPrivate::~QGeoAddressPrivate()
{
}

/*!
    \class QGeoAddress
    \brief The QGeoAddress class represents an address

    \inmodule QtLocation

    \ingroup location

    This class represents an address of a location.
*/

/*!
    Default constructor.
*/
QGeoAddress::QGeoAddress()
        : d(new QGeoAddressPrivate)
{
}

/*!
    Constructs a copy of \a other.
*/
QGeoAddress::QGeoAddress(const QGeoAddress &other)
        : d(other.d)
{
}

/*!
    Destroys this address.
*/
QGeoAddress::~QGeoAddress()
{
}

/*!
    Assigns the given \a address to this address and
    returns a reference to this address.
*/
QGeoAddress &QGeoAddress::operator=(const QGeoAddress & address)
{
    d = address.d;
    return *this;
}

/*!
    Returns true if this address is equal to \a other,
    otherwise returns false.
*/
bool QGeoAddress::operator==(const QGeoAddress &other) const
{
#ifdef QGEOADDRESS_DEBUG
    qDebug() << "country" << (d->sCountry == other.country());
    qDebug() << "countryCode" << (d->sCountryCode == other.countryCode());
    qDebug() << "state:" <<  (d->sState == other.state());
    qDebug() << "county:" << (d->sCounty == other.county());
    qDebug() << "city:" << (d->sCity == other.city());
    qDebug() << "district:" << (d->sDistrict == other.district());
    qDebug() << "street:" << (d->sStreet == other.street());
    qDebug() << "postcode:" << (d->sPostCode == other.postcode());
#endif

    return d->sCountry == other.country() &&
           d->sCountryCode == other.countryCode() &&
           d->sState == other.state() &&
           d->sCounty == other.county() &&
           d->sCity == other.city() &&
           d->sDistrict == other.district() &&
           d->sStreet == other.street() &&
           d->sPostCode == other.postcode();
}

/*!
    \fn bool QGeoAddress::operator!=(const QGeoAddress &other) const

    Returns true if this address is not equal to \a other,
    otherwise returns false.
*/

/*!
    Returns the country name according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::country() const
{
    return d->sCountry;
}

/*!
    Sets the \a country name according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountry(const QString &country)
{
    d->sCountry = country;
}

/*!
    Returns the country code according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::countryCode() const
{
    return d->sCountryCode;
}

/*!
    Sets the \a countryCode according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountryCode(const QString &countryCode)
{
    d->sCountryCode = countryCode;
}

/*!
    Returns the state.
*/
QString QGeoAddress::state() const
{
    return d->sState;
}

/*!
    Sets the \a state.
*/
void QGeoAddress::setState(const QString &state)
{
    d->sState = state;
}

/*!
    Returns the county.
*/
QString QGeoAddress::county() const
{
    return d->sCounty;
}

/*!
    Sets the \a county.
*/
void QGeoAddress::setCounty(const QString &county)
{
    d->sCounty = county;
}

/*!
    Returns the city.
*/
QString QGeoAddress::city() const
{
    return d->sCity;
}

/*!
    Sets the \a city.
*/
void QGeoAddress::setCity(const QString &city)
{
    d->sCity = city;
}

/*!
    Returns the district.
*/
QString QGeoAddress::district() const
{
    return d->sDistrict;
}

/*!
    Sets the \a district.
*/
void QGeoAddress::setDistrict(const QString &district)
{
    d->sDistrict = district;
}

/*!
    Returns the street-level component of the address.

    This typically includes a street number and street name
    but may also contain things like a unit number, a building
    name, or anything else that might be used to
    distinguish one address from another.
*/
QString QGeoAddress::street() const
{
    return d->sStreet;
}

/*!
    Sets the street-level component of the address to \a street.

    This typically includes a street number and street name
    but may also contain things like a unit number, a building
    name, or anything else that might be used to
    distinguish one address from another.
*/
void QGeoAddress::setStreet(const QString &street)
{
    d->sStreet = street;
}

/*!
    Returns the post code.
*/
QString QGeoAddress::postcode() const
{
    return d->sPostCode;
}

/*!
    Sets the \a postcode.
*/
void QGeoAddress::setPostcode(const QString &postcode)
{
    d->sPostCode = postcode;
}

/*!
    Returns whether this address is empty. An address is considered empty
    if \i all of its fields are empty.
*/
bool QGeoAddress::isEmpty() const
{
    return d->sCountry.isEmpty() &&
           d->sCountryCode.isEmpty() &&
           d->sState.isEmpty() &&
           d->sCounty.isEmpty() &&
           d->sCity.isEmpty() &&
           d->sDistrict.isEmpty() &&
           d->sStreet.isEmpty() &&
           d->sPostCode.isEmpty();
}
/*!
    Clears the all the address' data fields.
*/
void QGeoAddress::clear()
{
    d->sCountry.clear();
    d->sCountryCode.clear();
    d->sState.clear();
    d->sCounty.clear();
    d->sCity.clear();
    d->sDistrict.clear();
    d->sStreet.clear();
    d->sPostCode.clear();
}

QTM_END_NAMESPACE

<commit_msg>Fix documentation<commit_after>
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qgeoaddress.h"
#include "qgeoaddress_p.h"

#ifdef QGEOADDRESS_DEBUG
#include <QDebug>
#endif

QTM_BEGIN_NAMESPACE

QGeoAddressPrivate::QGeoAddressPrivate()
        : QSharedData()
{
}

QGeoAddressPrivate::QGeoAddressPrivate(const QGeoAddressPrivate &other)
        : QSharedData(other),
        sCountry(other.sCountry),
        sCountryCode(other.sCountryCode),
        sState(other.sState),
        sCounty(other.sCounty),
        sCity(other.sCity),
        sDistrict(other.sDistrict),
        sStreet(other.sStreet),
        sPostCode(other.sPostCode)
{
}

QGeoAddressPrivate::~QGeoAddressPrivate()
{
}

/*!
    \class QGeoAddress
    \brief The QGeoAddress class represents an address

    \inmodule QtLocation

    \ingroup location

    This class represents an address of a location.
*/

/*!
    Default constructor.
*/
QGeoAddress::QGeoAddress()
        : d(new QGeoAddressPrivate)
{
}

/*!
    Constructs a copy of \a other.
*/
QGeoAddress::QGeoAddress(const QGeoAddress &other)
        : d(other.d)
{
}

/*!
    Destroys this address.
*/
QGeoAddress::~QGeoAddress()
{
}

/*!
    Assigns the given \a address to this address and
    returns a reference to this address.
*/
QGeoAddress &QGeoAddress::operator=(const QGeoAddress & address)
{
    d = address.d;
    return *this;
}

/*!
    Returns true if this address is equal to \a other,
    otherwise returns false.
*/
bool QGeoAddress::operator==(const QGeoAddress &other) const
{
#ifdef QGEOADDRESS_DEBUG
    qDebug() << "country" << (d->sCountry == other.country());
    qDebug() << "countryCode" << (d->sCountryCode == other.countryCode());
    qDebug() << "state:" <<  (d->sState == other.state());
    qDebug() << "county:" << (d->sCounty == other.county());
    qDebug() << "city:" << (d->sCity == other.city());
    qDebug() << "district:" << (d->sDistrict == other.district());
    qDebug() << "street:" << (d->sStreet == other.street());
    qDebug() << "postcode:" << (d->sPostCode == other.postcode());
#endif

    return d->sCountry == other.country() &&
           d->sCountryCode == other.countryCode() &&
           d->sState == other.state() &&
           d->sCounty == other.county() &&
           d->sCity == other.city() &&
           d->sDistrict == other.district() &&
           d->sStreet == other.street() &&
           d->sPostCode == other.postcode();
}

/*!
    \fn bool QGeoAddress::operator!=(const QGeoAddress &other) const

    Returns true if this address is not equal to \a other,
    otherwise returns false.
*/

/*!
    Returns the country name.
*/
QString QGeoAddress::country() const
{
    return d->sCountry;
}

/*!
    Sets the \a country name.
*/
void QGeoAddress::setCountry(const QString &country)
{
    d->sCountry = country;
}

/*!
    Returns the country code according to ISO 3166-1 alpha-3
*/
QString QGeoAddress::countryCode() const
{
    return d->sCountryCode;
}

/*!
    Sets the \a countryCode according to ISO 3166-1 alpha-3
*/
void QGeoAddress::setCountryCode(const QString &countryCode)
{
    d->sCountryCode = countryCode;
}

/*!
    Returns the state.
*/
QString QGeoAddress::state() const
{
    return d->sState;
}

/*!
    Sets the \a state.
*/
void QGeoAddress::setState(const QString &state)
{
    d->sState = state;
}

/*!
    Returns the county.
*/
QString QGeoAddress::county() const
{
    return d->sCounty;
}

/*!
    Sets the \a county.
*/
void QGeoAddress::setCounty(const QString &county)
{
    d->sCounty = county;
}

/*!
    Returns the city.
*/
QString QGeoAddress::city() const
{
    return d->sCity;
}

/*!
    Sets the \a city.
*/
void QGeoAddress::setCity(const QString &city)
{
    d->sCity = city;
}

/*!
    Returns the district.
*/
QString QGeoAddress::district() const
{
    return d->sDistrict;
}

/*!
    Sets the \a district.
*/
void QGeoAddress::setDistrict(const QString &district)
{
    d->sDistrict = district;
}

/*!
    Returns the street-level component of the address.

    This typically includes a street number and street name
    but may also contain things like a unit number, a building
    name, or anything else that might be used to
    distinguish one address from another.
*/
QString QGeoAddress::street() const
{
    return d->sStreet;
}

/*!
    Sets the street-level component of the address to \a street.

    This typically includes a street number and street name
    but may also contain things like a unit number, a building
    name, or anything else that might be used to
    distinguish one address from another.
*/
void QGeoAddress::setStreet(const QString &street)
{
    d->sStreet = street;
}

/*!
    Returns the post code.
*/
QString QGeoAddress::postcode() const
{
    return d->sPostCode;
}

/*!
    Sets the \a postcode.
*/
void QGeoAddress::setPostcode(const QString &postcode)
{
    d->sPostCode = postcode;
}

/*!
    Returns whether this address is empty. An address is considered empty
    if \i all of its fields are empty.
*/
bool QGeoAddress::isEmpty() const
{
    return d->sCountry.isEmpty() &&
           d->sCountryCode.isEmpty() &&
           d->sState.isEmpty() &&
           d->sCounty.isEmpty() &&
           d->sCity.isEmpty() &&
           d->sDistrict.isEmpty() &&
           d->sStreet.isEmpty() &&
           d->sPostCode.isEmpty();
}
/*!
    Clears the all the address' data fields.
*/
void QGeoAddress::clear()
{
    d->sCountry.clear();
    d->sCountryCode.clear();
    d->sState.clear();
    d->sCounty.clear();
    d->sCity.clear();
    d->sDistrict.clear();
    d->sStreet.clear();
    d->sPostCode.clear();
}

QTM_END_NAMESPACE

<|endoftext|>


<commit_before>#include "game_window.h"
#include <sstream>

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->model = NULL;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ANCHO_DEFAULT, ALTO_DEFAULT,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	// TODO: IMG_INIT

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer != NULL) {
		SDL_DestroyRenderer(renderer);
		renderer = NULL;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window != NULL) {
		Logger::getInstance()->writeWarning("Window never initialized");
		SDL_DestroyWindow(window);
		window = NULL;
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	std::vector<std::shared_ptr<Entity>> entities = this->model->getBoard()->getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(*entities[i], 0, renderer);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	//model->restart()	PARA NO TENER Q INSTANCIAR UN NUEVO MODEL
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	init();
}

void GameWindow::init(){
	this->parser->parse();

	this->model = new Game(parser); // TODO: Esto debería ser parser->build()

	addSpriteSheet("agua", "resources//agua.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT,  1, 0, 0);
	addSpriteSheet("pasto", "resources//pasto_largo.png", 0, 5, TILE_HEIGHT_DEFAULT+5, TILE_WIDTH_DEFAULT, 1, 0, 0);
	addSpriteSheet("piedra", "resources//piedra.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0);
	addSpriteSheet("chancho", "resources//chanchos.png", -14, 32, 44, 48, 15, 0, 1);
	addSpriteSheet("mago", "resources//mago.png", 0, 0, 60, 60, 4, 0, 0);
}

void GameWindow::update(){
	model->update();
	return;
}

void GameWindow::addSpriteSheet(std::string name, std::string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, int fps, int delay) {
	spritesSheets[name] = new SpriteSheet(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
}

void GameWindow::processInput(){
	int mouse_x_screen, mouse_y_screen;

	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			SDL_GetMouseState(&mouse_x_screen, &mouse_y_screen);
			std::ostringstream oss;
			oss << "Mouse en " << mouse_x_screen << "," << mouse_y_screen;

			// Conversion de coordenadas en pantalla a coordenadas mapa

			double XsTerm = (double)(mouse_x_screen - ANCHO_DEFAULT/2)/(double)TILE_WIDTH_DEFAULT;
			double YsTerm = (double)(mouse_y_screen - ALTO_DEFAULT/2)/(double)TILE_HEIGHT_DEFAULT;

			double x_mapa = focus_x + XsTerm + YsTerm + .5;
			double y_mapa = focus_y - XsTerm + YsTerm + .5;

			oss << "; mapa: " << x_mapa << "," << y_mapa;

			Logger::getInstance()->writeInformation(oss.str().c_str());
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
				Logger::getInstance()->writeInformation("Boton Izquierdo");
				model->getBoard()->getProtagonist().setTarget(x_mapa, y_mapa);
			}
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
				Logger::getInstance()->writeInformation("Boton derecho");
			}
		}
	}
}

void GameWindow::scroll(){
	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 5;

	double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
		SDL_GetMouseState(&mouse_x, &mouse_y);

		if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_x / (double)MARGEN_PANTALLA_DEFAULT)) * ds;

			focus_x -= dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
		}
		else if(mouse_x >= ANCHO_DEFAULT - MARGEN_PANTALLA_DEFAULT){

			double dsi = ((double)(mouse_x + MARGEN_PANTALLA_DEFAULT - ANCHO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
		}
		if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_y / (double)MARGEN_PANTALLA_DEFAULT)) * ds;
			focus_x -= dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
		}
		if(mouse_y >= ALTO_DEFAULT - MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = ((double)(mouse_y + MARGEN_PANTALLA_DEFAULT - ALTO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
		}

		auto & board = *(model->getBoard());

		if(focus_x >= board.sizeX - 1){
			focus_x = board.sizeX - 1;
		}
		else if(focus_x < 0){
			focus_x = 0;
		}

		if(focus_y >= board.sizeY - 1){
			focus_y = board.sizeY - 1;
		}else if(focus_y < 0){
			focus_y = 0;
		}
}

int GameWindow::start(){
	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}

	while (!endOfGame())
	{
		scroll();
		processInput();
		update();
		render();

		SDL_Delay(model->getBoard()->dt); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}

<commit_msg>Centro el mago<commit_after>#include "game_window.h"
#include <sstream>

bool GameWindow::sdlInitialized = false;

bool GameWindow::initialize() {
	Logger::getInstance()->writeInformation("Initializing graphics");
	if (GameWindow::sdlInitialized) {
		Logger::getInstance()->writeWarning("SDL already initialized");
	} else {
		atexit(SDL_Quit);
		if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
			Logger::getInstance()->writeError("SDL could not initialize!");
			Logger::getInstance()->writeError(SDL_GetError());
			GameWindow::sdlInitialized = false;
		} else {
			GameWindow::sdlInitialized = true;
		}
	}
	return GameWindow::sdlInitialized;
}

GameWindow::GameWindow() {
	this->parser = new ParserYAML(CONFIG_FILE_PATH);
	this->model = NULL;
	this->exit = false;
	this->focus_x = 0;
	this->focus_y = 0;

	Logger::getInstance()->writeInformation("Creating window");

	GameWindow::initialize();
	window = SDL_CreateWindow("Trabajo Práctico 7542",
		SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
		ANCHO_DEFAULT, ALTO_DEFAULT,
		SDL_WINDOW_SHOWN);

	Logger::getInstance()->writeInformation("Creating renderer");
	renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );

	// TODO: IMG_INIT

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Color: negro opaco
	SDL_RenderClear(renderer); // Limpio pantalla inicialmente
	SDL_RenderPresent( renderer );
}

GameWindow::~GameWindow() {
	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	delete parser;
	delete model;

	Logger::getInstance()->writeInformation("Destroying renderer");
	if (renderer != NULL) {
		SDL_DestroyRenderer(renderer);
		renderer = NULL;
	}

	Logger::getInstance()->writeInformation("Destroying window");
	if (window != NULL) {
		Logger::getInstance()->writeWarning("Window never initialized");
		SDL_DestroyWindow(window);
		window = NULL;
	}
}

bool GameWindow::endOfGame(){
	return this->exit;
}

void GameWindow::render(){
	//	Dibujar
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	std::vector<std::shared_ptr<Entity>> entities = this->model->getBoard()->getEntities();
	std::map<std::string,SpriteSheet*>::iterator it;
	SpriteSheet* ss;
	for (std::size_t i =0; i < entities.size(); ++i){
		it = this->spritesSheets.find(entities[i]->name);
		if(it != this->spritesSheets.end()){
			ss = it->second;
			ss->render(*entities[i], 0, renderer);
		}
		else
			Logger::getInstance()->writeWarning("No existe SpriteSheet para este tipo de entidad" + entities[i]->name);
	}

	SDL_RenderPresent( renderer );
	return;
}

void GameWindow::restart(){
	//model->restart()	PARA NO TENER Q INSTANCIAR UN NUEVO MODEL
	delete model;

	map<std::string, SpriteSheet*>::const_iterator itr;
	for(itr = spritesSheets.begin(); itr != spritesSheets.end(); ++itr){
		delete itr->second;
	}

	init();
}

void GameWindow::init(){
	this->parser->parse();

	this->model = new Game(parser); // TODO: Esto debería ser parser->build()

	addSpriteSheet("agua", "resources//agua.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT,  1, 0, 0);
	addSpriteSheet("pasto", "resources//pasto_largo.png", 0, 5, TILE_HEIGHT_DEFAULT+5, TILE_WIDTH_DEFAULT, 1, 0, 0);
	addSpriteSheet("piedra", "resources//piedra.png", 0, 0, TILE_HEIGHT_DEFAULT, TILE_WIDTH_DEFAULT, 1, 0, 0);
	addSpriteSheet("chancho", "resources//chanchos.png", -14, 32, 44, 48, 15, 0, 1);
	addSpriteSheet("mago", "resources//mago.png", 0, 48, 60, 60, 4, 0, 0);
}

void GameWindow::update(){
	model->update();
	return;
}

void GameWindow::addSpriteSheet(std::string name, std::string pPath, int pixelRefX, int pixelRefY, int altoSprite, int anchoSprite, int cantSprites, int fps, int delay) {
	spritesSheets[name] = new SpriteSheet(pPath, pixelRefX, pixelRefY, altoSprite, anchoSprite, cantSprites, fps, delay, *this);
}

void GameWindow::processInput(){
	int mouse_x_screen, mouse_y_screen;

	//	Procesar input del usuario
	while(SDL_PollEvent(EventHandler::getInstance()->getEvent())) {
		if(EventHandler::getInstance()->getEvent()->type == SDL_QUIT )
			this->exit = true;
		if(EventHandler::getInstance()->getEvent()->type == SDL_KEYDOWN ){
			Logger::getInstance()->writeInformation("Teclado");
			if(EventHandler::getInstance()->getEvent()->key.keysym.sym == SDLK_r){
				restart();
			}
		}
		if( EventHandler::getInstance()->getEvent()->type == SDL_MOUSEBUTTONUP ){
			SDL_GetMouseState(&mouse_x_screen, &mouse_y_screen);
			std::ostringstream oss;
			oss << "Mouse en " << mouse_x_screen << "," << mouse_y_screen;

			// Conversion de coordenadas en pantalla a coordenadas mapa

			double XsTerm = (double)(mouse_x_screen - ANCHO_DEFAULT/2)/(double)TILE_WIDTH_DEFAULT;
			double YsTerm = (double)(mouse_y_screen - ALTO_DEFAULT/2)/(double)TILE_HEIGHT_DEFAULT;

			double x_mapa = focus_x + XsTerm + YsTerm + .5;
			double y_mapa = focus_y - XsTerm + YsTerm + .5;

			oss << "; mapa: " << x_mapa << "," << y_mapa;

			Logger::getInstance()->writeInformation(oss.str().c_str());
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_LEFT ) {
				Logger::getInstance()->writeInformation("Boton Izquierdo");
				model->getBoard()->getProtagonist().setTarget(x_mapa, y_mapa);
			}
			if( EventHandler::getInstance()->getEvent()->button.button == SDL_BUTTON_RIGHT) {
				Logger::getInstance()->writeInformation("Boton derecho");
			}
		}
	}
}

void GameWindow::scroll(){
	Uint8 mouse_b;
	int mouse_x, mouse_y;
	const double SCROLL_SPEED = 5;

	double ds = SCROLL_SPEED * model->getBoard()->dt / 1000; //deltascroll
		SDL_GetMouseState(&mouse_x, &mouse_y);

		if(mouse_x <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_x / (double)MARGEN_PANTALLA_DEFAULT)) * ds;

			focus_x -= dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la izquierda");
		}
		else if(mouse_x >= ANCHO_DEFAULT - MARGEN_PANTALLA_DEFAULT){

			double dsi = ((double)(mouse_x + MARGEN_PANTALLA_DEFAULT - ANCHO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia la derecha");
		}
		if(mouse_y <= MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = (1.0 - ((double)mouse_y / (double)MARGEN_PANTALLA_DEFAULT)) * ds;
			focus_x -= dsi;
			focus_y -= dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia arriba");
		}
		if(mouse_y >= ALTO_DEFAULT - MARGEN_PANTALLA_DEFAULT)
		{
			double dsi = ((double)(mouse_y + MARGEN_PANTALLA_DEFAULT - ALTO_DEFAULT)/(double)MARGEN_PANTALLA_DEFAULT) * ds;

			focus_x += dsi;
			focus_y += dsi;
			Logger::getInstance()->writeInformation("Scrolleando hacia abajo");
		}

		auto & board = *(model->getBoard());

		if(focus_x >= board.sizeX - 1){
			focus_x = board.sizeX - 1;
		}
		else if(focus_x < 0){
			focus_x = 0;
		}

		if(focus_y >= board.sizeY - 1){
			focus_y = board.sizeY - 1;
		}else if(focus_y < 0){
			focus_y = 0;
		}
}

int GameWindow::start(){
	init();
	{
		auto protagonist = model->getBoard()->getProtagonist();
		focus_x = protagonist.getX();
		focus_y = protagonist.getY();
	}

	while (!endOfGame())
	{
		scroll();
		processInput();
		update();
		render();

		SDL_Delay(model->getBoard()->dt); // TODO: Optimizar, sacar hardcodeo
	}
	return 0;
}

<|endoftext|>