<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 */

#ifndef ELEKTRA_KDB_IO_HPP
#define ELEKTRA_KDB_IO_HPP

/*
 * @brief See examples/cpp_example_userio.cpp for how to use
 * USER_DEFINED_IO
 */
#define USER_DEFINED_IO

#include <key.hpp>

#include <iomanip>
#include <ostream>

#include "ansicolors.hpp"

namespace kdb
{

inline std::ostream & printError (std::ostream & os, kdb::Key const & error)
{
	try
	{
		if (!error.getMeta<const kdb::Key> ("error"))
		{
			// no error available
			return os;
		}

		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::RED) << "Sorry, the error (#"
		   << error.getMeta<std::string> ("error/number") << ") occurred ;(" << getErrorColor (ANSI_COLOR::RESET) << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Description: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/description") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Ingroup: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/ingroup") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Module: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/module") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "At: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/file") << ":" << error.getMeta<std::string> ("error/line") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Reason: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/reason") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Mountpoint: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/mountpoint") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Configfile: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/configfile") << std::endl;
	}
	catch (kdb::KeyTypeConversion const & e)
	{
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::RED)
		   << "Sorry, error metadata is not set correctly by a plugin: " << getErrorColor (ANSI_COLOR::RESET) << e.what () << std::endl;
	}

	return os;
}

inline std::ostream & printWarnings (std::ostream & os, kdb::Key const & error)
{
	try
	{
		if (!error.getMeta<const kdb::Key> ("warnings"))
		{
			// no warnings were issued
			return os;
		}

		int nr = error.getMeta<int> ("warnings");
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA) << " Sorry, " << nr + 1 << " warning" << (!nr ? " was" : "s were")
		   << " issued:" << getErrorColor (ANSI_COLOR::RESET) << " ;(" << std::endl;

		for (int i = 0; i <= nr; i++)
		{
			std::ostringstream name;
			name << "warnings/#" << std::setfill ('0') << std::setw (2) << i;
			// os << "\t" << name.str() << ": " << error.getMeta<std::string>(name.str()) << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA)
			   << " Warning " << i << getErrorColor (ANSI_COLOR::RESET) << " (#"
			   << error.getMeta<std::string> (name.str () + "/number") << ")" << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tDescription: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/description") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tIngroup: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/ingroup") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tModule: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/module") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tAt: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/file") << ":"
			   << error.getMeta<std::string> (name.str () + "/line") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tReason: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/reason") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tMountpoint: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/mountpoint") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tConfigfile: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/configfile") << std::endl;
		}
	}
	catch (kdb::KeyTypeConversion const & e)
	{
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA)
		   << "Sorry, warnings metadata not set correctly by a plugin: " << getErrorColor (ANSI_COLOR::RESET) << e.what () << std::endl;
	}

	return os;
}
}

#endif
<commit_msg>reformat source<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 */

#ifndef ELEKTRA_KDB_IO_HPP
#define ELEKTRA_KDB_IO_HPP

/*
 * @brief See examples/cpp_example_userio.cpp for how to use
 * USER_DEFINED_IO
 */
#define USER_DEFINED_IO

#include <key.hpp>

#include <iomanip>
#include <ostream>

#include "ansicolors.hpp"

namespace kdb
{

inline std::ostream & printError (std::ostream & os, kdb::Key const & error)
{
	try
	{
		if (!error.getMeta<const kdb::Key> ("error"))
		{
			// no error available
			return os;
		}

		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::RED) << "Sorry, the error (#"
		   << error.getMeta<std::string> ("error/number") << ") occurred ;(" << getErrorColor (ANSI_COLOR::RESET) << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Description: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/description") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Ingroup: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/ingroup") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Module: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/module") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "At: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/file") << ":" << error.getMeta<std::string> ("error/line") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Reason: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/reason") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Mountpoint: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/mountpoint") << std::endl;
		os << getErrorColor (ANSI_COLOR::BOLD) << "Configfile: " << getErrorColor (ANSI_COLOR::RESET)
		   << error.getMeta<std::string> ("error/configfile") << std::endl;
	}
	catch (kdb::KeyTypeConversion const & e)
	{
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::RED)
		   << "Sorry, error metadata is not set correctly by a plugin: " << getErrorColor (ANSI_COLOR::RESET) << e.what ()
		   << std::endl;
	}

	return os;
}

inline std::ostream & printWarnings (std::ostream & os, kdb::Key const & error)
{
	try
	{
		if (!error.getMeta<const kdb::Key> ("warnings"))
		{
			// no warnings were issued
			return os;
		}

		int nr = error.getMeta<int> ("warnings");
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA) << " Sorry, " << nr + 1 << " warning"
		   << (!nr ? " was" : "s were") << " issued:" << getErrorColor (ANSI_COLOR::RESET) << " ;(" << std::endl;

		for (int i = 0; i <= nr; i++)
		{
			std::ostringstream name;
			name << "warnings/#" << std::setfill ('0') << std::setw (2) << i;
			// os << "\t" << name.str() << ": " << error.getMeta<std::string>(name.str()) << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA) << " Warning " << i
			   << getErrorColor (ANSI_COLOR::RESET) << " (#" << error.getMeta<std::string> (name.str () + "/number") << ")"
			   << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tDescription: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/description") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tIngroup: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/ingroup") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tModule: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/module") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tAt: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/file") << ":"
			   << error.getMeta<std::string> (name.str () + "/line") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tReason: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/reason") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tMountpoint: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/mountpoint") << std::endl;
			os << getErrorColor (ANSI_COLOR::BOLD) << "\tConfigfile: " << getErrorColor (ANSI_COLOR::RESET)
			   << error.getMeta<std::string> (name.str () + "/configfile") << std::endl;
		}
	}
	catch (kdb::KeyTypeConversion const & e)
	{
		os << getErrorColor (ANSI_COLOR::BOLD) << getErrorColor (ANSI_COLOR::MAGENTA)
		   << "Sorry, warnings metadata not set correctly by a plugin: " << getErrorColor (ANSI_COLOR::RESET) << e.what ()
		   << std::endl;
	}

	return os;
}
}

#endif
<|endoftext|>


<commit_before>#include "tracing_command_runner.h"

#include <assert.h>

#include "util.h"
#include "sandbox_parser.h"

namespace shk {
namespace {

class TemporaryFile {
 public:
  TemporaryFile(FileSystem &file_system) throw(IoError)
      : path(file_system.mkstemp("shk.tmp.sb.XXXXXXXX")),
        _file_system(file_system) {}

  ~TemporaryFile() {
    try {
      _file_system.unlink(path);
    } catch (IoError &) {
      // Maybe the file is already gone, or was never created. We don't care
      // enough to make sure to clean up this temporary file.
    }
  }

  const std::string path;

 private:
  FileSystem &_file_system;
};

class TracingCommandRunner : public CommandRunner {
 public:
  TracingCommandRunner(
      FileSystem &file_system,
      std::unique_ptr<CommandRunner> &&inner)
      : _file_system(file_system),
        _inner(std::move(inner)) {}

  void invoke(
      const std::string &command,
      UseConsole use_console,
      const Callback &callback) override {
    if (command.empty()) {
      _inner->invoke("", use_console, callback);
      return;
    }

    try {
      const auto tmp = std::make_shared<TemporaryFile>(_file_system);

      std::string escaped_command;
      getShellEscapedString(command, &escaped_command);
      // Here we assume that the generated temporary file path does not contain
      // ' or ". It would be an evil temporary file creation function that would
      // do that.
      _inner->invoke(
          "/usr/bin/sandbox-exec -p '(version 1)(trace \"" +
              tmp->path + "\")' /bin/sh -c " + escaped_command,
          use_console,
          [this, tmp, callback](CommandRunner::Result &&result) {
            computeResults(tmp->path, result);
            callback(std::move(result));
          });
    } catch (IoError &error) {
      _inner->invoke(
          "/bin/echo Failed to create temporary file && exit 1",
          use_console,
          callback);
    }
  }

  size_t size() const override {
    return _inner->size();
  }

  bool canRunMore() const override {
    return _inner->canRunMore();
  }

  bool runCommands() override {
    return _inner->runCommands();
  }

 private:
  void computeResults(
      const std::string &path,
      CommandRunner::Result &result) {
    if (result.exit_status != ExitStatus::SUCCESS) {
      // If the command did not suceed there is no need to track dependencies.
      // Trying to do so might not even work, which could cause confusing
      // extraenous error messages.
      return;
    }
    try {
      auto sandbox = parseSandbox(
          SandboxIgnores::defaults(),
          _file_system.readFile(path));

      for (const auto &path : sandbox.read) {
        result.input_files.push_back(path);
      }

      for (const auto &path : sandbox.created) {
        result.output_files.push_back(path);
      }

      if (!sandbox.violations.empty()) {
        for (const auto &violation : sandbox.violations) {
          result.output += "Linting error: " + violation + "\n";
        }
        result.exit_status = ExitStatus::FAILURE;
      }
    } catch (ParseError &error) {
      result.output +=
          std::string("Failed to parse sandbox file: ") + error.what() + "\n";
      result.exit_status = ExitStatus::FAILURE;
    } catch (IoError &error) {
      result.output +=
          std::string("Failed to open sandbox file: ") + error.what() + "\n";
      result.exit_status = ExitStatus::FAILURE;
    }
  }

  FileSystem &_file_system;
  const std::unique_ptr<CommandRunner> _inner;
};

}

std::unique_ptr<CommandRunner> makeTracingCommandRunner(
    FileSystem &file_system,
    std::unique_ptr<CommandRunner> &&command_runner) {
  return std::unique_ptr<CommandRunner>(
      new TracingCommandRunner(file_system, std::move(command_runner)));
}

}  // namespace shk
<commit_msg>Catch exceptions by const reference<commit_after>#include "tracing_command_runner.h"

#include <assert.h>

#include "util.h"
#include "sandbox_parser.h"

namespace shk {
namespace {

class TemporaryFile {
 public:
  TemporaryFile(FileSystem &file_system) throw(IoError)
      : path(file_system.mkstemp("shk.tmp.sb.XXXXXXXX")),
        _file_system(file_system) {}

  ~TemporaryFile() {
    try {
      _file_system.unlink(path);
    } catch (const IoError &) {
      // Maybe the file is already gone, or was never created. We don't care
      // enough to make sure to clean up this temporary file.
    }
  }

  const std::string path;

 private:
  FileSystem &_file_system;
};

class TracingCommandRunner : public CommandRunner {
 public:
  TracingCommandRunner(
      FileSystem &file_system,
      std::unique_ptr<CommandRunner> &&inner)
      : _file_system(file_system),
        _inner(std::move(inner)) {}

  void invoke(
      const std::string &command,
      UseConsole use_console,
      const Callback &callback) override {
    if (command.empty()) {
      _inner->invoke("", use_console, callback);
      return;
    }

    try {
      const auto tmp = std::make_shared<TemporaryFile>(_file_system);

      std::string escaped_command;
      getShellEscapedString(command, &escaped_command);
      // Here we assume that the generated temporary file path does not contain
      // ' or ". It would be an evil temporary file creation function that would
      // do that.
      _inner->invoke(
          "/usr/bin/sandbox-exec -p '(version 1)(trace \"" +
              tmp->path + "\")' /bin/sh -c " + escaped_command,
          use_console,
          [this, tmp, callback](CommandRunner::Result &&result) {
            computeResults(tmp->path, result);
            callback(std::move(result));
          });
    } catch (const IoError &error) {
      _inner->invoke(
          "/bin/echo Failed to create temporary file && exit 1",
          use_console,
          callback);
    }
  }

  size_t size() const override {
    return _inner->size();
  }

  bool canRunMore() const override {
    return _inner->canRunMore();
  }

  bool runCommands() override {
    return _inner->runCommands();
  }

 private:
  void computeResults(
      const std::string &path,
      CommandRunner::Result &result) {
    if (result.exit_status != ExitStatus::SUCCESS) {
      // If the command did not suceed there is no need to track dependencies.
      // Trying to do so might not even work, which could cause confusing
      // extraenous error messages.
      return;
    }
    try {
      auto sandbox = parseSandbox(
          SandboxIgnores::defaults(),
          _file_system.readFile(path));

      for (const auto &path : sandbox.read) {
        result.input_files.push_back(path);
      }

      for (const auto &path : sandbox.created) {
        result.output_files.push_back(path);
      }

      if (!sandbox.violations.empty()) {
        for (const auto &violation : sandbox.violations) {
          result.output += "Linting error: " + violation + "\n";
        }
        result.exit_status = ExitStatus::FAILURE;
      }
    } catch (const ParseError &error) {
      result.output +=
          std::string("Failed to parse sandbox file: ") + error.what() + "\n";
      result.exit_status = ExitStatus::FAILURE;
    } catch (const IoError &error) {
      result.output +=
          std::string("Failed to open sandbox file: ") + error.what() + "\n";
      result.exit_status = ExitStatus::FAILURE;
    }
  }

  FileSystem &_file_system;
  const std::unique_ptr<CommandRunner> _inner;
};

}

std::unique_ptr<CommandRunner> makeTracingCommandRunner(
    FileSystem &file_system,
    std::unique_ptr<CommandRunner> &&command_runner) {
  return std::unique_ptr<CommandRunner>(
      new TracingCommandRunner(file_system, std::move(command_runner)));
}

}  // namespace shk
<|endoftext|>


<commit_before>#ifndef BST_HPP
#define BST_HPP
#include "BSTNode.hpp"
#include "BSTIterator.hpp"
#include <utility> // for std::pair

template<typename Data>
class BST {

protected:

  /** Pointer to the root of this BST, or nullptr if the BST is empty */
  BSTNode<Data>* root;

  /** Number of Data items stored in this BST. */
  unsigned int isize;

public:

  /** iterator is an aliased typename for BSTIterator<Data>. */
  typedef BSTIterator<Data> iterator;

  /** Default constructor.
      Initialize an empty BST.
   */
  BST() : root(nullptr), isize(0)
  {
  }

  /** Default destructor.
   *  It is virtual, to allow appropriate destruction of subclass objects.
   *  Delete every node in this BST.
   */ // TODO
  virtual ~BST()
  {
     //may need to delete isize, iterator as well...
     delete this->root;
     this->root = NULL;
  }

  /** Insert a Data item in the BST.
   *  Return a pair, with the pair's first member set to an
   *  iterator pointing to either the newly inserted element
   *  or to the equivalent element already in the set.
   *  The pair's second element is set to true
   *  if a new element was inserted or false if an
   *  equivalent element already existed.
   */ // TODO
  virtual std::pair<iterator,bool> insert(const Data& item)
  {
    bool inserted;
    if (this->root == NULL){
      this->root = new BSTNode<Data>(item);
      BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
      inserted = true;
      ++isize;
      return std::make_pair(*iter,inserted);
    }
    BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
    while (iter->curr != NULL){
      if (iter->curr->data > item){
        iter->curr = iter->curr->left;
      }
      else if (iter->curr->data < item){
        iter->curr = iter->curr->right;
      }
      else { //iter->curr->value == item
        inserted = false;
        ++isize;
        return std::make_pair(*iter, inserted);
      }
    }
    iter->curr = new BSTNode<Data>(item);
    inserted = true;
    ++isize;
    return std::make_pair(*iter,inserted);
  }

  /** Find a Data item in the BST.
   *  Return an iterator pointing to the item, or the end
   *  iterator if the item is not in the BST.
   */ // TODO
  iterator find(const Data& item) const
  {
    if (this->root == NULL){
      BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
      return *iter;
    }
    BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
    while (iter->curr != NULL && iter->curr->data != item){
      if (iter->curr->data > item){
        iter->curr = iter->curr->left;
      }
      if (iter->curr->data < item){
        iter->curr = iter->curr->right;
      }
    }
    return *iter;
  }

  /** Return the number of items currently in the BST.
   */ // TODO
  unsigned int size() const
  {
    return isize;
  }

  /** Remove all elements from this BST, and destroy them,
   *  leaving this BST with a size of 0.
   */ // TODO
  void clear()
  {
    delete this->root;
    this->root = NULL;
    isize = 0;
  }

  /** Return true if the BST is empty, else false.
   */ // TODO
  bool empty() const
  {
    return ( isize == 0 );
  }

  /** Return an iterator pointing to the first item in the BST.
   */ // TODO
  iterator begin() const
  {
    BSTNode<Data>* temp = new BSTNode<Data>(this->root);
    while (temp->left)
      temp = temp->left;

    return new BSTIterator<Data>(temp);
  }

  /** Return an iterator pointing past the last item in the BST.
   */
  iterator end() const
  {
    return typename BST<Data>::iterator(nullptr);
  }

 };

#endif //BST_HPP
<commit_msg>Edited insert logic<commit_after>#ifndef BST_HPP
#define BST_HPP
#include "BSTNode.hpp"
#include "BSTIterator.hpp"
#include <utility> // for std::pair

template<typename Data>
class BST {

protected:

  /** Pointer to the root of this BST, or nullptr if the BST is empty */
  BSTNode<Data>* root;

  /** Number of Data items stored in this BST. */
  unsigned int isize;

public:

  /** iterator is an aliased typename for BSTIterator<Data>. */
  typedef BSTIterator<Data> iterator;

  /** Default constructor.
      Initialize an empty BST.
   */
  BST() : root(nullptr), isize(0)
  {
  }

  /** Default destructor.
   *  It is virtual, to allow appropriate destruction of subclass objects.
   *  Delete every node in this BST.
   */ // TODO
  virtual ~BST()
  {
     //may need to delete isize, iterator as well...
     delete this->root;
     this->root = NULL;
  }

  /** Insert a Data item in the BST.
   *  Return a pair, with the pair's first member set to an
   *  iterator pointing to either the newly inserted element
   *  or to the equivalent element already in the set.
   *  The pair's second element is set to true
   *  if a new element was inserted or false if an
   *  equivalent element already existed.
   */ // TODO
  virtual std::pair<iterator,bool> insert(const Data& item)
  {
    bool inserted;
    if (this->root == NULL){
      this->root = new BSTNode<Data>(item);
      BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
      inserted = true;
      ++isize;
      return std::make_pair(*iter,inserted);
    }
    BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
    BSTIterator<Data>* parent = new BSTIterator<Data>(this->root);
    while (iter->curr != NULL){
      if (iter->curr->data > item){
        parent->curr = iter->curr->left;
        iter->curr = iter->curr->left;
      }
      else if (iter->curr->data < item){
        parent->curr = iter->curr->left;
        iter->curr = iter->curr->right;
      }
      else { //iter->curr->value == item
        inserted = false;
        return std::make_pair(*iter, inserted);
      }
    }
    iter->curr = new BSTNode<Data>(item);
    iter->curr->parent = parent->curr
    inserted = true;
    ++isize;
    return std::make_pair(*iter,inserted);
  }

  /** Find a Data item in the BST.
   *  Return an iterator pointing to the item, or the end
   *  iterator if the item is not in the BST.
   */ // TODO
  iterator find(const Data& item) const
  {
    if (this->root == NULL){
      BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
      return *iter;
    }
    BSTIterator<Data>* iter = new BSTIterator<Data>(this->root);
    while (iter->curr != NULL && iter->curr->data != item){
      if (iter->curr->data > item){
        iter->curr = iter->curr->left;
      }
      if (iter->curr->data < item){
        iter->curr = iter->curr->right;
      }
    }
    return *iter;
  }

  /** Return the number of items currently in the BST.
   */ // TODO
  unsigned int size() const
  {
    return isize;
  }

  /** Remove all elements from this BST, and destroy them,
   *  leaving this BST with a size of 0.
   */ // TODO
  void clear()
  {
    delete this->root;
    this->root = NULL;
    isize = 0;
  }

  /** Return true if the BST is empty, else false.
   */ // TODO
  bool empty() const
  {
    return ( isize == 0 );
  }

  /** Return an iterator pointing to the first item in the BST.
   */ // TODO
  iterator begin() const
  {
    BSTNode<Data>* temp = new BSTNode<Data>(this->root);
    while (temp->left)
      temp = temp->left;

    return new BSTIterator<Data>(temp);
  }

  /** Return an iterator pointing past the last item in the BST.
   */
  iterator end() const
  {
    return typename BST<Data>::iterator(nullptr);
  }

 };

#endif //BST_HPP
<|endoftext|>


<commit_before>#include "UASQuickTabView.h"
#include "ui_UASQuickTabView.h"
#include <QTextCodec>
#include <QDebug>
#include <QTableWidget>

UASQuickTabView::UASQuickTabView(QWidget *parent) :
    ui(new Ui::UASQuickTabView)
{
    ui->setupUi(this);
    this->setLayout(ui->gridLayout);

	QStringList nameList;// = new QStringList();
//	nameList.append("Широта:");
//	nameList.append("Долгота:");
//	nameList.append("Высота:");
//	nameList.append("Курс:");
//	nameList.append("Крен:");
//	nameList.append("Тангаж:");

    nameList.append(tr("Latitude:"));
    nameList.append(tr("Longitude:"));
    nameList.append(tr("Altitude:"));
    nameList.append(tr("Roll:"));
    nameList.append(tr("Pitch:"));
    nameList.append(tr("Yaw:"));

    fieldNameList << "M24:GLOBAL_POSITION_INT.lat"
                  << "M24:GLOBAL_POSITION_INT.lon"
                  << "M24:GLOBAL_POSITION_INT.alt"
                  << "M24:ATTITUDE.roll"
                  << "M24:ATTITUDE.pitch"
                  << "M24:ATTITUDE.yaw";

    foreach(QString str, fieldNameList){
        uasPropertyValueMap.insert(str, 0.0);
    }

	QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
	ui->tableWidget->setColumnCount(2);
    ui->tableWidget->setRowCount(6);
    ui->tableWidget->setLineWidth(1);
    ui->tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    ui->tableWidget->setStyleSheet("gridline-color : gray");

    //tableFont = new QFont("Times New Roman", 14, 3);
//    tableFont.setFamily("Times New Roman");
    tableFont.setPixelSize(14);
    tableFont.setBold(3);

    for(int i = 0; i < nameList.count(); i++) {
        /* Add first column that shows lable names.*/
        QTableWidgetItem* item = new QTableWidgetItem();
        Q_ASSERT(item);
        if (item) {
            item->setText(nameList.at(i));
            tableNameList.append(item);
            item->setFont(tableFont);
            item->setFlags(item->flags() ^ Qt::ItemIsEditable ^ Qt::ItemIsSelectable);
            ui->tableWidget->setItem(i, 0, item);
        }

        /* Add column with values.*/
        item = new QTableWidgetItem();
        Q_ASSERT(item);
        if (item) {
            tableValueList.append(item);
            item->setFont(tableFont);
            item->setText("0.0");
            item->setFlags(item->flags() ^ Qt::ItemIsEditable ^ Qt::ItemIsSelectable);
            ui->tableWidget->setItem(i, 1, item);
        }
    }

    updateTimer = new QTimer(this);
    connect(updateTimer,SIGNAL(timeout()),this,SLOT(updateTimerTick()));
    updateTimer->start(1000);

//    testTimerValue = true;
//    testTimer = new QTimer(this);
//    testTimer->setSingleShot(false);
//    connect(testTimer,SIGNAL(timeout()),this,SLOT(testTimerExpired()));
//    testTimer->start(750);

}

UASQuickTabView::~UASQuickTabView()
{
    delete ui;
    foreach (QTableWidgetItem* item, tableNameList) {
        delete item;
    }
    foreach (QTableWidgetItem* item, tableValueList) {
        delete item;
    }
    delete updateTimer;
}

void UASQuickTabView::addSource(MAVLinkDecoder *decoder)
{
    connect(decoder,SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)),this,SLOT(valueChanged(int,QString,QString,QVariant,quint64)));
}

void UASQuickTabView::valueChanged(const int uasId, const QString& name, const QString& unit, const QVariant &variant, const quint64 msec)
{
    Q_UNUSED(uasId);
    Q_UNUSED(unit);
    Q_UNUSED(msec);

    bool ok;
    double value = variant.toDouble(&ok);
    QMetaType::Type metaType = static_cast<QMetaType::Type>(variant.type());
    if(!ok || metaType == QMetaType::QString || metaType == QMetaType::QByteArray)
        return;
    //qDebug()<<name<<" "<<value;
//    if (!uasPropertyValueMap.contains(name))
//    {
//        if (quickViewSelectDialog)
//        {
//            quickViewSelectDialog->addItem(name);
//        }
//    }

    if((name == "M24:GLOBAL_POSITION_INT.lat")||(name == "M24:GLOBAL_POSITION_INT.lon"))
        uasPropertyValueMap[name] = value/10000000;
    else if(name == "M24:GLOBAL_POSITION_INT.alt")
        uasPropertyValueMap[name] = value/1000;
    else if((name == "M24:ATTITUDE.roll")||(name == "M24:ATTITUDE.pitch")||(name == "M24:ATTITUDE.yaw"))
        uasPropertyValueMap[name] = value/M_PI*180;
}

void UASQuickTabView::updateTimerTick()
{
    for(int i = 0; i < fieldNameList.size(); i++){
        //QString str = QString::number(uasPropertyValueMap[fieldNameList.at(i)]);
        QString str = formText(fieldNameList.at(i), uasPropertyValueMap[fieldNameList.at(i)]);
        ui->tableWidget->item(i,1)->setText(str);
    }
}

//void UASQuickTabView::testTimerExpired(){
//    if(testTimerValue == true){
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lat","unit",538893530,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lon","unit",275296780,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.alt","unit",272000,0);
//        valueChanged(0,"M24:ATTITUDE.roll","unit",0.36814,0);
//        valueChanged(0,"M24:ATTITUDE.pitch","unit",0.56715,0);
//        valueChanged(0,"M24:ATTITUDE.yaw","unit",0.24715,0);
//        testTimerValue = false;
//    }
//    else{
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lat","unit",-549993530,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lon","unit",-277796780,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.alt","unit",284000,0);
//        valueChanged(0,"M24:ATTITUDE.roll","unit",0.35614,0);
//        valueChanged(0,"M24:ATTITUDE.pitch","unit",0.46815,0);
//        valueChanged(0,"M24:ATTITUDE.yaw","unit",0.67895,0);
//        testTimerValue = true;
//    }
//}

void UASQuickTabView::setTableGeometry(){

    ui->tableWidget->setColumnWidth(0, ((this->width() - 5)/2));
    ui->tableWidget->setColumnWidth(1, ((this->width())/2));

    for(int i = 0; i < ui->tableWidget->rowCount(); i++) {
        ui->tableWidget->setRowHeight(i, (this->height() - 2)/6);
        //qDebug()<<"qgridrowminimumheight: "<<ui->gridLayout->rowMinimumHeight(0);
    }

}

QString UASQuickTabView::formText(QString name, double value){

    QString str;

    if(name == "M24:GLOBAL_POSITION_INT.lat"){
        if(value >= 0){
            str = QString::number(value,'f',5);
            str += 0x00B0;
             str += tr("n.l.");
        }
        else if(value < 0){
            value *=-1;
            str = QString::number(value,'f',5);
            str += 0x00B0;
            str += tr("s.l.");
        }
    }

    else if(name == "M24:GLOBAL_POSITION_INT.lon"){
        if(value >= 0){
            str = QString::number(value,'f',5);
            str += 0x00B0;
             str += tr("e.l.");
        }
        else if(value < 0){
            value *=-1;
            str = QString::number(value,'f',5);
            str += 0x00B0;
            str += tr("w.l.");
        }
    }

    else if(name == "M24:GLOBAL_POSITION_INT.alt"){
        str = QString::number(value,'f',1);
        str +=tr("m.");
    }
    else if((name == "M24:ATTITUDE.roll")||(name == "M24:ATTITUDE.pitch")||(name == "M24:ATTITUDE.yaw")){
        str = QString::number(value,'f',2);
        str += 0x00B0;
    }
    return str;
}

void UASQuickTabView::resizeEvent(QResizeEvent *event){
    setTableGeometry();
}

<commit_msg>- Added spaces.<commit_after>#include "UASQuickTabView.h"
#include "ui_UASQuickTabView.h"
#include <QTextCodec>
#include <QDebug>
#include <QTableWidget>

UASQuickTabView::UASQuickTabView(QWidget *parent) :
    ui(new Ui::UASQuickTabView)
{
    ui->setupUi(this);
    this->setLayout(ui->gridLayout);

	QStringList nameList;// = new QStringList();
//	nameList.append("Широта:");
//	nameList.append("Долгота:");
//	nameList.append("Высота:");
//	nameList.append("Курс:");
//	nameList.append("Крен:");
//	nameList.append("Тангаж:");

    nameList.append(tr("Latitude:"));
    nameList.append(tr("Longitude:"));
    nameList.append(tr("Altitude:"));
    nameList.append(tr("Roll:"));
    nameList.append(tr("Pitch:"));
    nameList.append(tr("Yaw:"));

    fieldNameList << "M24:GLOBAL_POSITION_INT.lat"
                  << "M24:GLOBAL_POSITION_INT.lon"
                  << "M24:GLOBAL_POSITION_INT.alt"
                  << "M24:ATTITUDE.roll"
                  << "M24:ATTITUDE.pitch"
                  << "M24:ATTITUDE.yaw";

    foreach(QString str, fieldNameList){
        uasPropertyValueMap.insert(str, 0.0);
    }

	QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
	ui->tableWidget->setColumnCount(2);
    ui->tableWidget->setRowCount(6);
    ui->tableWidget->setLineWidth(1);
    ui->tableWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    ui->tableWidget->setStyleSheet("gridline-color : gray");

    //tableFont = new QFont("Times New Roman", 14, 3);
//    tableFont.setFamily("Times New Roman");
    tableFont.setPixelSize(14);
    tableFont.setBold(3);

    for(int i = 0; i < nameList.count(); i++) {
        /* Add first column that shows lable names.*/
        QTableWidgetItem* item = new QTableWidgetItem();
        Q_ASSERT(item);
        if (item) {
            item->setText(nameList.at(i));
            tableNameList.append(item);
            item->setFont(tableFont);
            item->setFlags(item->flags() ^ Qt::ItemIsEditable ^ Qt::ItemIsSelectable);
            ui->tableWidget->setItem(i, 0, item);
        }

        /* Add column with values.*/
        item = new QTableWidgetItem();
        Q_ASSERT(item);
        if (item) {
            tableValueList.append(item);
            item->setFont(tableFont);
            item->setText("0.0");
            item->setFlags(item->flags() ^ Qt::ItemIsEditable ^ Qt::ItemIsSelectable);
            ui->tableWidget->setItem(i, 1, item);
        }
    }

    updateTimer = new QTimer(this);
    connect(updateTimer,SIGNAL(timeout()),this,SLOT(updateTimerTick()));
    updateTimer->start(1000);

//    testTimerValue = true;
//    testTimer = new QTimer(this);
//    testTimer->setSingleShot(false);
//    connect(testTimer,SIGNAL(timeout()),this,SLOT(testTimerExpired()));
//    testTimer->start(750);

}

UASQuickTabView::~UASQuickTabView()
{
    delete ui;
    foreach (QTableWidgetItem* item, tableNameList) {
        delete item;
    }
    foreach (QTableWidgetItem* item, tableValueList) {
        delete item;
    }
    delete updateTimer;
}

void UASQuickTabView::addSource(MAVLinkDecoder *decoder)
{
    connect(decoder,SIGNAL(valueChanged(int,QString,QString,QVariant,quint64)),this,SLOT(valueChanged(int,QString,QString,QVariant,quint64)));
}

void UASQuickTabView::valueChanged(const int uasId, const QString& name, const QString& unit, const QVariant &variant, const quint64 msec)
{
    Q_UNUSED(uasId);
    Q_UNUSED(unit);
    Q_UNUSED(msec);

    bool ok;
    double value = variant.toDouble(&ok);
    QMetaType::Type metaType = static_cast<QMetaType::Type>(variant.type());
    if(!ok || metaType == QMetaType::QString || metaType == QMetaType::QByteArray)
        return;
    //qDebug()<<name<<" "<<value;
//    if (!uasPropertyValueMap.contains(name))
//    {
//        if (quickViewSelectDialog)
//        {
//            quickViewSelectDialog->addItem(name);
//        }
//    }

    if((name == "M24:GLOBAL_POSITION_INT.lat")||(name == "M24:GLOBAL_POSITION_INT.lon"))
        uasPropertyValueMap[name] = value/10000000;
    else if(name == "M24:GLOBAL_POSITION_INT.alt")
        uasPropertyValueMap[name] = value/1000;
    else if((name == "M24:ATTITUDE.roll")||(name == "M24:ATTITUDE.pitch")||(name == "M24:ATTITUDE.yaw"))
        uasPropertyValueMap[name] = value/M_PI*180;
}

void UASQuickTabView::updateTimerTick()
{
    for(int i = 0; i < fieldNameList.size(); i++){
        //QString str = QString::number(uasPropertyValueMap[fieldNameList.at(i)]);
        QString str = formText(fieldNameList.at(i), uasPropertyValueMap[fieldNameList.at(i)]);
        ui->tableWidget->item(i,1)->setText(str);
    }
}

//void UASQuickTabView::testTimerExpired(){
//    if(testTimerValue == true){
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lat","unit",538893530,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lon","unit",275296780,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.alt","unit",272000,0);
//        valueChanged(0,"M24:ATTITUDE.roll","unit",0.36814,0);
//        valueChanged(0,"M24:ATTITUDE.pitch","unit",0.56715,0);
//        valueChanged(0,"M24:ATTITUDE.yaw","unit",0.24715,0);
//        testTimerValue = false;
//    }
//    else{
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lat","unit",-549993530,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.lon","unit",-277796780,0);
//        valueChanged(0,"M24:GLOBAL_POSITION_INT.alt","unit",284000,0);
//        valueChanged(0,"M24:ATTITUDE.roll","unit",0.35614,0);
//        valueChanged(0,"M24:ATTITUDE.pitch","unit",0.46815,0);
//        valueChanged(0,"M24:ATTITUDE.yaw","unit",0.67895,0);
//        testTimerValue = true;
//    }
//}

void UASQuickTabView::setTableGeometry(){

    ui->tableWidget->setColumnWidth(0, ((this->width() - 5)/2));
    ui->tableWidget->setColumnWidth(1, ((this->width())/2));

    for(int i = 0; i < ui->tableWidget->rowCount(); i++) {
        ui->tableWidget->setRowHeight(i, (this->height() - 2)/6);
        //qDebug()<<"qgridrowminimumheight: "<<ui->gridLayout->rowMinimumHeight(0);
    }

}

QString UASQuickTabView::formText(QString name, double value){

    QString str;

    if(name == "M24:GLOBAL_POSITION_INT.lat"){
        if(value >= 0){
            str = QString::number(value,'f',5);
            str += 0x00B0;
             str += tr(" N");
        }
        else if(value < 0){
            value *=-1;
            str = QString::number(value,'f',5);
            str += 0x00B0;
            str += tr(" S");
        }
    }

    else if(name == "M24:GLOBAL_POSITION_INT.lon"){
        if(value >= 0){
            str = QString::number(value,'f',5);
            str += 0x00B0;
             str += tr(" E");
        }
        else if(value < 0){
            value *=-1;
            str = QString::number(value,'f',5);
            str += 0x00B0;
            str += tr(" W");
        }
    }

    else if(name == "M24:GLOBAL_POSITION_INT.alt"){
        str = QString::number(value,'f',1);
        str +=tr(" m.");
    }
    else if((name == "M24:ATTITUDE.roll")||(name == "M24:ATTITUDE.pitch")||(name == "M24:ATTITUDE.yaw")){
        str = QString::number(value,'f',2);
        str += 0x00B0;
    }
    return str;
}

void UASQuickTabView::resizeEvent(QResizeEvent *event){
    setTableGeometry();
}

<|endoftext|>


<commit_before>#include "Player.h"
#include "Resources.h"
#include "Utils.h"
#include "Network.h"
#include <cmath>
#include "LD32.h"

Player::Player(Game* game)
    : Object(game, sf::Vector2f(50, 50), Resources::texturePlayer, sf::Vector2i(2, 1)),
    network(game), game(game)
{
    mapInput();
    state = SELECT_BEAST;
    timer = 0;
}

Player::~Player()
{
}

void Player::mapInput() {
    inputManager->addMouseMapping(sf::Mouse::Button::Left);
}

void Player::update(float deltaTime) {
    network.update();
    switch(state) {

    case START_MENU:
        startMenu(deltaTime);
        break;
    case SELECT_BEAST:
        selectBeast(deltaTime);
        break;
    case UPGRADE_BEAST:
        upgradeBeast(deltaTime);
        break;
    case CITIES_INITIALITZATION:
        citiesInitialitzation(deltaTime);
        break;
    case BEFORE_CITY_SELECTION:
        beforeCitySelection(deltaTime);
        break;
    case CITY_SELECTION:
        citySelection(deltaTime);
        break;
    case AFTER_CITY_SELECTION:
        afterCitySelection(deltaTime);
        break;
    case MOVE_NEXT_CITY:
        moveNextCity(deltaTime);
        break;
    case MOVING_ANIMATION:
        movingAnimation(deltaTime);
        break;
    case IN_BATTLE:
        inBattle(deltaTime);
        break;
    case BATTLE_ANIMATION:
        battleAnimation(deltaTime);
        break;
    case BATTLE_RESULT:
        battleResult(deltaTime);
        break;
    case ROUND_RESULT:
        roundResult(deltaTime);
        break;
    default:
        break;
    }

}

void Player::draw() {
    network.draw();

    sf::Text text;
    text.setFont(Resources::font);
    text.setString(std::to_string(numBeasts));
    text.setCharacterSize(24);
    text.setPosition(sf::Vector2f(50, 50));

    game->getWindow()->draw(text);

    text.setFont(Resources::font);
    text.setString(std::to_string(numCityBeasts));
    text.setCharacterSize(24);
    text.setPosition(sf::Vector2f(50, 100));

    game->getWindow()->draw(text);
}

void Player::startMenu(float deltaTime) {

}

void Player::selectBeast(float deltaTime) {
    numBeasts = 10;
    beasts = Beasts(game, numBeasts, 10, 10, 10, 10, 10);
    state = UPGRADE_BEAST;
}

void Player::upgradeBeast(float deltaTime) {
    state = CITIES_INITIALITZATION;
}

void Player::citiesInitialitzation(float deltaTime) {
    network.addPath(0,1);
    network.addPath(1,3);
    network.addPath(3,2);
    network.addPath(2,4);
    network.addPath(2,5);
    network.addPath(4,5);
    network.addPath(2, 6);
    network.addPath(3, 9);
    network.addPath(6, 7);
    network.addPath(6, 12);
    network.addPath(7, 8);
    network.addPath(7, 9);
    network.addPath(9, 10);
    network.addPath(10, 11);
    network.addPath(11, 12);

    path.clear();
    path.push_back(0);
    network.getCity(0)->highlightSpecial();

    state = BEFORE_CITY_SELECTION;
}

void Player::beforeCitySelection(float deltaTime) {
    currentNeighbours = network.getNeighbours(path.back());

    if (currentNeighbours.size() <= 0) {
        pathInitialLength = path.size();
        state = MOVE_NEXT_CITY;
        return;
    }

    //Highlight neighbours
    std::vector<int>::iterator it = currentNeighbours.begin();
    for (; it != currentNeighbours.end(); it++) {
        network.getCity(*it)->highlight();
    }

    state = CITY_SELECTION;
}

void Player::citySelection(float deltaTime) {
    if (inputManager->getMouseState(sf::Mouse::Button::Left) == true) {
        sf::Vector2f mousePos = sf::Vector2f(inputManager->getMousePosition().x, inputManager->getMousePosition().y);
        int result = network.getCityByCoords(mousePos);
        bool inNeighbours = false;

        for (std::vector<int>::iterator it = currentNeighbours.begin(); it != currentNeighbours.end(); it++) {
            if (*it == result) {
                inNeighbours = true;
                break;
            }
        }

        if (inNeighbours) {
            network.destroyNode(path.back());
            path.push_back(result);
            state = AFTER_CITY_SELECTION;
        }
    }
}

void Player::afterCitySelection(float deltaTime) {
    //Unhighlight neighbours
    std::vector<int>::iterator it = currentNeighbours.begin();

    for (; it != currentNeighbours.end(); it++) {
        network.getCity(*it)->unHighlight();
    }

    //Highlight special selected city
    network.getCity(path[path.size()-2])->highlightSpecial();

    state = BEFORE_CITY_SELECTION;
}

void Player::moveNextCity(float deltaTime) {
    cityBeasts = *network.getCity(path.front())->getBeasts();
    numCityBeasts = cityBeasts.beasts.size();

    state = MOVING_ANIMATION;
}

void Player::movingAnimation(float deltaTime) {
    state = IN_BATTLE;
}

void Player::inBattle(float deltaTime) {
    BattleManager::resolveBattle(&beasts, &cityBeasts);
    state = BATTLE_ANIMATION;
    timer = 0;
}

/**
 * Decrements numBeasts and numCityBeasts until they
 * reach the respective beasts.size()
 */
void Player::battleAnimation(float deltaTime) {
     timer += deltaTime;

     if (timer > 0.2f) {
         timer = 0;
         int deltaBeasts = (int)std::ceil((numBeasts - beasts.beasts.size())/7.0);
         int deltaCityBeasts = (int)std::ceil((numCityBeasts - cityBeasts.beasts.size())/7.0);

         numBeasts -= deltaBeasts;
         numCityBeasts -= deltaCityBeasts;

         if(deltaBeasts <= 0 && deltaCityBeasts <= 0) {
             state = BATTLE_RESULT;
         }
     }
}

void Player::battleResult(float deltaTime) {
    if(beasts.beasts.size() <= 0) {
        state = ROUND_RESULT;
    } else {
        network.getCity(path.front())->destroy();
        path.erase(path.begin());
        if (path.size() > 0) {
            state = MOVE_NEXT_CITY;
        }
        else {
            state = ROUND_RESULT;
        }
    }
}

void Player::roundResult(float deltaTime) {
    upgradePoints += (pathInitialLength - path.size())*10;
}
<commit_msg>fixed last city selected to not be highlighted<commit_after>#include "Player.h"
#include "Resources.h"
#include "Utils.h"
#include "Network.h"
#include <cmath>
#include "LD32.h"

Player::Player(Game* game)
    : Object(game, sf::Vector2f(50, 50), Resources::texturePlayer, sf::Vector2i(2, 1)),
    network(game), game(game)
{
    mapInput();
    state = SELECT_BEAST;
    timer = 0;
}

Player::~Player()
{
}

void Player::mapInput() {
    inputManager->addMouseMapping(sf::Mouse::Button::Left);
}

void Player::update(float deltaTime) {
    network.update();
    switch(state) {

    case START_MENU:
        startMenu(deltaTime);
        break;
    case SELECT_BEAST:
        selectBeast(deltaTime);
        break;
    case UPGRADE_BEAST:
        upgradeBeast(deltaTime);
        break;
    case CITIES_INITIALITZATION:
        citiesInitialitzation(deltaTime);
        break;
    case BEFORE_CITY_SELECTION:
        beforeCitySelection(deltaTime);
        break;
    case CITY_SELECTION:
        citySelection(deltaTime);
        break;
    case AFTER_CITY_SELECTION:
        afterCitySelection(deltaTime);
        break;
    case MOVE_NEXT_CITY:
        moveNextCity(deltaTime);
        break;
    case MOVING_ANIMATION:
        movingAnimation(deltaTime);
        break;
    case IN_BATTLE:
        inBattle(deltaTime);
        break;
    case BATTLE_ANIMATION:
        battleAnimation(deltaTime);
        break;
    case BATTLE_RESULT:
        battleResult(deltaTime);
        break;
    case ROUND_RESULT:
        roundResult(deltaTime);
        break;
    default:
        break;
    }

}

void Player::draw() {
    network.draw();

    sf::Text text;
    text.setFont(Resources::font);
    text.setString(std::to_string(numBeasts));
    text.setCharacterSize(24);
    text.setPosition(sf::Vector2f(50, 50));

    game->getWindow()->draw(text);

    text.setFont(Resources::font);
    text.setString(std::to_string(numCityBeasts));
    text.setCharacterSize(24);
    text.setPosition(sf::Vector2f(50, 100));

    game->getWindow()->draw(text);
}

void Player::startMenu(float deltaTime) {

}

void Player::selectBeast(float deltaTime) {
    numBeasts = 10;
    beasts = Beasts(game, numBeasts, 10, 10, 10, 10, 10);
    state = UPGRADE_BEAST;
}

void Player::upgradeBeast(float deltaTime) {
    state = CITIES_INITIALITZATION;
}

void Player::citiesInitialitzation(float deltaTime) {
    network.addPath(0,1);
    network.addPath(1,3);
    network.addPath(3,2);
    network.addPath(2,4);
    network.addPath(2,5);
    network.addPath(4,5);
    network.addPath(2, 6);
    network.addPath(3, 9);
    network.addPath(6, 7);
    network.addPath(6, 12);
    network.addPath(7, 8);
    network.addPath(7, 9);
    network.addPath(9, 10);
    network.addPath(10, 11);
    network.addPath(11, 12);

    path.clear();
    path.push_back(0);
    network.getCity(0)->highlightSpecial();

    state = BEFORE_CITY_SELECTION;
}

void Player::beforeCitySelection(float deltaTime) {
    currentNeighbours = network.getNeighbours(path.back());

    if (currentNeighbours.size() <= 0) {
        pathInitialLength = path.size();
        state = MOVE_NEXT_CITY;
        return;
    }

    //Highlight neighbours
    std::vector<int>::iterator it = currentNeighbours.begin();
    for (; it != currentNeighbours.end(); it++) {
        network.getCity(*it)->highlight();
    }

    state = CITY_SELECTION;
}

void Player::citySelection(float deltaTime) {
    if (inputManager->getMouseState(sf::Mouse::Button::Left) == true) {
        sf::Vector2f mousePos = sf::Vector2f(inputManager->getMousePosition().x, inputManager->getMousePosition().y);
        int result = network.getCityByCoords(mousePos);
        bool inNeighbours = false;

        for (std::vector<int>::iterator it = currentNeighbours.begin(); it != currentNeighbours.end(); it++) {
            if (*it == result) {
                inNeighbours = true;
                break;
            }
        }

        if (inNeighbours) {
            network.destroyNode(path.back());
            path.push_back(result);
            state = AFTER_CITY_SELECTION;
        }
    }
}

void Player::afterCitySelection(float deltaTime) {
    //Unhighlight neighbours
    std::vector<int>::iterator it = currentNeighbours.begin();

    for (; it != currentNeighbours.end(); it++) {
        network.getCity(*it)->unHighlight();
    }

    //Highlight special selected city
    network.getCity(path[path.size()-1])->highlightSpecial();

    state = BEFORE_CITY_SELECTION;
}

void Player::moveNextCity(float deltaTime) {
    cityBeasts = *network.getCity(path.front())->getBeasts();
    numCityBeasts = cityBeasts.beasts.size();

    state = MOVING_ANIMATION;
}

void Player::movingAnimation(float deltaTime) {
    state = IN_BATTLE;
}

void Player::inBattle(float deltaTime) {
    BattleManager::resolveBattle(&beasts, &cityBeasts);
    state = BATTLE_ANIMATION;
    timer = 0;
}

/**
 * Decrements numBeasts and numCityBeasts until they
 * reach the respective beasts.size()
 */
void Player::battleAnimation(float deltaTime) {
     timer += deltaTime;

     if (timer > 0.2f) {
         timer = 0;
         int deltaBeasts = (int)std::ceil((numBeasts - beasts.beasts.size())/7.0);
         int deltaCityBeasts = (int)std::ceil((numCityBeasts - cityBeasts.beasts.size())/7.0);

         numBeasts -= deltaBeasts;
         numCityBeasts -= deltaCityBeasts;

         if(deltaBeasts <= 0 && deltaCityBeasts <= 0) {
             state = BATTLE_RESULT;
         }
     }
}

void Player::battleResult(float deltaTime) {
    if(beasts.beasts.size() <= 0) {
        state = ROUND_RESULT;
    } else {
        network.getCity(path.front())->destroy();
        path.erase(path.begin());
        if (path.size() > 0) {
            state = MOVE_NEXT_CITY;
        }
        else {
            state = ROUND_RESULT;
        }
    }
}

void Player::roundResult(float deltaTime) {
    upgradePoints += (pathInitialLength - path.size())*10;
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>

#include "base/not_null.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/named_quantities.hpp"
#include "numerics/polynomial.hpp"
#include "physics/oblate_body.hpp"
#include "quantities/named_quantities.hpp"

namespace principia {
namespace physics {
namespace internal_geopotential {

using base::not_null;
using geometry::Displacement;
using geometry::Instant;
using geometry::Vector;
using numerics::PolynomialInMonomialBasis;
using quantities::Acceleration;
using quantities::Angle;
using quantities::Exponentiation;
using quantities::GravitationalParameter;
using quantities::Infinity;
using quantities::Inverse;
using quantities::Length;
using quantities::Quotient;
using quantities::Square;

// Specification of the damping of a spherical harmonic, acting as a radial
// multiplier on the potential:
//   V_damped = σ(‖r‖) V(r).
class HarmonicDamping final {
 public:
  HarmonicDamping() = default;
  explicit HarmonicDamping(Length const& inner_threshold);

  // Above this threshold, the contribution to the potential from this
  // harmonic is 0, i.e., σ = 0.
  Length const& outer_threshold() const;
  // Below this threshold, the contribution to the potential from this
  // harmonic is undamped, σ = 1.
  // This class depends on the invariant: outer_threshold = 3 * inner_threshold.
  Length const& inner_threshold() const;

  // Sets σℜ_over_r and grad_σℜ according to σ as defined by |*this|.
  template<typename Frame>
  void ComputeDampedRadialQuantities(
      Length const& r_norm,
      Square<Length> const& r²,
      Vector<double, Frame> const& r_normalized,
      Inverse<Square<Length>> const& ℜ_over_r,
      Inverse<Square<Length>> const& ℜʹ,
      Inverse<Square<Length>>& σℜ_over_r,
      Vector<Inverse<Square<Length>>, Frame>& grad_σℜ) const;

 private:
  Length outer_threshold_ = Infinity<Length>();
  Length inner_threshold_ = Infinity<Length>();

  // For r in [outer_threshold, inner_threshold], σ is a polynomial with the
  // following coefficients in monomial basis.
  // The constant term is always 0, and is thus ignored in the evaluation.
  // TODO(phl): We have to specify an evaluator, but we do not use it; we use a
  // custom evaluation that ignores the constant term instead.  See #1922.
  PolynomialInMonomialBasis<
      double, Length, 4,
      numerics::EstrinEvaluator>::Coefficients sigmoid_coefficients_;
};

// Representation of the geopotential model of an oblate body.
template<typename Frame>
class Geopotential {
 public:
  // Spherical harmonics will not be damped if their contribution to the radial
  // force exceeds |tolerance| times the central force.
  Geopotential(not_null<OblateBody<Frame> const*> body,
               double tolerance);

  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  SphericalHarmonicsAcceleration(
      Instant const& t,
      Displacement<Frame> const& r,
      Square<Length> const& r²,
      Exponentiation<Length, -3> const& one_over_r³) const;

  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  GeneralSphericalHarmonicsAcceleration(
      Instant const& t,
      Displacement<Frame> const& r,
      Length const& r_norm,
      Square<Length> const& r²,
      Exponentiation<Length, -3> const& one_over_r³) const;

 private:
  // The frame of the surface of the celestial.
  struct SurfaceFrame;
  static const Vector<double, SurfaceFrame> x_;
  static const Vector<double, SurfaceFrame> y_;

  // This is the type that we return, so better have a name for it.
  using ReducedAcceleration = Quotient<Acceleration, GravitationalParameter>;

  // List of reduced accelerations computed for all degrees or orders.
  template<int size>
  using ReducedAccelerations =
      std::array<Vector<ReducedAcceleration, Frame>, size>;

  using UnitVector = Vector<double, Frame>;

  // Holds precomputed data for one evaluation of the acceleration.
  template<int size>
  struct Precomputations;

  // Helper templates for iterating over the degrees/orders of the geopotential.
  template<int size, int degree, int order>
  struct DegreeNOrderM;
  template<int size, int degree, typename>
  struct DegreeNAllOrders;
  template<typename>
  struct AllDegrees;

  // If z is a unit vector along the axis of rotation, and r a vector from the
  // center of |body_| to some point in space, the acceleration computed here
  // is:
  //
  //   -(J₂ / (μ ‖r‖⁵)) (3 z (r.z) + r (3 - 15 (r.z)² / ‖r‖²) / 2)
  //
  // Where ‖r‖ is the norm of r and r.z is the inner product.  It is the
  // additional acceleration exerted by the oblateness of |body| on a point at
  // position r.  J₂, J̃₂ and J̄₂ are normally positive and C̃₂₀ and C̄₂₀ negative
  // because the planets are oblate, not prolate.  Note that this follows IERS
  // Technical Note 36 and it differs from
  // https://en.wikipedia.org/wiki/Geopotential_model which seems to want J̃₂ to
  // be negative.
  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  Degree2ZonalAcceleration(UnitVector const& axis,
                           Displacement<Frame> const& r,
                           Exponentiation<Length, -2> const& one_over_r²,
                           Exponentiation<Length, -3> const& one_over_r³) const;

  not_null<OblateBody<Frame> const*> body_;

  // The contribution from the harmonics of degree n is damped by
  // degree_damping_[n].
  // degree_damping_[0] and degree_damping_[1] have infinite thresholds, and are
  // not used (this class does not compute the central force and disregards
  // degree 1, which is equivalent to a translation of the centre of mass).
  std::vector<HarmonicDamping> degree_damping_;

  // The contribution of low-degree tesseral (including sectoral) harmonics is
  // damped by |tesseral_damping_|.
  HarmonicDamping tesseral_damping_;

  // |first_tesseral_degree_| is the integer n such that
  //   degree_damping_[n-1].outer_threshold >= tesseral_damping_.outer_threshold
  // and
  //   tesseral_damping_.outer_threshold > degree_damping_[n].outer_threshold,
  // or is |degree_damping_.size()| if
  // |tesseral_threshold_ <= degree_threshold_[n]| for all n.
  // Tesseral (including sectoral) harmonics of degree less than
  // |first_tesseral_degree_| are damped by |tesseral_damping_|, instead
  // of their respective |degree_damping_|.
  int first_tesseral_degree_;
};

}  // namespace internal_geopotential

using internal_geopotential::Geopotential;

}  // namespace physics
}  // namespace principia

#include "physics/geopotential_body.hpp"
<commit_msg>off-by-one<commit_after>#pragma once

#include <vector>

#include "base/not_null.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/named_quantities.hpp"
#include "numerics/polynomial.hpp"
#include "physics/oblate_body.hpp"
#include "quantities/named_quantities.hpp"

namespace principia {
namespace physics {
namespace internal_geopotential {

using base::not_null;
using geometry::Displacement;
using geometry::Instant;
using geometry::Vector;
using numerics::PolynomialInMonomialBasis;
using quantities::Acceleration;
using quantities::Angle;
using quantities::Exponentiation;
using quantities::GravitationalParameter;
using quantities::Infinity;
using quantities::Inverse;
using quantities::Length;
using quantities::Quotient;
using quantities::Square;

// Specification of the damping of a spherical harmonic, acting as a radial
// multiplier on the potential:
//   V_damped = σ(‖r‖) V(r).
class HarmonicDamping final {
 public:
  HarmonicDamping() = default;
  explicit HarmonicDamping(Length const& inner_threshold);

  // Above this threshold, the contribution to the potential from this
  // harmonic is 0, i.e., σ = 0.
  Length const& outer_threshold() const;
  // Below this threshold, the contribution to the potential from this
  // harmonic is undamped, σ = 1.
  // This class depends on the invariant: outer_threshold = 3 * inner_threshold.
  Length const& inner_threshold() const;

  // Sets σℜ_over_r and grad_σℜ according to σ as defined by |*this|.
  template<typename Frame>
  void ComputeDampedRadialQuantities(
      Length const& r_norm,
      Square<Length> const& r²,
      Vector<double, Frame> const& r_normalized,
      Inverse<Square<Length>> const& ℜ_over_r,
      Inverse<Square<Length>> const& ℜʹ,
      Inverse<Square<Length>>& σℜ_over_r,
      Vector<Inverse<Square<Length>>, Frame>& grad_σℜ) const;

 private:
  Length outer_threshold_ = Infinity<Length>();
  Length inner_threshold_ = Infinity<Length>();

  // For r in [outer_threshold, inner_threshold], σ is a polynomial with the
  // following coefficients in monomial basis.
  // The constant term is always 0, and is thus ignored in the evaluation.
  // TODO(phl): We have to specify an evaluator, but we do not use it; we use a
  // custom evaluation that ignores the constant term instead.  See #1922.
  PolynomialInMonomialBasis<
      double, Length, 3,
      numerics::EstrinEvaluator>::Coefficients sigmoid_coefficients_;
};

// Representation of the geopotential model of an oblate body.
template<typename Frame>
class Geopotential {
 public:
  // Spherical harmonics will not be damped if their contribution to the radial
  // force exceeds |tolerance| times the central force.
  Geopotential(not_null<OblateBody<Frame> const*> body,
               double tolerance);

  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  SphericalHarmonicsAcceleration(
      Instant const& t,
      Displacement<Frame> const& r,
      Square<Length> const& r²,
      Exponentiation<Length, -3> const& one_over_r³) const;

  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  GeneralSphericalHarmonicsAcceleration(
      Instant const& t,
      Displacement<Frame> const& r,
      Length const& r_norm,
      Square<Length> const& r²,
      Exponentiation<Length, -3> const& one_over_r³) const;

 private:
  // The frame of the surface of the celestial.
  struct SurfaceFrame;
  static const Vector<double, SurfaceFrame> x_;
  static const Vector<double, SurfaceFrame> y_;

  // This is the type that we return, so better have a name for it.
  using ReducedAcceleration = Quotient<Acceleration, GravitationalParameter>;

  // List of reduced accelerations computed for all degrees or orders.
  template<int size>
  using ReducedAccelerations =
      std::array<Vector<ReducedAcceleration, Frame>, size>;

  using UnitVector = Vector<double, Frame>;

  // Holds precomputed data for one evaluation of the acceleration.
  template<int size>
  struct Precomputations;

  // Helper templates for iterating over the degrees/orders of the geopotential.
  template<int size, int degree, int order>
  struct DegreeNOrderM;
  template<int size, int degree, typename>
  struct DegreeNAllOrders;
  template<typename>
  struct AllDegrees;

  // If z is a unit vector along the axis of rotation, and r a vector from the
  // center of |body_| to some point in space, the acceleration computed here
  // is:
  //
  //   -(J₂ / (μ ‖r‖⁵)) (3 z (r.z) + r (3 - 15 (r.z)² / ‖r‖²) / 2)
  //
  // Where ‖r‖ is the norm of r and r.z is the inner product.  It is the
  // additional acceleration exerted by the oblateness of |body| on a point at
  // position r.  J₂, J̃₂ and J̄₂ are normally positive and C̃₂₀ and C̄₂₀ negative
  // because the planets are oblate, not prolate.  Note that this follows IERS
  // Technical Note 36 and it differs from
  // https://en.wikipedia.org/wiki/Geopotential_model which seems to want J̃₂ to
  // be negative.
  Vector<Quotient<Acceleration, GravitationalParameter>, Frame>
  Degree2ZonalAcceleration(UnitVector const& axis,
                           Displacement<Frame> const& r,
                           Exponentiation<Length, -2> const& one_over_r²,
                           Exponentiation<Length, -3> const& one_over_r³) const;

  not_null<OblateBody<Frame> const*> body_;

  // The contribution from the harmonics of degree n is damped by
  // degree_damping_[n].
  // degree_damping_[0] and degree_damping_[1] have infinite thresholds, and are
  // not used (this class does not compute the central force and disregards
  // degree 1, which is equivalent to a translation of the centre of mass).
  std::vector<HarmonicDamping> degree_damping_;

  // The contribution of low-degree tesseral (including sectoral) harmonics is
  // damped by |tesseral_damping_|.
  HarmonicDamping tesseral_damping_;

  // |first_tesseral_degree_| is the integer n such that
  //   degree_damping_[n-1].outer_threshold >= tesseral_damping_.outer_threshold
  // and
  //   tesseral_damping_.outer_threshold > degree_damping_[n].outer_threshold,
  // or is |degree_damping_.size()| if
  // |tesseral_threshold_ <= degree_threshold_[n]| for all n.
  // Tesseral (including sectoral) harmonics of degree less than
  // |first_tesseral_degree_| are damped by |tesseral_damping_|, instead
  // of their respective |degree_damping_|.
  int first_tesseral_degree_;
};

}  // namespace internal_geopotential

using internal_geopotential::Geopotential;

}  // namespace physics
}  // namespace principia

#include "physics/geopotential_body.hpp"
<|endoftext|>


<commit_before>#include "parser.h"

Parser::Parser(Scanner scanner){
  _scanner = scanner;
}
Term* Parser::createTerm(){
  int token = _scanner.nextToken();
  //std::cout << _scanner.position() << '\n';
  //std::cout << token << '\n';
  if(token == VAR) {
    return new Variable(symtable[_scanner.tokenValue()].first);
  } else if(token == NUMBER) {
    return new Number(_scanner.tokenValue());
  } else if(token == ATOM) {
      Atom* atom = new Atom(symtable[_scanner.tokenValue()].first);
      if(_scanner.currentChar() == '('){
        _scanner.nextToken();
        vector<Term *> terms = getArgs();
        if(_currentToken == ')')
         return new Struct(*atom,terms);
      }else{
        return atom;
      }
  } else if(token == 91){
    //std::cout << _scanner.position() << '\n';
    if(_scanner.nextToken() == 93)
      return new List();
  } else {
      return NULL;
    }
}

vector<Term *> Parser::getArgs(){
      Term* term = createTerm();
      vector<Term *> args;
      args.push_back(term);
      while((_currentToken = _scanner.nextToken()) == ','){
        args.push_back(createTerm());
      }
      return args;
}
<commit_msg>Delete Parser.cpp<commit_after><|endoftext|>


<commit_before>#include "Parser.h"

#include <llvm/Config/config.h>
#include <llvm/Support/MemoryBuffer.h>

#include <clang/AST/ASTConsumer.h>
#include <clang/Driver/InitHeaderSearch.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>

using std::string;

namespace ccons {

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

Parser::~Parser()
{
}

clang::Preprocessor * Parser::parse(string source, clang::Diagnostic *diag, clang::ASTConsumer *consumer)
{
	llvm::MemoryBuffer *mb = llvm::MemoryBuffer::getMemBufferCopy(&*source.begin(), &*source.end(), "Main");
	assert(mb);
	clang::SourceManager sm;
	sm.createMainFileIDForMemBuffer(mb);
	assert(sm.getMainFileID());
	clang::HeaderSearch headers(_fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();
	clang::Preprocessor *pp = new clang::Preprocessor(*diag, _options, *_target, sm, headers);
	clang::ParseAST(*pp, consumer, /* PrintStats = */ false, /* FreeMemory = */ false);
	return pp;
}

} // namespace ccons
<commit_msg>update parser to compile with latest changes to clang<commit_after>#include "Parser.h"

#include <llvm/Config/config.h>
#include <llvm/Support/MemoryBuffer.h>

#include <clang/AST/ASTConsumer.h>
#include <clang/Driver/InitHeaderSearch.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Sema/ParseAST.h>

using std::string;

namespace ccons {

Parser::Parser(const clang::LangOptions& options) :
	_options(options),
	_target(clang::TargetInfo::CreateTargetInfo(LLVM_HOSTTRIPLE))
{
}

Parser::~Parser()
{
}

clang::Preprocessor * Parser::parse(string source, clang::Diagnostic *diag, clang::ASTConsumer *consumer)
{
	llvm::MemoryBuffer *mb = llvm::MemoryBuffer::getMemBufferCopy(&*source.begin(), &*source.end(), "Main");
	assert(mb);
	clang::SourceManager sm;
	sm.createMainFileIDForMemBuffer(mb);
	assert(sm.getMainFileID());
	clang::HeaderSearch headers(_fm);
	clang::InitHeaderSearch ihs(headers);
	ihs.AddDefaultEnvVarPaths(_options);
	ihs.AddDefaultSystemIncludePaths(_options);
	ihs.Realize();
	clang::Preprocessor *pp = new clang::Preprocessor(*diag, _options, *_target, sm, headers, NULL);
	clang::ParseAST(*pp, consumer, /* PrintStats = */ false, /* FreeMemory = */ false);
	return pp;
}

} // namespace ccons
<|endoftext|>


<commit_before>// InteractiveNotifications.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "InteractiveNotifications.h"
#include <NotificationActivationCallback.h>

#include <Shellapi.h>
#include <string>
#include <iostream>
#include <SDKDDKVer.h>
#include <Windows.h>
#include <Psapi.h>
#include <strsafe.h>
#include <ShObjIdl.h>
#include <Shlobj.h>
#include <Pathcch.h>
#include <propvarutil.h>
#include <propkey.h>
#include <wchar.h>
#include <wrl.h>
#include <wrl\wrappers\corewrappers.h>
#include <windows.ui.notifications.h>

// Correct flow
// RegisterAppForNotificationSupport()
// RegisterActivator()

//  Name:     System.AppUserModel.ToastActivatorCLSID -- PKEY_AppUserModel_ToastActivatorCLSID
//  Type:     Guid -- VT_CLSID
//  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 26
//
//  Used to CoCreate an INotificationActivationCallback interface to notify about toast activations.
EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY PKEY_AppUserModel_ToastActivatorCLSID = { { 0x9F4C2855, 0x9F79, 0x4B39,{ 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 26 };

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

struct CoTaskMemStringTraits
{
	typedef PWSTR Type;

	inline static bool Close(_In_ Type h) throw() { ::CoTaskMemFree(h); return true; }

	inline static Type GetInvalidValue() throw() { return nullptr; }
};
typedef HandleT<CoTaskMemStringTraits> CoTaskMemString;

const wchar_t Shortcut[] = LR"(Microsoft\Windows\Start Menu\Slack.lnk)";

#define __CSID "F4B2D0CA-5D93-41CF-9A4C-721782B3246F"

// For the app to be activated from Action Center, it needs to provide a COM server to be called
// when the notification is activated.  The CLSID of the object needs to be registered with the
// OS via its shortcut so that it knows who to call later.
class DECLSPEC_UUID(__CSID) NotificationActivator WrlSealed WrlFinal
: public RuntimeClass < RuntimeClassFlags<ClassicCom>,
	INotificationActivationCallback >
{
public:
	virtual HRESULT STDMETHODCALLTYPE Activate(
		_In_ LPCWSTR appUserModelId,
		_In_ LPCWSTR invokedArgs,
		_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
		ULONG dataCount) override
	{
		std::string args;

		for (int i = 0; i < dataCount; i++) {
			LPCWSTR lvalue = data[i].Value;
			LPCWSTR lkey = data[i].Key;

			std::wstring wvalue(lvalue);
			std::wstring wkey(lkey);

			std::string value(wvalue.begin(), wvalue.end());
			std::string key(wkey.begin(), wkey.end());

			args = args + "\"key\":\"" + key + "\"";
			args = args + ",\"value\":\"" + value + "\"";
		}

		std::string escapedArgs = "";
		for (char ch : args) {
			switch (ch) {
			case ' ': escapedArgs += "%20"; break;
			case '&': escapedArgs += "^&"; break;
			case '\\': escapedArgs += "^\\"; break;
			case '<': escapedArgs += "^<"; break;
			case '>': escapedArgs += "^>"; break;
			case '|': escapedArgs += "^|"; break;
			case '^': escapedArgs += "^^"; break;
			case '"': escapedArgs += "^%22"; break;
			default: escapedArgs += ch; break;
			}
		}

		std::wstring wToastArgs(invokedArgs);
		std::string toastArgs(wToastArgs.begin(), wToastArgs.end());

		// CMD needs stuff escaped, so we'll do that here
		std::string escapedToastArgs = "";
		for (char ch : toastArgs) {
			switch (ch) {
			case ' ': escapedToastArgs += "%20"; break;
			case '&': escapedToastArgs += "^&"; break;
			case '\\': escapedToastArgs += "^\\"; break;
			case '<': escapedToastArgs += "^<"; break;
			case '>': escapedToastArgs += "^>"; break;
			case '|': escapedToastArgs += "^|"; break;
			case '^': escapedToastArgs += "^^"; break;
			case '"': escapedToastArgs += "%22"; break;
			default: escapedToastArgs += ch; break;
			}
		}

		std::string cmdLine = "cmd.exe \"start slack://" + escapedToastArgs + "^&userData=[{" + escapedArgs + "}]\"";
		WinExec(cmdLine.c_str(), SW_HIDE);

		return HRESULT();
	}
};
CoCreatableClass(NotificationActivator);

namespace InteractiveNotifications
{
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterAppForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		CoTaskMemString appData;
		auto hr = ::SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, appData.GetAddressOf());

		if (SUCCEEDED(hr))
		{
			wchar_t shortcutPath[MAX_PATH];
			// Todo: Don't hardcode the path
			hr = ::PathCchCombine(shortcutPath, ARRAYSIZE(shortcutPath), appData.Get(), shortcut);

			if (SUCCEEDED(hr))
			{
				DWORD attributes = ::GetFileAttributes(shortcutPath);
				bool fileExists = attributes < 0xFFFFFFF;

				if (!fileExists)
				{
					// Todo: This is probably the wrong path bc Squirrel
					wchar_t exePath[MAX_PATH];
					DWORD charWritten = ::GetModuleFileName(nullptr, exePath, ARRAYSIZE(exePath));
					hr = charWritten > 0 ? S_OK : HRESULT_FROM_WIN32(::GetLastError());

					if (SUCCEEDED(hr))
					{
						hr = InstallShortcut(shortcutPath, exePath, appId);
						if (SUCCEEDED(hr))
						{
							hr = RegisterComServer(exePath);
						}
					}
				}
			}
		}
		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT InstallShortcut(PCWSTR shortcutPath, PCWSTR exePath, PCWSTR appId)
	{
		ComPtr<IShellLink> shellLink;
		HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));

		if (!SUCCEEDED(hr)) return hr;
		hr = shellLink->SetPath(exePath);

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPropertyStore> propertyStore;
		hr = shellLink.As(&propertyStore);

		if (!SUCCEEDED(hr)) return hr;
		PROPVARIANT propVar;
		propVar.vt = VT_LPWSTR;
		propVar.pwszVal = const_cast<PWSTR>(appId); // for _In_ scenarios, we don't need a copy
		hr = propertyStore->SetValue(PKEY_AppUserModel_ID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		propVar.vt = VT_CLSID;
		propVar.puuid = const_cast<CLSID*>(&__uuidof(NotificationActivator));
		hr = propertyStore->SetValue(PKEY_AppUserModel_ToastActivatorCLSID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		hr = propertyStore->Commit();

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPersistFile> persistFile;
		hr = shellLink.As(&persistFile);

		if (!SUCCEEDED(hr)) return hr;
		hr = persistFile->Save(shortcutPath, TRUE);

		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterComServer(PCWSTR exePath)
	{
		// We don't need to worry about overflow here as ::GetModuleFileName won't
		// return anything bigger than the max file system path (much fewer than max of DWORD).
		DWORD dataSize = static_cast<DWORD>((::wcslen(exePath) + 1) * sizeof(WCHAR));
		auto key = LR"(SOFTWARE\Classes\CLSID\{F4B2D0CA-5D93-41CF-9A4C-721782B3246F}\LocalServer32)";

		return HRESULT_FROM_WIN32(::RegSetKeyValue(
			HKEY_CURRENT_USER,
			key,
			nullptr,
			REG_SZ,
			reinterpret_cast<const BYTE*>(exePath),
			dataSize));
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterActivator()
	{
		// Module<OutOfProc> needs a callback registered before it can be used.
		// Since we don't care about when it shuts down, we'll pass an empty lambda here.
		// If we need to clean up, do it here (we probably don't have to)
		Module<OutOfProc>::Create([] {});

		// If a local server process only hosts the COM object then COM expects
		// the COM server host to shutdown when the references drop to zero.
		// Since the user might still be using the program after activating the notification,
		// we don't want to shutdown immediately.  Incrementing the object count tells COM that
		// we aren't done yet.
		Module<OutOfProc>::GetModule().IncrementObjectCount();

		return Module<OutOfProc>::GetModule().RegisterObjects();
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API void UnregisterActivator()
	{
		Module<OutOfProc>::GetModule().UnregisterObjects();
		Module<OutOfProc>::GetModule().DecrementObjectCount();
	}
}

extern "C"
{
	__declspec(dllexport) void CRegisterForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		InteractiveNotifications::RegisterAppForNotificationSupport(shortcut, appId);
	}

	__declspec(dllexport) void CRegisterActivator()
	{
		InteractiveNotifications::RegisterActivator();
	}

	__declspec(dllexport) void CUnregisterActivator()
	{
		InteractiveNotifications::UnregisterActivator();
	}
}<commit_msg>:hocho: New GUID<commit_after>// InteractiveNotifications.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "InteractiveNotifications.h"
#include <NotificationActivationCallback.h>

#include <Shellapi.h>
#include <string>
#include <iostream>
#include <SDKDDKVer.h>
#include <Windows.h>
#include <Psapi.h>
#include <strsafe.h>
#include <ShObjIdl.h>
#include <Shlobj.h>
#include <Pathcch.h>
#include <propvarutil.h>
#include <propkey.h>
#include <wchar.h>
#include <wrl.h>
#include <wrl\wrappers\corewrappers.h>
#include <windows.ui.notifications.h>

// Correct flow
// RegisterAppForNotificationSupport()
// RegisterActivator()

//  Name:     System.AppUserModel.ToastActivatorCLSID -- PKEY_AppUserModel_ToastActivatorCLSID
//  Type:     Guid -- VT_CLSID
//  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 26
//
//  Used to CoCreate an INotificationActivationCallback interface to notify about toast activations.
EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY PKEY_AppUserModel_ToastActivatorCLSID = { { 0x9F4C2855, 0x9F79, 0x4B39,{ 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 26 };

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

struct CoTaskMemStringTraits
{
	typedef PWSTR Type;

	inline static bool Close(_In_ Type h) throw() { ::CoTaskMemFree(h); return true; }

	inline static Type GetInvalidValue() throw() { return nullptr; }
};
typedef HandleT<CoTaskMemStringTraits> CoTaskMemString;

const wchar_t Shortcut[] = LR"(Microsoft\Windows\Start Menu\Slack.lnk)";

#define __CSID "A23D2B18-8DD7-403A-B9B7-152B40A1478C"

// For the app to be activated from Action Center, it needs to provide a COM server to be called
// when the notification is activated.  The CLSID of the object needs to be registered with the
// OS via its shortcut so that it knows who to call later.
class DECLSPEC_UUID(__CSID) NotificationActivator WrlSealed WrlFinal
: public RuntimeClass < RuntimeClassFlags<ClassicCom>,
	INotificationActivationCallback >
{
public:
	virtual HRESULT STDMETHODCALLTYPE Activate(
		_In_ LPCWSTR appUserModelId,
		_In_ LPCWSTR invokedArgs,
		_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
		ULONG dataCount) override
	{
		std::string args;

		for (int i = 0; i < dataCount; i++) {
			LPCWSTR lvalue = data[i].Value;
			LPCWSTR lkey = data[i].Key;

			std::wstring wvalue(lvalue);
			std::wstring wkey(lkey);

			std::string value(wvalue.begin(), wvalue.end());
			std::string key(wkey.begin(), wkey.end());

			args = args + "\"key\":\"" + key + "\"";
			args = args + ",\"value\":\"" + value + "\"";
		}

		std::string escapedArgs = "";
		for (char ch : args) {
			switch (ch) {
			case ' ': escapedArgs += "%20"; break;
			case '&': escapedArgs += "^&"; break;
			case '\\': escapedArgs += "^\\"; break;
			case '<': escapedArgs += "^<"; break;
			case '>': escapedArgs += "^>"; break;
			case '|': escapedArgs += "^|"; break;
			case '^': escapedArgs += "^^"; break;
			case '"': escapedArgs += "^%22"; break;
			default: escapedArgs += ch; break;
			}
		}

		std::wstring wToastArgs(invokedArgs);
		std::string toastArgs(wToastArgs.begin(), wToastArgs.end());

		// CMD needs stuff escaped, so we'll do that here
		std::string escapedToastArgs = "";
		for (char ch : toastArgs) {
			switch (ch) {
			case ' ': escapedToastArgs += "%20"; break;
			case '&': escapedToastArgs += "^&"; break;
			case '\\': escapedToastArgs += "^\\"; break;
			case '<': escapedToastArgs += "^<"; break;
			case '>': escapedToastArgs += "^>"; break;
			case '|': escapedToastArgs += "^|"; break;
			case '^': escapedToastArgs += "^^"; break;
			case '"': escapedToastArgs += "%22"; break;
			default: escapedToastArgs += ch; break;
			}
		}

		std::string cmdLine = "cmd.exe \"start slack://" + escapedToastArgs + "^&userData=[{" + escapedArgs + "}]\"";
		WinExec(cmdLine.c_str(), SW_HIDE);

		return HRESULT();
	}
};
CoCreatableClass(NotificationActivator);

namespace InteractiveNotifications
{
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterAppForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		CoTaskMemString appData;
		auto hr = ::SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, appData.GetAddressOf());

		if (SUCCEEDED(hr))
		{
			wchar_t shortcutPath[MAX_PATH];
			// Todo: Don't hardcode the path
			hr = ::PathCchCombine(shortcutPath, ARRAYSIZE(shortcutPath), appData.Get(), shortcut);

			if (SUCCEEDED(hr))
			{
				DWORD attributes = ::GetFileAttributes(shortcutPath);
				bool fileExists = attributes < 0xFFFFFFF;

				if (!fileExists)
				{
					// Todo: This is probably the wrong path bc Squirrel
					wchar_t exePath[MAX_PATH];
					DWORD charWritten = ::GetModuleFileName(nullptr, exePath, ARRAYSIZE(exePath));
					hr = charWritten > 0 ? S_OK : HRESULT_FROM_WIN32(::GetLastError());

					if (SUCCEEDED(hr))
					{
						hr = InstallShortcut(shortcutPath, exePath, appId);
						if (SUCCEEDED(hr))
						{
							hr = RegisterComServer(exePath);
						}
					}
				}
			}
		}
		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT InstallShortcut(PCWSTR shortcutPath, PCWSTR exePath, PCWSTR appId)
	{
		ComPtr<IShellLink> shellLink;
		HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));

		if (!SUCCEEDED(hr)) return hr;
		hr = shellLink->SetPath(exePath);

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPropertyStore> propertyStore;
		hr = shellLink.As(&propertyStore);

		if (!SUCCEEDED(hr)) return hr;
		PROPVARIANT propVar;
		propVar.vt = VT_LPWSTR;
		propVar.pwszVal = const_cast<PWSTR>(appId); // for _In_ scenarios, we don't need a copy
		hr = propertyStore->SetValue(PKEY_AppUserModel_ID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		propVar.vt = VT_CLSID;
		propVar.puuid = const_cast<CLSID*>(&__uuidof(NotificationActivator));
		hr = propertyStore->SetValue(PKEY_AppUserModel_ToastActivatorCLSID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		hr = propertyStore->Commit();

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPersistFile> persistFile;
		hr = shellLink.As(&persistFile);

		if (!SUCCEEDED(hr)) return hr;
		hr = persistFile->Save(shortcutPath, TRUE);

		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterComServer(PCWSTR exePath)
	{
		// We don't need to worry about overflow here as ::GetModuleFileName won't
		// return anything bigger than the max file system path (much fewer than max of DWORD).
		DWORD dataSize = static_cast<DWORD>((::wcslen(exePath) + 1) * sizeof(WCHAR));
		auto key = LR"(SOFTWARE\Classes\CLSID\{A23D2B18-8DD7-403A-B9B7-152B40A1478C}\LocalServer32)";

		return HRESULT_FROM_WIN32(::RegSetKeyValue(
			HKEY_CURRENT_USER,
			key,
			nullptr,
			REG_SZ,
			reinterpret_cast<const BYTE*>(exePath),
			dataSize));
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterActivator()
	{
		// Module<OutOfProc> needs a callback registered before it can be used.
		// Since we don't care about when it shuts down, we'll pass an empty lambda here.
		// If we need to clean up, do it here (we probably don't have to)
		Module<OutOfProc>::Create([] {});

		// If a local server process only hosts the COM object then COM expects
		// the COM server host to shutdown when the references drop to zero.
		// Since the user might still be using the program after activating the notification,
		// we don't want to shutdown immediately.  Incrementing the object count tells COM that
		// we aren't done yet.
		Module<OutOfProc>::GetModule().IncrementObjectCount();

		return Module<OutOfProc>::GetModule().RegisterObjects();
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API void UnregisterActivator()
	{
		Module<OutOfProc>::GetModule().UnregisterObjects();
		Module<OutOfProc>::GetModule().DecrementObjectCount();
	}
}

extern "C"
{
	__declspec(dllexport) void CRegisterForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		InteractiveNotifications::RegisterAppForNotificationSupport(shortcut, appId);
	}

	__declspec(dllexport) void CRegisterActivator()
	{
		InteractiveNotifications::RegisterActivator();
	}

	__declspec(dllexport) void CUnregisterActivator()
	{
		InteractiveNotifications::UnregisterActivator();
	}
}<|endoftext|>