<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#ifndef HAVE_PTRDIFF_T
#error Cannot compile without ptrdiff_t support
#endif

#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <tr1/memory>

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#include <curl/curl.h>

#include "hosthandler.h"
#include "hostfactory.h"
#include "macros.h"
#include "opts.h"
#include "curl.h"
#include "exec.h"
#include "retry.h"
#include "log.h"
#include "app.h"

#define SHP std::tr1::shared_ptr

// singleton instances
static SHP<OptionsMgr> __optsmgr (new OptionsMgr);
static SHP<CurlMgr>    __curlmgr (new CurlMgr);
static SHP<ExecMgr>    __execmgr (new ExecMgr);
static SHP<RetryMgr>   __retrymgr(new RetryMgr);
static SHP<LogMgr>     __logmgr  (new LogMgr);

extern void handle_sigwinch(int); // src/progress.cpp

App::~App() {
}

void
App::main(const int& argc, char * const *argv) {
    optsmgr.init(argc, argv);
    logmgr.init(); // apply --quiet
    curlmgr.init();
}

static void
printVideo(const VideoProperties& props) {
    logmgr.cout()
        << "file: "
        << props.getFilename()
        << "  "
        << std::setprecision(1)
        << _TOMB(props.getLength())
        << "M  ["
        << props.getContentType()
        << "]"
        << std::endl;
}

static void
printCSV(const VideoProperties& props) {
    std::cout.setf(std::ios::fixed);
    std::cout.unsetf(std::ios::showpoint);
    std::cout
        << "csv:\""
        << props.getFilename()
        << "\",\""
        << std::setprecision(0)
        << props.getLength()
        << "\",\""
        << props.getLink()
        << "\""
        << std::endl;
}

typedef CurlMgr::FetchException FetchError;

static void
fetchPage(SHP<HostHandler> handler,
          const std::string& url,
          const bool& reset=false)
{
    if (reset)
        retrymgr.reset();
    try   { handler->parsePage(url); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        fetchPage(handler, url);
    }
    logmgr.resetReturnCode();
}

static void
fetchFile(const VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.fetchToFile(props); }
    catch (const FetchError& x) {
        retrymgr.setRetryUntilRetrievedFlag();
        retrymgr.handle(x);
        fetchFile(props);
    }
    logmgr.resetReturnCode();
}

static void
queryLength(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.queryFileLength(props); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        queryLength(props);
    }
    logmgr.resetReturnCode();
}

static void
processVideo(VideoProperties& props) {
    queryLength(props, true);

    const Options opts =
        optsmgr.getOptions();

    if (opts.no_extract_given)
        printVideo(props);
    else if (opts.emit_csv_given)
        printCSV(props);
    else if (opts.stream_pass_given)
        execmgr.passStream(props);
    else
    {
        if (opts.print_fname_given)
            printVideo(props);

        fetchFile(props, true);
    }
}

typedef HostHandlerFactory::UnsupportedHostException NoSupport;
typedef HostHandler::ParseException                  ParseError;
typedef VideoProperties::NothingToDoException        NothingTodo;

static void
handleURL(const std::string& url) {
    try
    {
        SHP<HostHandler> handler =
            HostHandlerFactory::createHandler(url);

        fetchPage(handler, url, true);

        VideoProperties props =
            handler->getVideoProperties();

        try   { processVideo(props); }
        catch (const NothingTodo& x) { logmgr.cerr(x, false); }

        if (optsmgr.getOptions().exec_run_given)
            execmgr.append(props);
    }
    catch (const NoSupport& x)   { logmgr.cerr(x, false); }
    catch (const FetchError& x)  { /* printed by retrymgr.handle already */ }
    catch (const ParseError& x)  { logmgr.cerr(x, false); }
}

typedef std::vector<std::string> STRV;

void
App::run() {
    const Options opts = optsmgr.getOptions();

    if (opts.version_given) {
        printVersion();
        return;
    }

    if (opts.hosts_given) {
        HostHandlerFactory::printHosts();
        return;
    }

    execmgr.verifyExecArgument();

#if !defined(HAVE_FORK) || !defined(HAVE_WORKING_FORK)
    if (opts.stream_exec_given) {
        logmgr.cerr()
            << "warn: this system does not have a working fork.\n"
            << "warn: --stream-exec ignored."
            << std::endl;
    }
#endif

    STRV tokens;

    typedef unsigned int _uint;

    if (!opts.inputs_num)
        tokens = parseInput();
    else {
        for (register _uint i=0; i<opts.inputs_num; ++i)
            tokens.push_back(opts.inputs[i]);
    }

    for (STRV::iterator iter=tokens.begin();
        iter != tokens.end();
        ++iter)
    {
        // Convert alternate domain link to youtube.com page link.
        Util::nocookieToYoutube(*iter);

        // Convert any embed type URLs to video page links.
        Util::embedToPage(*iter);

        // Convert last.fm video link to Youtube page link.
        if ((*iter).find("last.fm") != std::string::npos)
            Util::lastfmToYoutube(*iter);
    }

    logmgr.cout().setf(std::ios::fixed);
#ifdef SIGWINCH
    signal(SIGWINCH, handle_sigwinch);
#endif
    std::for_each(tokens.begin(), tokens.end(), handleURL);

    if (opts.exec_run_given)
        execmgr.playQueue();
}

STRV
App::parseInput() {
    std::string input;

    char ch;
    while (std::cin.get(ch))
        input += ch;

    std::istringstream iss(input);
    STRV tokens;

    std::copy(
        std::istream_iterator<std::string >(iss),
        std::istream_iterator<std::string >(),
        std::back_inserter<STRV>(tokens)
    );

    return tokens;
}

void
App::printVersion() {
static const char copyr_notice[] =
"Copyright (C) 2009 Toni Gundogdu. "
"License GPLv3+: GNU GPL version 3 or later\n"
"This is free software; see the  source for  copying conditions.  There is NO\n"
"warranty;  not even for MERCHANTABILITY or FITNESS FOR A  PARTICULAR PURPOSE.";

    const curl_version_info_data *c =
        curl_version_info(CURLVERSION_NOW);

    std::cout
        << CMDLINE_PARSER_PACKAGE       << " version "
        << CMDLINE_PARSER_VERSION       << " with libcurl version "
        << c->version                   << "  ["
        << CANONICAL_TARGET             << "]\n"
        << copyr_notice                 << "\n"
        << "\n  Locale/codeset  : "     << optsmgr.getLocale()
        << "\n  Config          : "     << optsmgr.getPath()
        << "\n  Features        : pcre "
#ifdef HAVE_ICONV
        << "iconv "
#endif
#ifdef SIGWINCH
        << "sigwinch "
#endif
        << "\n  Home            : "     << "<http://cclive.googlecode.com/>"
        << std::endl;
}
<commit_msg>Add report notice.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#ifndef HAVE_PTRDIFF_T
#error Cannot compile without ptrdiff_t support
#endif

#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <tr1/memory>

#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif

#include <curl/curl.h>

#include "hosthandler.h"
#include "hostfactory.h"
#include "macros.h"
#include "opts.h"
#include "curl.h"
#include "exec.h"
#include "retry.h"
#include "log.h"
#include "app.h"

#define SHP std::tr1::shared_ptr

// singleton instances
static SHP<OptionsMgr> __optsmgr (new OptionsMgr);
static SHP<CurlMgr>    __curlmgr (new CurlMgr);
static SHP<ExecMgr>    __execmgr (new ExecMgr);
static SHP<RetryMgr>   __retrymgr(new RetryMgr);
static SHP<LogMgr>     __logmgr  (new LogMgr);

extern void handle_sigwinch(int); // src/progress.cpp

App::~App() {
}

void
App::main(const int& argc, char * const *argv) {
    optsmgr.init(argc, argv);
    logmgr.init(); // apply --quiet
    curlmgr.init();
}

static void
printVideo(const VideoProperties& props) {
    logmgr.cout()
        << "file: "
        << props.getFilename()
        << "  "
        << std::setprecision(1)
        << _TOMB(props.getLength())
        << "M  ["
        << props.getContentType()
        << "]"
        << std::endl;
}

static void
printCSV(const VideoProperties& props) {
    std::cout.setf(std::ios::fixed);
    std::cout.unsetf(std::ios::showpoint);
    std::cout
        << "csv:\""
        << props.getFilename()
        << "\",\""
        << std::setprecision(0)
        << props.getLength()
        << "\",\""
        << props.getLink()
        << "\""
        << std::endl;
}

typedef CurlMgr::FetchException FetchError;

static void
fetchPage(SHP<HostHandler> handler,
          const std::string& url,
          const bool& reset=false)
{
    if (reset)
        retrymgr.reset();
    try   { handler->parsePage(url); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        fetchPage(handler, url);
    }
    logmgr.resetReturnCode();
}

static void
fetchFile(const VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.fetchToFile(props); }
    catch (const FetchError& x) {
        retrymgr.setRetryUntilRetrievedFlag();
        retrymgr.handle(x);
        fetchFile(props);
    }
    logmgr.resetReturnCode();
}

static void
queryLength(VideoProperties& props, const bool& reset=false) {
    if (reset)
        retrymgr.reset();
    try   { curlmgr.queryFileLength(props); }
    catch (const FetchError& x) {
        retrymgr.handle(x);
        queryLength(props);
    }
    logmgr.resetReturnCode();
}

static void
processVideo(VideoProperties& props) {
    queryLength(props, true);

    const Options opts =
        optsmgr.getOptions();

    if (opts.no_extract_given)
        printVideo(props);
    else if (opts.emit_csv_given)
        printCSV(props);
    else if (opts.stream_pass_given)
        execmgr.passStream(props);
    else
    {
        if (opts.print_fname_given)
            printVideo(props);

        fetchFile(props, true);
    }
}

static void
reportNotice() {
    static const char report_notice[] =
    "error: Please report the above output to the issue tracker:\n"
    "error:     <http://code.google.com/p/cclive/issues/>\n"
    "error: Thanks!";
    logmgr.cerr() << report_notice << std::endl;
}

typedef HostHandlerFactory::UnsupportedHostException NoSupport;
typedef HostHandler::ParseException                  ParseError;
typedef VideoProperties::NothingToDoException        NothingTodo;

static void
handleURL(const std::string& url) {
    try
    {
        SHP<HostHandler> handler =
            HostHandlerFactory::createHandler(url);

        fetchPage(handler, url, true);

        VideoProperties props =
            handler->getVideoProperties();

        try   { processVideo(props); }
        catch (const NothingTodo& x) { logmgr.cerr(x, false); }

        if (optsmgr.getOptions().exec_run_given)
            execmgr.append(props);
    }
    catch (const NoSupport& x)   { logmgr.cerr(x, false); }
    catch (const FetchError& x)  { /* printed by retrymgr.handle already */ }
    catch (const ParseError& x)  { logmgr.cerr(x, false); reportNotice(); }
}

typedef std::vector<std::string> STRV;

void
App::run() {
    const Options opts = optsmgr.getOptions();

    if (opts.version_given) {
        printVersion();
        return;
    }

    if (opts.hosts_given) {
        HostHandlerFactory::printHosts();
        return;
    }

    execmgr.verifyExecArgument();

#if !defined(HAVE_FORK) || !defined(HAVE_WORKING_FORK)
    if (opts.stream_exec_given) {
        logmgr.cerr()
            << "warn: this system does not have a working fork.\n"
            << "warn: --stream-exec ignored."
            << std::endl;
    }
#endif

    STRV tokens;

    typedef unsigned int _uint;

    if (!opts.inputs_num)
        tokens = parseInput();
    else {
        for (register _uint i=0; i<opts.inputs_num; ++i)
            tokens.push_back(opts.inputs[i]);
    }

    for (STRV::iterator iter=tokens.begin();
        iter != tokens.end();
        ++iter)
    {
        // Convert alternate domain link to youtube.com page link.
        Util::nocookieToYoutube(*iter);

        // Convert any embed type URLs to video page links.
        Util::embedToPage(*iter);

        // Convert last.fm video link to Youtube page link.
        if ((*iter).find("last.fm") != std::string::npos)
            Util::lastfmToYoutube(*iter);
    }

    logmgr.cout().setf(std::ios::fixed);
#ifdef SIGWINCH
    signal(SIGWINCH, handle_sigwinch);
#endif
    std::for_each(tokens.begin(), tokens.end(), handleURL);

    if (opts.exec_run_given)
        execmgr.playQueue();
}

STRV
App::parseInput() {
    std::string input;

    char ch;
    while (std::cin.get(ch))
        input += ch;

    std::istringstream iss(input);
    STRV tokens;

    std::copy(
        std::istream_iterator<std::string >(iss),
        std::istream_iterator<std::string >(),
        std::back_inserter<STRV>(tokens)
    );

    return tokens;
}

void
App::printVersion() {
static const char copyr_notice[] =
"Copyright (C) 2009 Toni Gundogdu. "
"License GPLv3+: GNU GPL version 3 or later\n"
"This is free software; see the  source for  copying conditions.  There is NO\n"
"warranty;  not even for MERCHANTABILITY or FITNESS FOR A  PARTICULAR PURPOSE.";

    const curl_version_info_data *c =
        curl_version_info(CURLVERSION_NOW);

    std::cout
        << CMDLINE_PARSER_PACKAGE       << " version "
        << CMDLINE_PARSER_VERSION       << " with libcurl version "
        << c->version                   << "  ["
        << CANONICAL_TARGET             << "]\n"
        << copyr_notice                 << "\n"
        << "\n  Locale/codeset  : "     << optsmgr.getLocale()
        << "\n  Config          : "     << optsmgr.getPath()
        << "\n  Features        : pcre "
#ifdef HAVE_ICONV
        << "iconv "
#endif
#ifdef SIGWINCH
        << "sigwinch "
#endif
        << "\n  Home            : "     << "<http://cclive.googlecode.com/>"
        << std::endl;
}
<|endoftext|>


<commit_before>/*
 * app.cpp
 *
 *  Created on: 03.07.2015
 *      Author: scones
 */

#include "app.h"

#include <iostream>
#include <algorithm>

extern app *pgalaxy_renderer;

app::app(std::uint64_t const number_of_stars)
  :
    m_number_of_stars(number_of_stars),
    m_glfw(),
    m_window(1980, 1080, "galaxy simulation by density wave", false),
    m_va(),
    m_timer(),
    m_active(true),
    m_inner_excentricity(0.9),
    m_outer_excentricity(0.5),
    m_angular_offset(0.0005),
    m_core_radius(4000.0),
    m_galaxy_radius(13000.0),
    m_sigma(0.5),
    m_pgalaxy(nullptr)
{
  m_pgalaxy = new Galaxy(
    m_galaxy_radius,       // radius of the galaxy
    m_core_radius,         // radius of the core
    m_angular_offset,      // angluar offset of the density wave per parsec of radius
    m_inner_excentricity,  // excentricity at the edge of the core
    m_outer_excentricity,  // excentricity at the edge of the disk
    m_sigma,
    CORE_ORBIT_VELOCITY,   // orbital velocity at the edge of the core
    DISC_ORBIT_VELOCITY,   // orbital velovity at the edge of the disk
    m_number_of_stars      // total number of stars
  );
}

app::~app() {
  delete m_pgalaxy;
  m_pgalaxy = nullptr;
}

void app::init() {
  // init glfw
  m_glfw.init();
  glfwSetErrorCallback(&app::global_error_callback);

  // open window
  m_window.init();
  m_window.set_key_callback(&app::global_key_callback);
  m_window.make_current();

  // activate vertex_array
  m_va.init();

  // setup all the geometry
  m_pgalaxy->InitStars();
}

void app::run() {
  std::int64_t i = 0;
  m_timer.reset();
  do {
    glClearColor(0.5, 0.5, 0.5, 0.5);
    glClear(GL_COLOR_BUFFER_BIT);

    m_va.activate();

    if (m_pgalaxy)
      m_pgalaxy->render();

    m_window.swap_buffers();
    glfwPollEvents();
    ++i;
  } while (!m_window.should_close() && m_active);

  std::cout << "frames rendered: " << i << std::endl;
  std::cout << "fps: " << (double)i / m_timer.elapsed_time() << std::endl;
}

void app::error_callback(int error, const char* description) {
  std::cerr << "GLFW error (" << error << "): " << description << std::endl;
}

void app::key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
  bool rebuild_galaxy = false;
  switch (key) {
    if (GLFW_RELEASE == action) {
      case GLFW_KEY_ESCAPE:
        m_active = false;
        break;

      // inner excentricity
      case GLFW_KEY_Q:
        m_inner_excentricity = std::min(0.95, m_inner_excentricity + 0.01);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_A:
        m_inner_excentricity = std::max(0.05, m_inner_excentricity - 0.01);
        rebuild_galaxy = true;
        break;

      // outer excentricity
      case GLFW_KEY_W:
        m_outer_excentricity = std::min(0.95, m_outer_excentricity + 0.01);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_S:
        m_outer_excentricity = std::max(0.05, m_outer_excentricity - 0.01);
        rebuild_galaxy = true;
        break;

      // angular offset
      case GLFW_KEY_E:
        m_angular_offset += 0.00005;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_D:
        m_angular_offset -= 0.00005;
        rebuild_galaxy = true;
        break;

      // core radius
      case GLFW_KEY_R:
        std::min(m_galaxy_radius, m_core_radius + 500.0);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_F:
        m_core_radius = std::max(0.0, m_core_radius - 500.0);
        rebuild_galaxy = true;
        break;

      // galaxy radius
      case GLFW_KEY_T:
        m_galaxy_radius += 1000.0;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_G:
        if (m_galaxy_radius - 1000.0 > m_core_radius)
          m_galaxy_radius -= 1000.0;
        rebuild_galaxy = true;
        break;

      // sigma
      case GLFW_KEY_Z:
      case GLFW_KEY_Y:
        m_sigma += 0.05;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_H:
        m_sigma = std::max(0.05, m_sigma - 0.05);
        rebuild_galaxy = true;
        break;
    }
  }

  if (rebuild_galaxy) {

    Galaxy *new_galaxy = new Galaxy(
      m_galaxy_radius,       // radius of the galaxy
      m_core_radius,         // radius of the core
      m_angular_offset,      // angluar offset of the density wave per parsec of radius
      m_inner_excentricity,  // excentricity at the edge of the core
      m_outer_excentricity,  // excentricity at the edge of the disk
      m_sigma,
      CORE_ORBIT_VELOCITY,   // orbital velocity at the edge of the core
      DISC_ORBIT_VELOCITY,   // orbital velovity at the edge of the disk
      m_number_of_stars      // total number of stars
    );
    auto tmp_galaxy = m_pgalaxy;
    m_pgalaxy = new_galaxy;
    delete tmp_galaxy;
    std::cerr << "1";
    m_pgalaxy->InitStars();
    rebuild_galaxy = false;
  }
}

void app::global_error_callback(int error, const char* description) {
  pgalaxy_renderer->error_callback(error, description);
}

void app::global_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  pgalaxy_renderer->key_callback(window, key, scancode, action, mods);
}

<commit_msg>master - print out last settings<commit_after>/*
 * app.cpp
 *
 *  Created on: 03.07.2015
 *      Author: scones
 */

#include "app.h"

#include <iostream>
#include <algorithm>

extern app *pgalaxy_renderer;

app::app(std::uint64_t const number_of_stars)
  :
    m_number_of_stars(number_of_stars),
    m_glfw(),
    m_window(1980, 1080, "galaxy simulation by density wave", false),
    m_va(),
    m_timer(),
    m_active(true),
    m_inner_excentricity(0.78),
    m_outer_excentricity(0.92),
    m_angular_offset(0.0004),
    m_core_radius(4000.0),
    m_galaxy_radius(13000.0),
    m_sigma(0.5),
    m_pgalaxy(nullptr)
{
  m_pgalaxy = new Galaxy(
    m_galaxy_radius,       // radius of the galaxy
    m_core_radius,         // radius of the core
    m_angular_offset,      // angluar offset of the density wave per parsec of radius
    m_inner_excentricity,  // excentricity at the edge of the core
    m_outer_excentricity,  // excentricity at the edge of the disk
    m_sigma,
    CORE_ORBIT_VELOCITY,   // orbital velocity at the edge of the core
    DISC_ORBIT_VELOCITY,   // orbital velovity at the edge of the disk
    m_number_of_stars      // total number of stars
  );
}

app::~app() {
  delete m_pgalaxy;
  m_pgalaxy = nullptr;

  std::cout
    << "final configuration:\n"
    << "radius: " << m_galaxy_radius << "\n"
    << "core radius: " << m_core_radius << "\n"
    << "angular offset: " << m_angular_offset << "\n"
    << "inner excentricity: " << m_inner_excentricity << "\n"
    << "outer excentricity: " << m_outer_excentricity << "\n"
    << "sigma: " << m_sigma << "\n"
    << "star count: " << m_number_of_stars << "\n"
    << std::endl;
}

void app::init() {
  // init glfw
  m_glfw.init();
  glfwSetErrorCallback(&app::global_error_callback);

  // open window
  m_window.init();
  m_window.set_key_callback(&app::global_key_callback);
  m_window.make_current();

  // activate vertex_array
  m_va.init();

  // setup all the geometry
  m_pgalaxy->InitStars();
}

void app::run() {
  std::int64_t i = 0;
  m_timer.reset();
  do {
    glClearColor(0.5, 0.5, 0.5, 0.5);
    glClear(GL_COLOR_BUFFER_BIT);

    m_va.activate();

    if (m_pgalaxy)
      m_pgalaxy->render();

    m_window.swap_buffers();
    glfwPollEvents();
    ++i;
  } while (!m_window.should_close() && m_active);

  std::cout << "frames rendered: " << i << std::endl;
  std::cout << "fps: " << (double)i / m_timer.elapsed_time() << std::endl;
}

void app::error_callback(int error, const char* description) {
  std::cerr << "GLFW error (" << error << "): " << description << std::endl;
}

void app::key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
  bool rebuild_galaxy = false;
  switch (key) {
    if (GLFW_RELEASE == action) {
      case GLFW_KEY_ESCAPE:
        m_active = false;
        break;

      // inner excentricity
      case GLFW_KEY_Q:
        m_inner_excentricity = std::min(0.95, m_inner_excentricity + 0.01);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_A:
        m_inner_excentricity = std::max(0.05, m_inner_excentricity - 0.01);
        rebuild_galaxy = true;
        break;

      // outer excentricity
      case GLFW_KEY_W:
        m_outer_excentricity = std::min(0.95, m_outer_excentricity + 0.01);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_S:
        m_outer_excentricity = std::max(0.05, m_outer_excentricity - 0.01);
        rebuild_galaxy = true;
        break;

      // angular offset
      case GLFW_KEY_E:
        m_angular_offset += 0.00005;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_D:
        m_angular_offset -= 0.00005;
        rebuild_galaxy = true;
        break;

      // core radius
      case GLFW_KEY_R:
        std::min(m_galaxy_radius, m_core_radius + 500.0);
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_F:
        m_core_radius = std::max(0.0, m_core_radius - 500.0);
        rebuild_galaxy = true;
        break;

      // galaxy radius
      case GLFW_KEY_T:
        m_galaxy_radius += 1000.0;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_G:
        if (m_galaxy_radius - 1000.0 > m_core_radius)
          m_galaxy_radius -= 1000.0;
        rebuild_galaxy = true;
        break;

      // sigma
      case GLFW_KEY_Z:
      case GLFW_KEY_Y:
        m_sigma += 0.05;
        rebuild_galaxy = true;
        break;
      case GLFW_KEY_H:
        m_sigma = std::max(0.05, m_sigma - 0.05);
        rebuild_galaxy = true;
        break;
    }
  }

  if (rebuild_galaxy) {

    Galaxy *new_galaxy = new Galaxy(
      m_galaxy_radius,       // radius of the galaxy
      m_core_radius,         // radius of the core
      m_angular_offset,      // angluar offset of the density wave per parsec of radius
      m_inner_excentricity,  // excentricity at the edge of the core
      m_outer_excentricity,  // excentricity at the edge of the disk
      m_sigma,
      CORE_ORBIT_VELOCITY,   // orbital velocity at the edge of the core
      DISC_ORBIT_VELOCITY,   // orbital velovity at the edge of the disk
      m_number_of_stars      // total number of stars
    );
    auto tmp_galaxy = m_pgalaxy;
    m_pgalaxy = new_galaxy;
    delete tmp_galaxy;
    std::cerr << "1";
    m_pgalaxy->InitStars();
    rebuild_galaxy = false;
  }
}

void app::global_error_callback(int error, const char* description) {
  pgalaxy_renderer->error_callback(error, description);
}

void app::global_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
  pgalaxy_renderer->key_callback(window, key, scancode, action, mods);
}

<|endoftext|>


<commit_before>/*
   Copyright 2014 Kristina Simpson <sweet.kristas@gmail.com>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include <limits>

#include "asserts.hpp"
#include "bot.hpp"
#include "component.hpp"
#include "game_state.hpp"
#include "hex_logical_tiles.hpp"
#include "hex_pathfinding.hpp"
#include "message_format.pb.h"
#include "profile_timer.hpp"
#include "random.hpp"

namespace ai
{
	void local_bot_code(player_ptr bot, game::state gs, network::client_ptr client)
	{
		game::Update* up;
		bool running = true;
		profile::timer time;
		while(running) {
			if((up = client->read_recv_queue()) != nullptr) {
				bool end_of_turn_message = false;
				std::cerr << "local_bot_code: Got message: " << up->id() << "\n";
				gs.apply(up);
				if(up->has_quit() && up->quit() == true && up->id() == -1) {
					running = false;
				}
				if(up->has_end_turn()) {
					end_of_turn_message = up->end_turn();
				}
				delete up;

				if(end_of_turn_message) {
					up = bot->process(gs, time.get_time());
					if(up) {
						client->write_send_queue(up);
					}
				}
			}

			client->process();

			profile::sleep(0.01);
		}
	}

	bot::bot(team_ptr team, const std::string& name, uuid::uuid u)
		: player(team, PlayerType::AI, name, u)
	{
	}

	game::Update* bot::process(const game::state& gs, double time)
	{
		profile::manager botman("Bot process time");
		// Look at game state and decide if we need to do stuff.

		// Get current entity
		auto& e = gs.get_entities().front();

		// First test is whether the currently active entity is ours.
		if(e->owner.lock()->get_uuid() != get_uuid()) {
			return nullptr;
		}

		LOG_DEBUG("Running bot for " << e);

		// Find available moves for current unit.
		auto g = hex::create_cost_graph(gs, e->pos->gs_pos.x, e->pos->gs_pos.y, e->stat->move);
		auto possible_moves = hex::find_available_moves(g, e->pos->gs_pos, e->stat->move);

		// Calculate the closest enemy and move towards them
		component_set_ptr closest_enemy = nullptr;
		int closest_distance = std::numeric_limits<int>::max();
		for(auto& enemy : gs.get_entities()) {
			// XXX we should come up with a faster access for the team id, maybe add it directly as a member of component_set_ptr
			if(enemy->owner.lock()->team() != e->owner.lock()->team()) {
				if(closest_enemy == nullptr) {
					closest_enemy = enemy;
					closest_distance = hex::logical::distance(e->pos->gs_pos, enemy->pos->gs_pos);
				} else {
					int d = hex::logical::distance(e->pos->gs_pos, enemy->pos->gs_pos);
					if(d < closest_distance) {
						closest_enemy = enemy;
						closest_distance = d;
					}
				}
			}
		}
		// Found an enemy, try and get as close as possible.
		point dest;
		bool got_location = false;
		hex::result_path rp;
		if(closest_enemy && closest_distance > e->stat->range) {
			auto surrounds = gs.get_map()->get_surrounding_positions(closest_enemy->pos->gs_pos);
			for(auto& p : possible_moves) {
				for(auto& sp : surrounds) {
					if(p.loc == sp) {
						// We found a match.
						got_location = true;
						dest = sp;
						break;
					}
				}
			}

			// Did we find a location of enemy within our list of possible moves?
			if(got_location) {
				rp = hex::find_path(g, e->pos->gs_pos, dest);
			} else {
				// Nope. Then we need to find the tile that is closest and move there.
				int closest_d = std::numeric_limits<int>::max();
				point closest_pos;
				for(auto& p : possible_moves) {
					int d = hex::logical::distance(p.loc, closest_enemy->pos->gs_pos);
					if(d < closest_d) {
						closest_d = d;
						closest_pos = p.loc;
					}
				}
				rp = hex::find_path(g, e->pos->gs_pos, closest_pos);
				got_location = true;
			}
		}

		ASSERT_LOG(got_location || closest_distance <= e->stat->range, "Programmer error: No location for destination.");

		// Choose random destination
		//int x = generator::get_uniform_int<int>(0, static_cast<int>(possible_moves.size()));
		//auto rp = hex::find_path(g, e->pos->gs_pos, possible_moves[x].loc);

		// Random move unit.
		game::Update* up = gs.create_update();
		// No need to move if there is a unit next to us.
		if(closest_distance > e->stat->range) {
			gs.unit_move(up, e, rp);
			e->pos->gs_pos = point(rp.rbegin()->x, rp.rbegin()->y);
		}

		// See if there is anything in attack range.
		std::vector<component_set_ptr> attackable;
		int max_attacks = e->stat->unit->get_max_units_attackable();
		for(auto& ae : gs.get_entities()) {
			if(gs.is_attackable(e, ae)) {
				attackable.emplace_back(ae);
				if(--max_attacks == 0) {
					break;
				}
			}
		}
		if(!attackable.empty()) {
			gs.unit_attack(up, e, attackable);
		}
		gs.end_turn(up);
		return up;
	}

	player_ptr bot::clone()
	{
		return std::shared_ptr<bot>(new bot(*this));
	}

}
<commit_msg>Force the bot to exit when a game finishes.<commit_after>/*
   Copyright 2014 Kristina Simpson <sweet.kristas@gmail.com>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include <limits>

#include "asserts.hpp"
#include "bot.hpp"
#include "component.hpp"
#include "game_state.hpp"
#include "hex_logical_tiles.hpp"
#include "hex_pathfinding.hpp"
#include "message_format.pb.h"
#include "profile_timer.hpp"
#include "random.hpp"

namespace ai
{
	void local_bot_code(player_ptr bot, game::state gs, network::client_ptr client)
	{
		game::Update* up;
		bool running = true;
		profile::timer time;
		while(running) {
			if((up = client->read_recv_queue()) != nullptr) {
				bool end_of_turn_message = false;
				std::cerr << "local_bot_code: Got message: " << up->id() << "\n";
				gs.apply(up);
				if(up->has_quit() && up->quit() == true && up->id() == -1) {
					running = false;
				}
				if(up->has_end_turn()) {
					end_of_turn_message = up->end_turn();
				}
				if(up->has_game_win_state() && up->game_win_state() != game::Update_GameWinState_IN_PROGRESS) {
					// Bot is dispassionate and exits out after the game is over.
					running = false;
					/// XXX should we send a player quits message here?
				}
				delete up;

				if(end_of_turn_message && running) {
					up = bot->process(gs, time.get_time());
					if(up) {
						client->write_send_queue(up);
					}
				}
			}

			client->process();

			profile::sleep(0.01);
		}
		LOG_INFO("bot exits -- player " << bot->name());
	}

	bot::bot(team_ptr team, const std::string& name, uuid::uuid u)
		: player(team, PlayerType::AI, name, u)
	{
	}

	game::Update* bot::process(const game::state& gs, double time)
	{
		profile::manager botman("Bot process time");
		// Look at game state and decide if we need to do stuff.

		// Get current entity
		auto& e = gs.get_entities().front();

		// First test is whether the currently active entity is ours.
		if(e->owner.lock()->get_uuid() != get_uuid()) {
			return nullptr;
		}

		LOG_DEBUG("Running bot for " << e);

		// Find available moves for current unit.
		auto g = hex::create_cost_graph(gs, e->pos->gs_pos.x, e->pos->gs_pos.y, e->stat->move);
		auto possible_moves = hex::find_available_moves(g, e->pos->gs_pos, e->stat->move);

		// Calculate the closest enemy and move towards them
		component_set_ptr closest_enemy = nullptr;
		int closest_distance = std::numeric_limits<int>::max();
		for(auto& enemy : gs.get_entities()) {
			// XXX we should come up with a faster access for the team id, maybe add it directly as a member of component_set_ptr
			if(enemy->owner.lock()->team() != e->owner.lock()->team()) {
				if(closest_enemy == nullptr) {
					closest_enemy = enemy;
					closest_distance = hex::logical::distance(e->pos->gs_pos, enemy->pos->gs_pos);
				} else {
					int d = hex::logical::distance(e->pos->gs_pos, enemy->pos->gs_pos);
					if(d < closest_distance) {
						closest_enemy = enemy;
						closest_distance = d;
					}
				}
			}
		}
		// Found an enemy, try and get as close as possible.
		point dest;
		bool got_location = false;
		hex::result_path rp;
		if(closest_enemy && closest_distance > e->stat->range) {
			auto surrounds = gs.get_map()->get_surrounding_positions(closest_enemy->pos->gs_pos);
			for(auto& p : possible_moves) {
				for(auto& sp : surrounds) {
					if(p.loc == sp) {
						// We found a match.
						got_location = true;
						dest = sp;
						break;
					}
				}
			}

			// Did we find a location of enemy within our list of possible moves?
			if(got_location) {
				rp = hex::find_path(g, e->pos->gs_pos, dest);
			} else {
				// Nope. Then we need to find the tile that is closest and move there.
				int closest_d = std::numeric_limits<int>::max();
				point closest_pos;
				for(auto& p : possible_moves) {
					int d = hex::logical::distance(p.loc, closest_enemy->pos->gs_pos);
					if(d < closest_d) {
						closest_d = d;
						closest_pos = p.loc;
					}
				}
				rp = hex::find_path(g, e->pos->gs_pos, closest_pos);
				got_location = true;
			}
		}

		ASSERT_LOG(got_location || closest_distance <= e->stat->range, "Programmer error: No location for destination.");

		// Choose random destination
		//int x = generator::get_uniform_int<int>(0, static_cast<int>(possible_moves.size()));
		//auto rp = hex::find_path(g, e->pos->gs_pos, possible_moves[x].loc);

		// Random move unit.
		game::Update* up = gs.create_update();
		// No need to move if there is a unit next to us.
		if(closest_distance > e->stat->range) {
			gs.unit_move(up, e, rp);
			e->pos->gs_pos = point(rp.rbegin()->x, rp.rbegin()->y);
		}

		// See if there is anything in attack range.
		std::vector<component_set_ptr> attackable;
		int max_attacks = e->stat->unit->get_max_units_attackable();
		for(auto& ae : gs.get_entities()) {
			if(gs.is_attackable(e, ae)) {
				attackable.emplace_back(ae);
				if(--max_attacks == 0) {
					break;
				}
			}
		}
		if(!attackable.empty()) {
			gs.unit_attack(up, e, attackable);
		}
		gs.end_turn(up);
		return up;
	}

	player_ptr bot::clone()
	{
		return std::shared_ptr<bot>(new bot(*this));
	}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: fusel.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-21 16:02:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SC_FUSEL_HXX
#define SC_FUSEL_HXX

#ifndef _SV_HXX
#endif

#ifndef SC_FUDRAW_HXX
#include "fudraw.hxx"
#endif

//class Outliner;
//class OutlinerView;
class SdrPageView;

/*************************************************************************
|*
|* Basisklasse fuer alle Funktionen
|*
\************************************************************************/

class FuSelection : public FuDraw
{
 protected:
//  Outliner*       pOutliner;
//  OutlinerView*   pOutlinerView;
    BOOL            bVCAction;

 private:
    BOOL TestDetective( SdrPageView* pPV, const Point& rPos );  // -> fusel2
    BOOL TestComment( SdrPageView* pPV, const Point& rPos );    // -> fusel2

 public:
    FuSelection(ScTabViewShell* pViewSh, Window* pWin, SdrView* pView,
           SdrModel* pDoc, SfxRequest& rReq );

    virtual ~FuSelection();
                                       // Mouse- & Key-Events
    virtual BOOL KeyInput(const KeyEvent& rKEvt);
    virtual BOOL MouseMove(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonUp(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonDown(const MouseEvent& rMEvt);
    virtual BYTE Command(const CommandEvent& rCEvt);

    virtual void Activate();           // Function aktivieren
    virtual void Deactivate();         // Function deaktivieren

    void    ActivateNoteHandles(SdrObject* pObj) const ;
};

#endif      // _SD_FUSEL_HXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.2.146); FILE MERGED 2005/09/05 15:05:26 rt 1.2.146.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fusel.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 21:29:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SC_FUSEL_HXX
#define SC_FUSEL_HXX

#ifndef _SV_HXX
#endif

#ifndef SC_FUDRAW_HXX
#include "fudraw.hxx"
#endif

//class Outliner;
//class OutlinerView;
class SdrPageView;

/*************************************************************************
|*
|* Basisklasse fuer alle Funktionen
|*
\************************************************************************/

class FuSelection : public FuDraw
{
 protected:
//  Outliner*       pOutliner;
//  OutlinerView*   pOutlinerView;
    BOOL            bVCAction;

 private:
    BOOL TestDetective( SdrPageView* pPV, const Point& rPos );  // -> fusel2
    BOOL TestComment( SdrPageView* pPV, const Point& rPos );    // -> fusel2

 public:
    FuSelection(ScTabViewShell* pViewSh, Window* pWin, SdrView* pView,
           SdrModel* pDoc, SfxRequest& rReq );

    virtual ~FuSelection();
                                       // Mouse- & Key-Events
    virtual BOOL KeyInput(const KeyEvent& rKEvt);
    virtual BOOL MouseMove(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonUp(const MouseEvent& rMEvt);
    virtual BOOL MouseButtonDown(const MouseEvent& rMEvt);
    virtual BYTE Command(const CommandEvent& rCEvt);

    virtual void Activate();           // Function aktivieren
    virtual void Deactivate();         // Function deaktivieren

    void    ActivateNoteHandles(SdrObject* pObj) const ;
};

#endif      // _SD_FUSEL_HXX

<|endoftext|>


<commit_before>
#include "Transform.h"
#include <glm\gtc\matrix_transform.hpp>

Transform::Transform() :
	position(0.0f), scale(1.0f), axisAngles(0.0f), modelMatrix(1.0f), recalculate(false)
{
}

Transform::Transform(const glm::vec3& position, const glm::vec3& scale, const glm::vec3& axisAngles) :
	position(position), scale(scale), axisAngles(axisAngles), recalculate(true)
{
}

void Transform::setPosition(const glm::vec3 & newPosition)
{
	position = newPosition;
	recalculate = true;
}

void Transform::setScale(const glm::vec3 & newScale)
{
	scale = newScale;
	recalculate = true;
}

void Transform::setScale(const float newScale)
{
	scale = glm::vec3(newScale);
	recalculate = true;
}

void Transform::setAngles(const float xAxis, const float yAxis, const float zAxis)
{
	axisAngles = { xAxis, yAxis, zAxis };
	recalculate = true;
}

void Transform::setAngles(const glm::vec3& angles)
{
	axisAngles = angles;
	recalculate = true;
}

glm::vec3 Transform::getPosition() const
{
	return position;
}

glm::vec3 Transform::getScale() const
{
	return scale;
}

glm::vec3 Transform::getAxisAngles() const
{
	return axisAngles;
}

const glm::mat4& Transform::getTransformMatrix()
{
	if (recalculate) {
		modelMatrix =
			glm::rotate(
				glm::rotate(
					glm::rotate(
						glm::scale(glm::translate(glm::mat4(1.0f), position), scale),
						axisAngles.x, { 1.0f,0.0f,0.0f }),
					axisAngles.y, { 0.0f,1.0f,0.0f }),
				axisAngles.z, { 0.0f,0.0f,1.0f });
		recalculate = false;
	}
	return modelMatrix;
}
<commit_msg>GLM radians warning fixed.<commit_after>#define GLM_FORCE_RADIANS
#include "Transform.h"
#include <glm\gtc\matrix_transform.hpp>

Transform::Transform() :
	position(0.0f), scale(1.0f), axisAngles(0.0f), modelMatrix(1.0f), recalculate(false)
{
}

Transform::Transform(const glm::vec3& position, const glm::vec3& scale, const glm::vec3& axisAngles) :
	position(position), scale(scale), axisAngles(axisAngles), recalculate(true)
{
}

void Transform::setPosition(const glm::vec3 & newPosition)
{
	position = newPosition;
	recalculate = true;
}

void Transform::setScale(const glm::vec3 & newScale)
{
	scale = newScale;
	recalculate = true;
}

void Transform::setScale(const float newScale)
{
	scale = glm::vec3(newScale);
	recalculate = true;
}

void Transform::setAngles(const float xAxis, const float yAxis, const float zAxis)
{
	axisAngles = { xAxis, yAxis, zAxis };
	recalculate = true;
}

void Transform::setAngles(const glm::vec3& angles)
{
	axisAngles = angles;
	recalculate = true;
}

glm::vec3 Transform::getPosition() const
{
	return position;
}

glm::vec3 Transform::getScale() const
{
	return scale;
}

glm::vec3 Transform::getAxisAngles() const
{
	return axisAngles;
}

const glm::mat4& Transform::getTransformMatrix()
{
	if (recalculate) {
		glm::vec3 radAngles = glm::radians(axisAngles);

		modelMatrix =
			glm::rotate(
				glm::rotate(
					glm::rotate(
						glm::scale(glm::translate(glm::mat4(1.0f), position), scale),
						radAngles.x, { 1.0f,0.0f,0.0f }),
					radAngles.y, { 0.0f,1.0f,0.0f }),
				radAngles.z, { 0.0f,0.0f,1.0f });
		recalculate = false;
	}
	return modelMatrix;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <vector>

#ifndef _INSERTIONSORT_HPP
#define _INSERTIONSORT_HPP 1

namespace InsertionSort {

	template<class RandomIt>
	void Sort(RandomIt first, RandomIt end) {
		auto length = end-first;
		for (int i=1; i<length; ++i) {
			auto val = *(first+i);
			auto newPos = i-1;
			while (newPos >= 0 && *(first+newPos) > val) {
				*(first+newPos+1) = *(first+newPos);
				--newPos;
			}
			*(first+newPos+1) = val;
		}
	}
}

#endif //_INSERTIONSORT_HPP<commit_msg>removed auto usage from insertionSort<commit_after>#include <algorithm>
#include <vector>

#ifndef _INSERTIONSORT_HPP
#define _INSERTIONSORT_HPP 1

namespace InsertionSort {

	template<class RandomIt>
	void Sort(RandomIt first, RandomIt end) {
		typename std::iterator_traits<RandomIt>::difference_type length = end-first;
		for (unsigned int i=1; i<length; ++i) {
			typename std::iterator_traits<RandomIt>::value_type val = *(first+i);
			int newPos = i-1;
			while (*(first+newPos) > val && newPos >= 0) {
				*(first+newPos+1) = *(first+newPos);
				--newPos;
			}
			*(first+newPos+1) = val;
		}
	}
}

#endif //_INSERTIONSORT_HPP<|endoftext|>


<commit_before>
#include "odrive_main.h"

Controller::Controller(Config_t& config) :
    config_(config)
{}

void Controller::reset() {
    pos_setpoint_ = 0.0f;
    vel_setpoint_ = 0.0f;
    vel_integrator_current_ = 0.0f;
    current_setpoint_ = 0.0f;
}

void Controller::set_error(Error_t error) {
    error_ |= error;
    axis_->error_ |= Axis::ERROR_CONTROLLER_FAILED;
}

//--------------------------------
// Command Handling
//--------------------------------

void Controller::set_pos_setpoint(float pos_setpoint, float vel_feed_forward, float current_feed_forward) {
    pos_setpoint_ = pos_setpoint;
    vel_setpoint_ = vel_feed_forward;
    current_setpoint_ = current_feed_forward;
    config_.control_mode = CTRL_MODE_POSITION_CONTROL;
#ifdef DEBUG_PRINT
    printf("POSITION_CONTROL %6.0f %3.3f %3.3f\n", pos_setpoint, vel_setpoint_, current_setpoint_);
#endif
}

void Controller::set_vel_setpoint(float vel_setpoint, float current_feed_forward) {
    vel_setpoint_ = vel_setpoint;
    current_setpoint_ = current_feed_forward;
    config_.control_mode = CTRL_MODE_VELOCITY_CONTROL;
#ifdef DEBUG_PRINT
    printf("VELOCITY_CONTROL %3.3f %3.3f\n", vel_setpoint_, motor->current_setpoint_);
#endif
}

void Controller::set_current_setpoint(float current_setpoint) {
    current_setpoint_ = current_setpoint;
    config_.control_mode = CTRL_MODE_CURRENT_CONTROL;
#ifdef DEBUG_PRINT
    printf("CURRENT_CONTROL %3.3f\n", current_setpoint_);
#endif
}

void Controller::move_to_pos(float goal_point) {
    axis_->trap_.planTrapezoidal(goal_point, pos_setpoint_, vel_setpoint_,
                                 axis_->trap_.config_.vel_limit,
                                 axis_->trap_.config_.accel_limit,
                                 axis_->trap_.config_.decel_limit);
    traj_start_loop_count_ = axis_->loop_counter_;
    config_.control_mode = CTRL_MODE_TRAJECTORY_CONTROL;
    goal_point_ = goal_point;
}

void Controller::move_incremental(float displacement, bool from_goal_point = true){
    if(from_goal_point){
        move_to_pos(goal_point_ + displacement);
    } else{
        move_to_pos(pos_setpoint_ + displacement);
    }
}

void Controller::start_anticogging_calibration() {
    // Ensure the cogging map was correctly allocated earlier and that the motor is capable of calibrating
    if (anticogging_.cogging_map != NULL && axis_->error_ == Axis::ERROR_NONE) {
        anticogging_.calib_anticogging = true;
    }
}

/*
 * This anti-cogging implementation iterates through each encoder position,
 * waits for zero velocity & position error,
 * then samples the current required to maintain that position.
 *
 * This holding current is added as a feedforward term in the control loop.
 */
bool Controller::anticogging_calibration(float pos_estimate, float vel_estimate) {
    if (anticogging_.calib_anticogging && anticogging_.cogging_map != NULL) {
        float pos_err = anticogging_.index - pos_estimate;
        if (fabsf(pos_err) <= anticogging_.calib_pos_threshold &&
            fabsf(vel_estimate) < anticogging_.calib_vel_threshold) {
            anticogging_.cogging_map[anticogging_.index++] = vel_integrator_current_;
        }
        if (anticogging_.index < axis_->encoder_.config_.cpr) { // TODO: remove the dependency on encoder CPR
            set_pos_setpoint(anticogging_.index, 0.0f, 0.0f);
            return false;
        } else {
            anticogging_.index = 0;
            set_pos_setpoint(0.0f, 0.0f, 0.0f);  // Send the motor home
            anticogging_.use_anticogging = true;  // We're good to go, enable anti-cogging
            anticogging_.calib_anticogging = false;
            return true;
        }
    }
    return false;
}

bool Controller::update(float pos_estimate, float vel_estimate, float* current_setpoint_output) {
    // Only runs if anticogging_.calib_anticogging is true; non-blocking
    anticogging_calibration(pos_estimate, vel_estimate);
    float anticogging_pos = pos_estimate;

    // Trajectory control
    if (config_.control_mode == CTRL_MODE_TRAJECTORY_CONTROL) {
        // Note: uint32_t loop count delta is OK across overflow
        // Beware of negative deltas, as they will not be well behaved due to uint!
        float t = (axis_->loop_counter_ - traj_start_loop_count_) * current_meas_period;
        if (t > axis_->trap_.Tf_) {
            // Drop into position control mode when done to avoid problems on loop counter delta overflow
            config_.control_mode = CTRL_MODE_POSITION_CONTROL;
            // pos_setpoint already set by trajectory
            vel_setpoint_ = 0.0f;
            current_setpoint_ = 0.0f;
        } else {
            TrapezoidalTrajectory::Step_t traj_step = axis_->trap_.eval(t);
            pos_setpoint_ = traj_step.Y;
            vel_setpoint_ = traj_step.Yd;
            current_setpoint_ = traj_step.Ydd * axis_->trap_.config_.A_per_css;
        }
        anticogging_pos = pos_setpoint_; // FF the position setpoint instead of the pos_estimate
    }

    // Ramp rate limited velocity setpoint
    if (config_.control_mode == CTRL_MODE_VELOCITY_CONTROL && vel_ramp_enable_) {
        float max_step_size = current_meas_period * config_.vel_ramp_rate;
        float full_step = vel_ramp_target_ - vel_setpoint_;
        float step;
        if (fabsf(full_step) > max_step_size) {
            step = std::copysignf(max_step_size, full_step);
        } else {
            step = full_step;
        }
        vel_setpoint_ += step;
    }

    // Position control
    // TODO Decide if we want to use encoder or pll position here
    float vel_des = vel_setpoint_;
    if (config_.control_mode >= CTRL_MODE_POSITION_CONTROL) {
        float pos_err;
        if (config_.setpoints_in_cpr) {
            // TODO this breaks the semantics that estimates come in on the arguments.
            // It's probably better to call a get_estimate that will arbitrate (enc vs sensorless) instead.
            float cpr = (float)(axis_->encoder_.config_.cpr);
            // Keep pos setpoint from drifting
            pos_setpoint_ = fmodf_pos(pos_setpoint_, cpr);
            // Circular delta
            pos_err = pos_setpoint_ - axis_->encoder_.pos_cpr_;
            pos_err = wrap_pm(pos_err, 0.5f * cpr);
        } else {
            pos_err = pos_setpoint_ - pos_estimate;
        }
        vel_des += config_.pos_gain * pos_err;
    }

    // Velocity limiting
    float vel_lim = config_.vel_limit;
    if (vel_des > vel_lim) vel_des = vel_lim;
    if (vel_des < -vel_lim) vel_des = -vel_lim;

    // Check for overspeed fault (done in this module (controller) for cohesion with vel_lim)
    if (config_.vel_limit_tolerance > 0.0f) { // 0.0f to disable
        if (fabsf(vel_estimate) > config_.vel_limit_tolerance * vel_lim) {
            set_error(ERROR_OVERSPEED);
            return false;
        }
    }

    // Velocity control
    float Iq = current_setpoint_;

    // Anti-cogging is enabled after calibration
    // We get the current position and apply a current feed-forward
    // ensuring that we handle negative encoder positions properly (-1 == motor->encoder.encoder_cpr - 1)
    if (anticogging_.use_anticogging) {
        Iq += anticogging_.cogging_map[mod(static_cast<int>(anticogging_pos), axis_->encoder_.config_.cpr)];
    }

    float v_err = vel_des - vel_estimate;
    if (config_.control_mode >= CTRL_MODE_VELOCITY_CONTROL) {
        Iq += config_.vel_gain * v_err;
    }

    // Velocity integral action before limiting
    Iq += vel_integrator_current_;

    // Current limiting
    bool limited = false;
    float Ilim = axis_->motor_.effective_current_lim();
    if (Iq > Ilim) {
        limited = true;
        Iq = Ilim;
    }
    if (Iq < -Ilim) {
        limited = true;
        Iq = -Ilim;
    }

    // Velocity integrator (behaviour dependent on limiting)
    if (config_.control_mode < CTRL_MODE_VELOCITY_CONTROL) {
        // reset integral if not in use
        vel_integrator_current_ = 0.0f;
    } else {
        if (limited) {
            // TODO make decayfactor configurable
            vel_integrator_current_ *= 0.99f;
        } else {
            vel_integrator_current_ += (config_.vel_integrator_gain * current_meas_period) * v_err;
        }
    }

    if (current_setpoint_output) *current_setpoint_output = Iq;
    return true;
}
<commit_msg>velocity limiting in current control mode<commit_after>
#include "odrive_main.h"

Controller::Controller(Config_t& config) : config_(config) {}

void Controller::reset() {
    pos_setpoint_ = 0.0f;
    vel_setpoint_ = 0.0f;
    vel_integrator_current_ = 0.0f;
    current_setpoint_ = 0.0f;
}

void Controller::set_error(Error_t error) {
    error_ |= error;
    axis_->error_ |= Axis::ERROR_CONTROLLER_FAILED;
}

//--------------------------------
// Command Handling
//--------------------------------

void Controller::set_pos_setpoint(float pos_setpoint, float vel_feed_forward, float current_feed_forward) {
    pos_setpoint_ = pos_setpoint;
    vel_setpoint_ = vel_feed_forward;
    current_setpoint_ = current_feed_forward;
    config_.control_mode = CTRL_MODE_POSITION_CONTROL;
#ifdef DEBUG_PRINT
    printf("POSITION_CONTROL %6.0f %3.3f %3.3f\n", pos_setpoint, vel_setpoint_, current_setpoint_);
#endif
}

void Controller::set_vel_setpoint(float vel_setpoint, float current_feed_forward) {
    vel_setpoint_ = vel_setpoint;
    current_setpoint_ = current_feed_forward;
    config_.control_mode = CTRL_MODE_VELOCITY_CONTROL;
#ifdef DEBUG_PRINT
    printf("VELOCITY_CONTROL %3.3f %3.3f\n", vel_setpoint_, motor->current_setpoint_);
#endif
}

void Controller::set_current_setpoint(float current_setpoint) {
    current_setpoint_ = current_setpoint;
    config_.control_mode = CTRL_MODE_CURRENT_CONTROL;
#ifdef DEBUG_PRINT
    printf("CURRENT_CONTROL %3.3f\n", current_setpoint_);
#endif
}

void Controller::move_to_pos(float goal_point) {
    axis_->trap_.planTrapezoidal(goal_point, pos_setpoint_, vel_setpoint_,
                                 axis_->trap_.config_.vel_limit,
                                 axis_->trap_.config_.accel_limit,
                                 axis_->trap_.config_.decel_limit);
    traj_start_loop_count_ = axis_->loop_counter_;
    config_.control_mode = CTRL_MODE_TRAJECTORY_CONTROL;
    goal_point_ = goal_point;
}

void Controller::move_incremental(float displacement, bool from_goal_point = true) {
    if (from_goal_point) {
        move_to_pos(goal_point_ + displacement);
    } else {
        move_to_pos(pos_setpoint_ + displacement);
    }
}

void Controller::start_anticogging_calibration() {
    // Ensure the cogging map was correctly allocated earlier and that the motor is capable of calibrating
    if (anticogging_.cogging_map != NULL && axis_->error_ == Axis::ERROR_NONE) {
        anticogging_.calib_anticogging = true;
    }
}

/*
 * This anti-cogging implementation iterates through each encoder position,
 * waits for zero velocity & position error,
 * then samples the current required to maintain that position.
 *
 * This holding current is added as a feedforward term in the control loop.
 */
bool Controller::anticogging_calibration(float pos_estimate, float vel_estimate) {
    if (anticogging_.calib_anticogging && anticogging_.cogging_map != NULL) {
        float pos_err = anticogging_.index - pos_estimate;
        if (fabsf(pos_err) <= anticogging_.calib_pos_threshold &&
            fabsf(vel_estimate) < anticogging_.calib_vel_threshold) {
            anticogging_.cogging_map[anticogging_.index++] = vel_integrator_current_;
        }
        if (anticogging_.index < axis_->encoder_.config_.cpr) {  // TODO: remove the dependency on encoder CPR
            set_pos_setpoint(anticogging_.index, 0.0f, 0.0f);
            return false;
        } else {
            anticogging_.index = 0;
            set_pos_setpoint(0.0f, 0.0f, 0.0f);   // Send the motor home
            anticogging_.use_anticogging = true;  // We're good to go, enable anti-cogging
            anticogging_.calib_anticogging = false;
            return true;
        }
    }
    return false;
}

bool Controller::update(float pos_estimate, float vel_estimate, float* current_setpoint_output) {
    // Only runs if anticogging_.calib_anticogging is true; non-blocking
    anticogging_calibration(pos_estimate, vel_estimate);
    float anticogging_pos = pos_estimate;

    // Trajectory control
    if (config_.control_mode == CTRL_MODE_TRAJECTORY_CONTROL) {
        // Note: uint32_t loop count delta is OK across overflow
        // Beware of negative deltas, as they will not be well behaved due to uint!
        float t = (axis_->loop_counter_ - traj_start_loop_count_) * current_meas_period;
        if (t > axis_->trap_.Tf_) {
            // Drop into position control mode when done to avoid problems on loop counter delta overflow
            config_.control_mode = CTRL_MODE_POSITION_CONTROL;
            // pos_setpoint already set by trajectory
            vel_setpoint_ = 0.0f;
            current_setpoint_ = 0.0f;
        } else {
            TrapezoidalTrajectory::Step_t traj_step = axis_->trap_.eval(t);
            pos_setpoint_ = traj_step.Y;
            vel_setpoint_ = traj_step.Yd;
            current_setpoint_ = traj_step.Ydd * axis_->trap_.config_.A_per_css;
        }
        anticogging_pos = pos_setpoint_;  // FF the position setpoint instead of the pos_estimate
    }

    // Ramp rate limited velocity setpoint
    if (config_.control_mode == CTRL_MODE_VELOCITY_CONTROL && vel_ramp_enable_) {
        float max_step_size = current_meas_period * config_.vel_ramp_rate;
        float full_step = vel_ramp_target_ - vel_setpoint_;
        float step;
        if (fabsf(full_step) > max_step_size) {
            step = std::copysignf(max_step_size, full_step);
        } else {
            step = full_step;
        }
        vel_setpoint_ += step;
    }

    // Position control
    // TODO Decide if we want to use encoder or pll position here
    float vel_des = vel_setpoint_;
    if (config_.control_mode >= CTRL_MODE_POSITION_CONTROL) {
        float pos_err;
        if (config_.setpoints_in_cpr) {
            // TODO this breaks the semantics that estimates come in on the arguments.
            // It's probably better to call a get_estimate that will arbitrate (enc vs sensorless) instead.
            float cpr = (float)(axis_->encoder_.config_.cpr);
            // Keep pos setpoint from drifting
            pos_setpoint_ = fmodf_pos(pos_setpoint_, cpr);
            // Circular delta
            pos_err = pos_setpoint_ - axis_->encoder_.pos_cpr_;
            pos_err = wrap_pm(pos_err, 0.5f * cpr);
        } else {
            pos_err = pos_setpoint_ - pos_estimate;
        }
        vel_des += config_.pos_gain * pos_err;
    }

    // Velocity limiting
    float vel_lim = config_.vel_limit;
    if (vel_des > vel_lim) vel_des = vel_lim;
    if (vel_des < -vel_lim) vel_des = -vel_lim;

    // Check for overspeed fault (done in this module (controller) for cohesion with vel_lim)
    if (config_.vel_limit_tolerance > 0.0f) {  // 0.0f to disable
        if (fabsf(vel_estimate) > config_.vel_limit_tolerance * vel_lim) {
            set_error(ERROR_OVERSPEED);
            return false;
        }
    }

    // Velocity control
    float Iq = current_setpoint_;

    // Anti-cogging is enabled after calibration
    // We get the current position and apply a current feed-forward
    // ensuring that we handle negative encoder positions properly (-1 == motor->encoder.encoder_cpr - 1)
    if (anticogging_.use_anticogging) {
        Iq += anticogging_.cogging_map[mod(static_cast<int>(anticogging_pos), axis_->encoder_.config_.cpr)];
    }

    float v_err = vel_des - vel_estimate;
    if (config_.control_mode >= CTRL_MODE_VELOCITY_CONTROL) {
        Iq += config_.vel_gain * v_err;
    }

    // Velocity integral action before limiting
    Iq += vel_integrator_current_;

    // Current limiting
    bool limited = false;
    float Ilim = axis_->motor_.effective_current_lim();
    if (Iq > Ilim) {
        limited = true;
        Iq = Ilim;
    }
    if (Iq < -Ilim) {
        limited = true;
        Iq = -Ilim;
    }

    // Velocity limiting in current mode
    if (config_.control_mode < CTRL_MODE_VELOCITY_CONTROL) {
        float vmax = (config_.vel_limit - fabsf(vel_estimate)) * config_.vel_gain;
        if (Iq > 0 && Iq > vmax) {
            limited = true;
            if (vmax > 0) {
                Iq = vmax;
            } else {
                Iq = 0;
            }
        } else if (Iq < 0 && Iq < -vmax) {
            limited = true;
            if (vmax > 0) {
                Iq = -vmax;
            } else {
                Iq = 0;
            }
        }
    }

    // Velocity integrator (behaviour dependent on limiting)
    if (config_.control_mode < CTRL_MODE_VELOCITY_CONTROL) {
        // reset integral if not in use
        vel_integrator_current_ = 0.0f;
    } else {
        if (limited) {
            // TODO make decayfactor configurable
            vel_integrator_current_ *= 0.99f;
        } else {
            vel_integrator_current_ += (config_.vel_integrator_gain * current_meas_period) * v_err;
        }
    }

    if (current_setpoint_output) *current_setpoint_output = Iq;
    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Characters_ToString_inl_
#define _Stroika_Foundation_Characters_ToString_inl_ 1

#include <exception>
#include <typeindex>
#include <typeinfo>
#include <wchar.h>

#include "../Configuration/Concepts.h"
#include "../Configuration/Enumeration.h"
#include "FloatConversion.h"
#include "StringBuilder.h"
#include "String_Constant.h"

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace Stroika::Foundation::Characters {

    /*
     ********************************************************************************
     ********************************* ToString *************************************
     ********************************************************************************
     */
    namespace Private_ {

        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (ToString, (x.ToString ()));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (beginenditerable, (x.begin () != x.end ()));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (pair, (x.first, x.second));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (KeyValuePair, (x.fKey, x.fValue));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (CountedValue, (x.fValue, x.fCount));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (name, (x.name (), x.name ()));

        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<has_ToString<T>::value>* = 0)
        {
            return t.ToString ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_beginenditerable<T>::value and not has_ToString<T>::value and not is_convertible_v<T, String>>* = 0)
        {
            StringBuilder sb;
            sb << L"[";
            bool didFirst{false};
            for (auto i : t) {
                if (didFirst) {
                    sb << L", ";
                }
                else {
                    sb << L" ";
                }
                sb << ToString (i);
                didFirst = true;
            }
            if (didFirst) {
                sb << L" ";
            }
            sb << L"]";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_convertible_v<T, String>>* = 0)
        {
            return static_cast<String> (t);
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_convertible_v<T, const exception&>>* = 0)
        {
            //saying Exception: first produces 'Exception: HTTP exception: status 404 (URL not found)}' - redundant. Not sure about all cases, but try this way.
            //return String_Constant {L"Exception: " } + String::FromNarrowSDKString (t.what ()) + String_Constant {L"}" };
            return String::FromNarrowSDKString (t.what ());
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_pair<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.first) << L"': " << ToString (t.second);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_KeyValuePair<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.fKey) << L"': " << ToString (t.fValue);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_CountedValue<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.fValue) << L"': " << ToString (t.fCount);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_enum_v<T>>* = 0)
        {
            // SHOULD MAYBE only do if can detect is-defined Configuration::DefaultNames<T>, but right now not easy, and
            // not a problem: just don't call this, or replace it with a specific specialization of ToString
            return Configuration::DefaultNames<T>::k.GetName (t);
        }
        template <typename T, size_t SZ>
        String ToString_array_ (const T (&arr)[SZ])
        {
            StringBuilder sb;
            sb << L"[";
            for (size_t i = 0; i < SZ; ++i) {
                sb << L" " << ToString (arr[i]);
                if (i + 1 < SZ) {
                    sb << L",";
                }
                else {
                    sb << L" ";
                }
            }
            sb << L"]";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_array_v<T> and not is_convertible_v<T, String>>* = 0)
        {
            return ToString_array_ (t);
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_floating_point_v<T>>* = 0)
        {
            return Float2String (t);
        }
        template <typename T>
        inline String ToString_ (const shared_ptr<T>& pt)
        {
            return (pt == nullptr) ? L"nullptr" : ToString (*pt);
        }
        template <typename T>
        inline String ToString_ (const optional<T>& o)
        {
            return o.has_value () ? Characters::ToString (*o) : L"[missing]";
        }
    }

    template <typename T>
    inline String ToString (const T& t)
    {
        return Private_::ToString_ (t);
    }

    template <>
    String ToString (const exception_ptr& t);
    template <>
    String ToString (const type_info& t);
    template <>
    String ToString (const type_index& t);

    String ToString (const char* t);

    /*
     * From section from section 3.9.1 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
     *      There are five standard signed integer types : signed char, short int, int,
     *      long int, and long long int. In this list, each type provides at least as much
     *      storage as those preceding it in the list.
     *      For each of the standard signed integer types, there exists a corresponding (but different)
     *      standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int,
     *      and unsigned long long int, each of which occupies the same amount of storage and has the
     *      same alignment requirements.
     */
    template <>
    String ToString (const bool& t);
    template <>
    String ToString (const signed char& t);
    template <>
    String ToString (const short int& t);
    template <>
    String ToString (const int& t);
    template <>
    String ToString (const long int& t);
    template <>
    String ToString (const long long int& t);
    template <>
    String ToString (const unsigned char& t);
    template <>
    String ToString (const unsigned short& t);
    template <>
    String ToString (const unsigned int& t);
    template <>
    String ToString (const unsigned long& t);
    template <>
    String ToString (const unsigned long long& t);

}

#endif /*_Stroika_Foundation_Characters_ToString_inl_*/
<commit_msg>ToString() on STRING surrounds with quotes (looks better in debugging output)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2018.  All rights reserved
 */
#ifndef _Stroika_Foundation_Characters_ToString_inl_
#define _Stroika_Foundation_Characters_ToString_inl_ 1

#include <exception>
#include <typeindex>
#include <typeinfo>
#include <wchar.h>

#include "../Configuration/Concepts.h"
#include "../Configuration/Enumeration.h"
#include "FloatConversion.h"
#include "StringBuilder.h"
#include "String_Constant.h"

/*
 ********************************************************************************
 ***************************** Implementation Details ***************************
 ********************************************************************************
 */
namespace Stroika::Foundation::Characters {

    /*
     ********************************************************************************
     ********************************* ToString *************************************
     ********************************************************************************
     */
    namespace Private_ {

        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (ToString, (x.ToString ()));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (beginenditerable, (x.begin () != x.end ()));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (pair, (x.first, x.second));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (KeyValuePair, (x.fKey, x.fValue));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (CountedValue, (x.fValue, x.fCount));
        STROIKA_FOUNDATION_CONFIGURATION_DEFINE_HAS (name, (x.name (), x.name ()));

        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<has_ToString<T>::value>* = 0)
        {
            return t.ToString ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_beginenditerable<T>::value and not has_ToString<T>::value and not is_convertible_v<T, String>>* = 0)
        {
            StringBuilder sb;
            sb << L"[";
            bool didFirst{false};
            for (auto i : t) {
                if (didFirst) {
                    sb << L", ";
                }
                else {
                    sb << L" ";
                }
                sb << ToString (i);
                didFirst = true;
            }
            if (didFirst) {
                sb << L" ";
            }
            sb << L"]";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_convertible_v<T, String>>* = 0)
        {
            return L"'" + static_cast<String> (t) + L"'";
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_convertible_v<T, const exception&>>* = 0)
        {
            //saying Exception: first produces 'Exception: HTTP exception: status 404 (URL not found)}' - redundant. Not sure about all cases, but try this way.
            //return String_Constant {L"Exception: " } + String::FromNarrowSDKString (t.what ()) + String_Constant {L"}" };
            return String::FromNarrowSDKString (t.what ());
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_pair<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.first) << L"': " << ToString (t.second);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_KeyValuePair<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.fKey) << L"': " << ToString (t.fValue);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        String ToString_ (const T& t, enable_if_t<has_CountedValue<T>::value>* = 0)
        {
            StringBuilder sb;
            sb << L"{";
            sb << L"'" << ToString (t.fValue) << L"': " << ToString (t.fCount);
            sb << L"}";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_enum_v<T>>* = 0)
        {
            // SHOULD MAYBE only do if can detect is-defined Configuration::DefaultNames<T>, but right now not easy, and
            // not a problem: just don't call this, or replace it with a specific specialization of ToString
            return Configuration::DefaultNames<T>::k.GetName (t);
        }
        template <typename T, size_t SZ>
        String ToString_array_ (const T (&arr)[SZ])
        {
            StringBuilder sb;
            sb << L"[";
            for (size_t i = 0; i < SZ; ++i) {
                sb << L" " << ToString (arr[i]);
                if (i + 1 < SZ) {
                    sb << L",";
                }
                else {
                    sb << L" ";
                }
            }
            sb << L"]";
            return sb.str ();
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_array_v<T> and not is_convertible_v<T, String>>* = 0)
        {
            return ToString_array_ (t);
        }
        template <typename T>
        inline String ToString_ (const T& t, enable_if_t<is_floating_point_v<T>>* = 0)
        {
            return Float2String (t);
        }
        template <typename T>
        inline String ToString_ (const shared_ptr<T>& pt)
        {
            return (pt == nullptr) ? L"nullptr" : ToString (*pt);
        }
        template <typename T>
        inline String ToString_ (const optional<T>& o)
        {
            return o.has_value () ? Characters::ToString (*o) : L"[missing]";
        }
    }

    template <typename T>
    inline String ToString (const T& t)
    {
        return Private_::ToString_ (t);
    }

    template <>
    String ToString (const exception_ptr& t);
    template <>
    String ToString (const type_info& t);
    template <>
    String ToString (const type_index& t);

    String ToString (const char* t);

    /*
     * From section from section 3.9.1 of http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
     *      There are five standard signed integer types : signed char, short int, int,
     *      long int, and long long int. In this list, each type provides at least as much
     *      storage as those preceding it in the list.
     *      For each of the standard signed integer types, there exists a corresponding (but different)
     *      standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int,
     *      and unsigned long long int, each of which occupies the same amount of storage and has the
     *      same alignment requirements.
     */
    template <>
    String ToString (const bool& t);
    template <>
    String ToString (const signed char& t);
    template <>
    String ToString (const short int& t);
    template <>
    String ToString (const int& t);
    template <>
    String ToString (const long int& t);
    template <>
    String ToString (const long long int& t);
    template <>
    String ToString (const unsigned char& t);
    template <>
    String ToString (const unsigned short& t);
    template <>
    String ToString (const unsigned int& t);
    template <>
    String ToString (const unsigned long& t);
    template <>
    String ToString (const unsigned long long& t);

}

#endif /*_Stroika_Foundation_Characters_ToString_inl_*/
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Generator_inl_
#define _Stroika_Foundation_Traversal_Generator_inl_

#include    "../Debug/Assertions.h"
#include    "IterableFromIterator.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            namespace Private_ {

                // @todo - I think we can lose fAtEnd and use the fCur.IsMissing/IsPresent()
                template    <typename T>
                struct   GenItWrapper_ : Iterator<T>::IRep  {
                    function<Memory::Optional<T>()> fFun_;
                    Memory::Optional<T> fCur_;
                    bool                fAtEnd_;
                    GenItWrapper_ (function<Memory::Optional<T>()> f)
                        : fFun_ (f)
                        , fCur_ ()
                        , fAtEnd_ (false)
                    {
                        fCur_   =   fFun_ ();
                        if (fCur_.IsMissing ()) {
                            fAtEnd_ = true;
                        }
                    }
                    virtual void    More (Memory::Optional<T>* result, bool advance) override
                    {
                        RequireNotNull (result);
                        result->clear ();
                        if (advance) {
                            Require (not fAtEnd_);
                            Memory::Optional<T> n   =   fFun_ ();
                            if (n.IsMissing ()) {
                                fAtEnd_ = true;
                            }
                            else {
                                fCur_ = n;
                            }
                        }
                        if (not fAtEnd_) {
                            Assert (fCur_.IsPresent ());
                            *result = fCur_;
                        }
                    }
                    virtual bool    Equals (const typename Iterator<T>::IRep* rhs) const override
                    {
                        RequireNotNull (rhs);
                        // No way to tell equality (some must rethink definition in Iterator<T>::Equals()!!! @todo
                        AssertMember (rhs, GenItWrapper_);
                        const GenItWrapper_&  rrhs = *dynamic_cast<const GenItWrapper_*> (rhs);
                        return fAtEnd_ == rrhs.fAtEnd_;
                    }
                    virtual typename Iterator<T>::SharedIRepPtr    Clone () const override
                    {
                        return typename Iterator<T>::SharedIRepPtr (new GenItWrapper_ (*this));
                    }
                    virtual IteratorOwnerID GetOwner () const override
                    {
                        /*
                         *  This return value allows any two DiscreteRange iterators (of the same type) to be compared.
                         */
                        return typeid (*this).name ();
                    }
                };

            }

            /**
             */
            template    <typename T>
            Iterator<T> CreateGeneratorIterator (const function<Memory::Optional<T>()>& getNext)
            {
                return Iterator<T> (typename Iterator<T>::SharedIRepPtr (new Private_::GenItWrapper_<T> (getNext)));
            }

            /**
             */
            template    <typename T>
            Iterable<T> CreateGenerator (const function<Memory::Optional<T>()>& getNext)
            {
                struct  MyIterable_ : Iterable<T> {
                    using   MyContextData_      =   function<Memory::Optional<T>()>;
                    using   MyIteratorRep_      =   typename Private_::GenItWrapper_<T>;
                    struct MyIterableRep_ : Traversal::IterableFromIterator<T, MyIteratorRep_, MyContextData_>::_Rep {
                        using   inherited       = typename Traversal::IterableFromIterator<T, MyIteratorRep_, MyContextData_>::_Rep;
                        using   _SharedPtrIRep  = typename Iterable<T>::_SharedPtrIRep;
                        DECLARE_USE_BLOCK_ALLOCATION(MyIterableRep_);
                        MyIterableRep_ (const MyContextData_& context)
                            : inherited (context)
                        {
                        }
                        virtual _SharedPtrIRep Clone (IteratorOwnerID /*forIterableEnvelope*/) const override
                        {
                            // For now - generators have no owner, so we ignore forIterableEnvelope
                            return _SharedPtrIRep (new MyIterableRep_ (*this));
                        }
                    };
                    MyIterable_ (const function<Memory::Optional<T>()>& getNext)
                        : Iterable<T> (typename Iterable<T>::_SharedPtrIRep (new MyIterableRep_ (getNext)))
                    {
                    }
                };
                return MyIterable_ (getNext);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Generator_inl_ */
<commit_msg>formatting<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#ifndef _Stroika_Foundation_Traversal_Generator_inl_
#define _Stroika_Foundation_Traversal_Generator_inl_

#include    "../Debug/Assertions.h"
#include    "IterableFromIterator.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Traversal {

            namespace Private_ {

                // @todo - I think we can lose fAtEnd and use the fCur.IsMissing/IsPresent()
                template    <typename T>
                struct   GenItWrapper_ : Iterator<T>::IRep  {
                    function<Memory::Optional<T>()> fFun_;
                    Memory::Optional<T> fCur_;
                    bool                fAtEnd_;
                    GenItWrapper_ (function<Memory::Optional<T>()> f)
                        : fFun_ (f)
                        , fCur_ ()
                        , fAtEnd_ (false)
                    {
                        fCur_   =   fFun_ ();
                        if (fCur_.IsMissing ()) {
                            fAtEnd_ = true;
                        }
                    }
                    virtual void    More (Memory::Optional<T>* result, bool advance) override
                    {
                        RequireNotNull (result);
                        result->clear ();
                        if (advance) {
                            Require (not fAtEnd_);
                            Memory::Optional<T> n   =   fFun_ ();
                            if (n.IsMissing ()) {
                                fAtEnd_ = true;
                            }
                            else {
                                fCur_ = n;
                            }
                        }
                        if (not fAtEnd_) {
                            Assert (fCur_.IsPresent ());
                            *result = fCur_;
                        }
                    }
                    virtual bool    Equals (const typename Iterator<T>::IRep* rhs) const override
                    {
                        RequireNotNull (rhs);
                        // No way to tell equality (some must rethink definition in Iterator<T>::Equals()!!! @todo
                        AssertMember (rhs, GenItWrapper_);
                        const GenItWrapper_&  rrhs = *dynamic_cast<const GenItWrapper_*> (rhs);
                        return fAtEnd_ == rrhs.fAtEnd_;
                    }
                    virtual typename Iterator<T>::SharedIRepPtr    Clone () const override
                    {
                        return typename Iterator<T>::SharedIRepPtr (new GenItWrapper_ (*this));
                    }
                    virtual IteratorOwnerID GetOwner () const override
                    {
                        /*
                         *  This return value allows any two DiscreteRange iterators (of the same type) to be compared.
                         */
                        return typeid (*this).name ();
                    }
                };

            }

            /**
             */
            template    <typename T>
            Iterator<T> CreateGeneratorIterator (const function<Memory::Optional<T>()>& getNext)
            {
                return Iterator<T> (typename Iterator<T>::SharedIRepPtr (new Private_::GenItWrapper_<T> (getNext)));
            }

            /**
             */
            template    <typename T>
            Iterable<T> CreateGenerator (const function<Memory::Optional<T>()>& getNext)
            {
                struct  MyIterable_ : Iterable<T> {
                    using   MyContextData_      =   function<Memory::Optional<T>()>;
                    using   MyIteratorRep_      =   typename Private_::GenItWrapper_<T>;
                    struct  MyIterableRep_ : Traversal::IterableFromIterator<T, MyIteratorRep_, MyContextData_>::_Rep {
                        using   inherited       = typename Traversal::IterableFromIterator<T, MyIteratorRep_, MyContextData_>::_Rep;
                        using   _SharedPtrIRep  = typename Iterable<T>::_SharedPtrIRep;
                        DECLARE_USE_BLOCK_ALLOCATION(MyIterableRep_);
                        MyIterableRep_ (const MyContextData_& context)
                            : inherited (context)
                        {
                        }
                        virtual _SharedPtrIRep Clone (IteratorOwnerID /*forIterableEnvelope*/) const override
                        {
                            // For now - generators have no owner, so we ignore forIterableEnvelope
                            return _SharedPtrIRep (new MyIterableRep_ (*this));
                        }
                    };
                    MyIterable_ (const function<Memory::Optional<T>()>& getNext)
                        : Iterable<T> (typename Iterable<T>::_SharedPtrIRep (new MyIterableRep_ (getNext)))
                    {
                    }
                };
                return MyIterable_ (getNext);
            }

        }
    }
}
#endif /* _Stroika_Foundation_Traversal_Generator_inl_ */
<|endoftext|>