<commit_before>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "root.h"
#include "objects/domain.h"
#include "utils/utils.h"
#include "utils/language.h"
#include "utils/skaffariconfig.h"
#include "../common/config.h"

#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Application>

#include <QLocale>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>

#include "../common/global.h"

using namespace Cutelyst;

Root::Root(QObject *parent) : Controller(parent)
{
}

Root::~Root()
{
}

void Root::index(Context *c)
{
	c->stash({
                 {QStringLiteral("template"), QStringLiteral("dashboard.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "Dashboard")}
             });
}

void Root::about(Context *c)
{
    QStringList description;
    description.push_back(c->translate("Root", "Skaffari is a web application for managing e-mail accounts, based on Cutelyst and written in Qt/C++. It serves as a link and access to a combination of SQL database, IMAP and SMTP server. Skaffari bundles administrative tasks such as the creation of new e-mail domains and e-mail accounts, as well as the creation of new e-mail addresses and e-mail forwards."));
    description.push_back(c->translate("Root", "Administrators can be either global or only responsible for specific domains. Individual domains and accounts can be subject to certain restrictions such as storage space, number of accounts or user names."));
    description.push_back(c->translate("Root", "Skaffari has been tested to work with Cyrus IMAP, Postfix and pam_mysql and was inspired by a PHP-based tool called web-cyradm."));
    description.push_back(c->translate("Root", "By the way, Skaffari is the Old High German word for steward."));

    QVariantList coreComponents;
    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Skaffari")},
                                             {QStringLiteral("version"), QStringLiteral(SKAFFARI_VERSION)},
                                             {QStringLiteral("url"), QStringLiteral("https://github.com/Huessenbergnetz/Skaffari")},
                                             {QStringLiteral("author"), QStringLiteral("Matthias Fehring")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://www.buschmann23.de")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Affero General Public License 3.0")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://www.gnu.org/licenses/agpl-3.0.en.html")}
                                         }));

    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Cutelyst")},
                                             {QStringLiteral("version"), QString::fromLatin1(Application::cutelystVersion())},
                                             {QStringLiteral("url"), QStringLiteral("https://www.cutelyst.org")},
                                             {QStringLiteral("author"), QStringLiteral("Daniel Nicoletti")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://dantti.wordpress.com/")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Lesser General Public License 2.1")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://www.gnu.org/licenses/lgpl-2.1.en.html")}
                                         }));
    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Qt")},
                                             {QStringLiteral("version"), QString::fromLatin1(qVersion())},
                                             {QStringLiteral("url"), QStringLiteral("https://www.qt.io/")},
                                             {QStringLiteral("author"), QStringLiteral("The Qt Company")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://www.qt.io")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Lesser General Public License 2.1")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://www.gnu.org/licenses/lgpl-2.1.en.html")}
                                         }));

    if (SkaffariConfig::useMemcached()) {
        coreComponents.push_back(QVariantMap({
                                                 {QStringLiteral("name"), QStringLiteral("libMemcached")},
                                                 {QStringLiteral("version"), QStringLiteral("1.0.18")},
                                                 {QStringLiteral("url"), QStringLiteral("http://libmemcached.org")},
                                                 {QStringLiteral("author"), QStringLiteral("Data Differential")},
                                                 {QStringLiteral("authorUrl"), QStringLiteral("http://www.datadifferential.com/")},
                                                 {QStringLiteral("license"), QStringLiteral("BSD License")},
                                                 {QStringLiteral("licenseUrl"), QStringLiteral("http://libmemcached.org/License.html")}
                                             }));
    }

    c->stash({
                 {QStringLiteral("template"), QStringLiteral("about.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "About")},
                 {QStringLiteral("core_components"), coreComponents},
                 {QStringLiteral("description"), description}
             });
}

void Root::defaultPage(Context *c)
{
    c->stash({
                 {QStringLiteral("template"), QStringLiteral("404.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "Not found")}
             });
    c->res()->setStatus(404);
}

void Root::csrfdenied(Context *c)
{
    c->res()->setStatus(403);
    Language::setLang(c);
    if (Utils::isAjax(c)) {
        c->res()->setJsonBody(QJsonObject({
                                              {QStringLiteral("error_msg"), QJsonValue(c->stash(QStringLiteral("error_msg")).toString())}
                                          }));
    } else {
        c->stash({
                     {QStringLiteral("template"), QStringLiteral("csrfdenied.html")},
                     {QStringLiteral("no_wrapper"), QStringLiteral("1")}
                 });
    }
}

bool Root::Auto(Context* c)
{
    AuthenticationUser user = Authentication::user(c);

    Language::setLang(c);

    if (c->controller() == c->controller(QStringLiteral("Login"))) {
        return true;
    }

    if (Q_UNLIKELY(user.isNull())) {
        if (Utils::isAjax(c)) {
            c->res()->setStatus(Response::Unauthorized);
            c->res()->setJsonBody(QJsonDocument(QJsonObject({
                                                                {QStringLiteral("error_msg"), QJsonValue(c->translate("Root", "You have to login at first."))}
                                                            })));
        } else {
            c->res()->redirect(c->uriFor(QStringLiteral("/login")));
        }
        return false;
    }

    StatusMessage::load(c);

    c->stash({
                 {QStringLiteral("userId"), QVariant::fromValue<dbid_t>(user.id().toULong())},
                 {QStringLiteral("userType"), user.value(QStringLiteral("type"))},
                 {QStringLiteral("userName"), user.value(QStringLiteral("username"))},
                 {QStringLiteral("userMaxDisplay"), Session::value(c, QStringLiteral("maxdisplay"), SkaffariConfig::defMaxdisplay()).value<quint8>()},
                 {QStringLiteral("userWarnLevel"), Session::value(c, QStringLiteral("warnlevel"), SkaffariConfig::defWarnlevel()).value<quint8>()}
             });

    return true;
}

#include "moc_root.cpp"
<commit_msg>Add Grantlee to about page core components (#39)<commit_after>/*
 * Skaffari - a mail account administration web interface based on Cutelyst
 * Copyright (C) 2017 Matthias Fehring <kontakt@buschmann23.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "root.h"
#include "objects/domain.h"
#include "utils/utils.h"
#include "utils/language.h"
#include "utils/skaffariconfig.h"
#include "../common/config.h"

#include <Cutelyst/Plugins/Authentication/authentication.h>
#include <Cutelyst/Plugins/StatusMessage>
#include <Cutelyst/Plugins/Session/Session>
#include <Cutelyst/Application>

#include <QLocale>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>

#include "../common/global.h"

using namespace Cutelyst;

Root::Root(QObject *parent) : Controller(parent)
{
}

Root::~Root()
{
}

void Root::index(Context *c)
{
	c->stash({
                 {QStringLiteral("template"), QStringLiteral("dashboard.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "Dashboard")}
             });
}

void Root::about(Context *c)
{
    QStringList description;
    description.push_back(c->translate("Root", "Skaffari is a web application for managing e-mail accounts, based on Cutelyst and written in Qt/C++. It serves as a link and access to a combination of SQL database, IMAP and SMTP server. Skaffari bundles administrative tasks such as the creation of new e-mail domains and e-mail accounts, as well as the creation of new e-mail addresses and e-mail forwards."));
    description.push_back(c->translate("Root", "Administrators can be either global or only responsible for specific domains. Individual domains and accounts can be subject to certain restrictions such as storage space, number of accounts or user names."));
    description.push_back(c->translate("Root", "Skaffari has been tested to work with Cyrus IMAP, Postfix and pam_mysql and was inspired by a PHP-based tool called web-cyradm."));
    description.push_back(c->translate("Root", "By the way, Skaffari is the Old High German word for steward."));

    QVariantList coreComponents;
    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Skaffari")},
                                             {QStringLiteral("version"), QStringLiteral(SKAFFARI_VERSION)},
                                             {QStringLiteral("url"), QStringLiteral("https://github.com/Huessenbergnetz/Skaffari")},
                                             {QStringLiteral("author"), QStringLiteral("Matthias Fehring")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://www.buschmann23.de")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Affero General Public License 3.0")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://github.com/Huessenbergnetz/Skaffari/blob/master/LICENSE")}
                                         }));

    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Cutelyst")},
                                             {QStringLiteral("version"), QString::fromLatin1(Application::cutelystVersion())},
                                             {QStringLiteral("url"), QStringLiteral("https://www.cutelyst.org")},
                                             {QStringLiteral("author"), QStringLiteral("Daniel Nicoletti")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://dantti.wordpress.com/")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Lesser General Public License 2.1")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://github.com/cutelyst/cutelyst/blob/master/COPYING")}
                                         }));
    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Qt")},
                                             {QStringLiteral("version"), QString::fromLatin1(qVersion())},
                                             {QStringLiteral("url"), QStringLiteral("https://www.qt.io/")},
                                             {QStringLiteral("author"), QStringLiteral("The Qt Company")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://www.qt.io")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Lesser General Public License 2.1")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://doc.qt.io/qt-5.6/lgpl.html")}
                                         }));
    coreComponents.push_back(QVariantMap({
                                             {QStringLiteral("name"), QStringLiteral("Grantlee")},
                                             {QStringLiteral("version"), QStringLiteral(GRANTLEE_VERSION)},
                                             {QStringLiteral("url"), QStringLiteral("http://www.grantlee.org")},
                                             {QStringLiteral("author"), QStringLiteral("Stephen Kelly")},
                                             {QStringLiteral("authorUrl"), QStringLiteral("https://steveire.wordpress.com/")},
                                             {QStringLiteral("license"), QStringLiteral("GNU Lesser General Public License 2.1")},
                                             {QStringLiteral("licenseUrl"), QStringLiteral("https://github.com/steveire/grantlee/blob/master/COPYING.LIB")}
                                         }));

    if (SkaffariConfig::useMemcached()) {
        coreComponents.push_back(QVariantMap({
                                                 {QStringLiteral("name"), QStringLiteral("libMemcached")},
                                                 {QStringLiteral("version"), QStringLiteral("1.0.18")},
                                                 {QStringLiteral("url"), QStringLiteral("http://libmemcached.org")},
                                                 {QStringLiteral("author"), QStringLiteral("Data Differential")},
                                                 {QStringLiteral("authorUrl"), QStringLiteral("http://www.datadifferential.com/")},
                                                 {QStringLiteral("license"), QStringLiteral("BSD License")},
                                                 {QStringLiteral("licenseUrl"), QStringLiteral("http://libmemcached.org/License.html")}
                                             }));
    }

    c->stash({
                 {QStringLiteral("template"), QStringLiteral("about.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "About")},
                 {QStringLiteral("core_components"), coreComponents},
                 {QStringLiteral("description"), description}
             });
}

void Root::defaultPage(Context *c)
{
    c->stash({
                 {QStringLiteral("template"), QStringLiteral("404.html")},
                 {QStringLiteral("site_title"), c->translate("Root", "Not found")}
             });
    c->res()->setStatus(404);
}

void Root::csrfdenied(Context *c)
{
    c->res()->setStatus(403);
    Language::setLang(c);
    if (Utils::isAjax(c)) {
        c->res()->setJsonBody(QJsonObject({
                                              {QStringLiteral("error_msg"), QJsonValue(c->stash(QStringLiteral("error_msg")).toString())}
                                          }));
    } else {
        c->stash({
                     {QStringLiteral("template"), QStringLiteral("csrfdenied.html")},
                     {QStringLiteral("no_wrapper"), QStringLiteral("1")}
                 });
    }
}

bool Root::Auto(Context* c)
{
    AuthenticationUser user = Authentication::user(c);

    Language::setLang(c);

    if (c->controller() == c->controller(QStringLiteral("Login"))) {
        return true;
    }

    if (Q_UNLIKELY(user.isNull())) {
        if (Utils::isAjax(c)) {
            c->res()->setStatus(Response::Unauthorized);
            c->res()->setJsonBody(QJsonDocument(QJsonObject({
                                                                {QStringLiteral("error_msg"), QJsonValue(c->translate("Root", "You have to login at first."))}
                                                            })));
        } else {
            c->res()->redirect(c->uriFor(QStringLiteral("/login")));
        }
        return false;
    }

    StatusMessage::load(c);

    c->stash({
                 {QStringLiteral("userId"), QVariant::fromValue<dbid_t>(user.id().toULong())},
                 {QStringLiteral("userType"), user.value(QStringLiteral("type"))},
                 {QStringLiteral("userName"), user.value(QStringLiteral("username"))},
                 {QStringLiteral("userMaxDisplay"), Session::value(c, QStringLiteral("maxdisplay"), SkaffariConfig::defMaxdisplay()).value<quint8>()},
                 {QStringLiteral("userWarnLevel"), Session::value(c, QStringLiteral("warnlevel"), SkaffariConfig::defWarnlevel()).value<quint8>()}
             });

    return true;
}

#include "moc_root.cpp"
<|endoftext|>


<commit_before>
<commit_msg>Delete SelectionSort.cpp<commit_after><|endoftext|>


<commit_before>// @(#)root/base:$Id$
// Author: Fons Rademakers   04/05/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBuffer                                                              //
//                                                                      //
// Buffer base class used for serializing objects.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBuffer.h"
#include "TClass.h"
#include "TProcessID.h"

const Int_t  kExtraSpace        = 8;   // extra space at end of buffer (used for free block count)

ClassImp(TBuffer)

//______________________________________________________________________________
static char *R__NoReAllocChar(char *, size_t, size_t)
{
   // The user has provided memory than we don't own, thus we can not extent it
   // either.
   return 0;
}

//______________________________________________________________________________
static inline ULong_t Void_Hash(const void *ptr)
{
   // Return hash value for this object.

   return TString::Hash(&ptr, sizeof(void*));
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes.

   fBufSize      = kInitialSize;
   fMode         = mode;
   fVersion      = 0;
   fParent       = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite.

   if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
   // to TBuffer via the buf argument. By default this buffer will be adopted
   // unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   if (buf) {
      fBuffer = (char *)buf;
      if (!adopt) ResetBit(kIsOwner);
   } else {
      if (fBufSize < kMinimalSize) {
         fBufSize = kMinimalSize;
      }
      fBuffer = new char[fBufSize+kExtraSpace];
   }
   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && fBufSize < kMinimalSize) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
TBuffer::~TBuffer()
{
   // Delete an I/O buffer object.

   if (TestBit(kIsOwner)) {
      //printf("Deleting fBuffer=%lx\n", fBuffer);
      delete [] fBuffer;
   }
   fBuffer = 0;
   fParent = 0;
}

//______________________________________________________________________________
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
   // new buffer is expected to have the same size as the previous buffer.
   // The current buffer position is reset to the start of the buffer.
   // If the TBuffer owned the previous buffer, it will be deleted prior
   // to accepting the new buffer. By default the new buffer will be
   // adopted unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   if (fBuffer && TestBit(kIsOwner))
      delete [] fBuffer;

   if (adopt)
      SetBit(kIsOwner);
   else
      ResetBit(kIsOwner);

   fBuffer = (char *)buf;
   fBufCur = fBuffer;
   if (newsiz > 0) {
      fBufSize = newsiz - kExtraSpace;
   }
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && fBufSize < kMinimalSize) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
void TBuffer::Expand(Int_t newsize)
{
   // Expand the I/O buffer to newsize bytes.

   Int_t l  = Length();
   fBuffer  = fReAllocFunc(fBuffer, newsize+kExtraSpace,
                           fBufSize+kExtraSpace);
   if (fBuffer == 0) {
      if (fReAllocFunc == TStorage::ReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
      } if (fReAllocFunc == R__NoReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
      } else {
         Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", fReAllocFunc);
      }
   }
   fBufSize = newsize;
   fBufCur  = fBuffer + l;
   fBufMax  = fBuffer + fBufSize;
}

//______________________________________________________________________________
TObject *TBuffer::GetParent() const
{
   // Return pointer to parent of this buffer.

   return fParent;
}

//______________________________________________________________________________
void TBuffer::SetParent(TObject *parent)
{
   // Set parent owning this buffer.

   fParent = parent;
}
//______________________________________________________________________________
ReAllocCharFun_t TBuffer::GetReAllocFunc()
{
   // Return the reallocation method currently used.
   return fReAllocFunc;
}

//______________________________________________________________________________
void  TBuffer::SetReAllocFunc(ReAllocCharFun_t reallocfunc )
{
   // Set which memory reallocation method to use.  If reallocafunc is null,
   // reset it to the defaul value (TStorage::ReAlloc)

   if (reallocfunc) {
      fReAllocFunc = reallocfunc;
   } else {
      if (TestBit(kIsOwner)) {
         fReAllocFunc = TStorage::ReAllocChar;
      } else {
         fReAllocFunc = R__NoReAllocChar;
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetReadMode()
{
   // Set buffer in read mode.

   fMode = kRead;
}

//______________________________________________________________________________
void TBuffer::SetWriteMode()
{
   // Set buffer in write mode.

   fMode = kWrite;
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const type_info &typeinfo)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(typeinfo);
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const char *className)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(className);
}

//______________________________________________________________________________
TProcessID *TBuffer::ReadProcessID(UShort_t pidf)
{
   // Return the current PRocessID.

   if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
   return 0;
}

//______________________________________________________________________________
UShort_t TBuffer::WriteProcessID(TProcessID *)
{
   // Always return 0 (current processID).

   return 0;
}
<commit_msg>Do not resize user provide buffer when the buffer is reading.  When writing only resize it when it is smaller then kExtraSpace (i.e. 8 bytes)<commit_after>// @(#)root/base:$Id$
// Author: Fons Rademakers   04/05/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBuffer                                                              //
//                                                                      //
// Buffer base class used for serializing objects.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBuffer.h"
#include "TClass.h"
#include "TProcessID.h"

const Int_t  kExtraSpace        = 8;   // extra space at end of buffer (used for free block count)

ClassImp(TBuffer)

//______________________________________________________________________________
static char *R__NoReAllocChar(char *, size_t, size_t)
{
   // The user has provided memory than we don't own, thus we can not extent it
   // either.
   return 0;
}

//______________________________________________________________________________
static inline ULong_t Void_Hash(const void *ptr)
{
   // Return hash value for this object.

   return TString::Hash(&ptr, sizeof(void*));
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes.

   fBufSize      = kInitialSize;
   fMode         = mode;
   fVersion      = 0;
   fParent       = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite.

   if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
   // to TBuffer via the buf argument. By default this buffer will be adopted
   // unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   if (buf) {
      fBuffer = (char *)buf;
      fBufSize -= kExtraSpace;
      if (!adopt) ResetBit(kIsOwner);
   } else {
      if (fBufSize < kMinimalSize) {
         fBufSize = kMinimalSize;
      }
      fBuffer = new char[fBufSize+kExtraSpace];
   }
   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
TBuffer::~TBuffer()
{
   // Delete an I/O buffer object.

   if (TestBit(kIsOwner)) {
      //printf("Deleting fBuffer=%lx\n", fBuffer);
      delete [] fBuffer;
   }
   fBuffer = 0;
   fParent = 0;
}

//______________________________________________________________________________
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
   // new buffer is expected to have the same size as the previous buffer.
   // The current buffer position is reset to the start of the buffer.
   // If the TBuffer owned the previous buffer, it will be deleted prior
   // to accepting the new buffer. By default the new buffer will be
   // adopted unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   if (fBuffer && TestBit(kIsOwner))
      delete [] fBuffer;

   if (adopt)
      SetBit(kIsOwner);
   else
      ResetBit(kIsOwner);

   fBuffer = (char *)buf;
   fBufCur = fBuffer;
   if (newsiz > 0) {
      fBufSize = newsiz - kExtraSpace;
   }
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && fBufSize < kMinimalSize) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
void TBuffer::Expand(Int_t newsize)
{
   // Expand the I/O buffer to newsize bytes.

   Int_t l  = Length();
   fBuffer  = fReAllocFunc(fBuffer, newsize+kExtraSpace,
                           fBufSize+kExtraSpace);
   if (fBuffer == 0) {
      if (fReAllocFunc == TStorage::ReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
      } if (fReAllocFunc == R__NoReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
      } else {
         Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", fReAllocFunc);
      }
   }
   fBufSize = newsize;
   fBufCur  = fBuffer + l;
   fBufMax  = fBuffer + fBufSize;
}

//______________________________________________________________________________
TObject *TBuffer::GetParent() const
{
   // Return pointer to parent of this buffer.

   return fParent;
}

//______________________________________________________________________________
void TBuffer::SetParent(TObject *parent)
{
   // Set parent owning this buffer.

   fParent = parent;
}
//______________________________________________________________________________
ReAllocCharFun_t TBuffer::GetReAllocFunc()
{
   // Return the reallocation method currently used.
   return fReAllocFunc;
}

//______________________________________________________________________________
void  TBuffer::SetReAllocFunc(ReAllocCharFun_t reallocfunc )
{
   // Set which memory reallocation method to use.  If reallocafunc is null,
   // reset it to the defaul value (TStorage::ReAlloc)

   if (reallocfunc) {
      fReAllocFunc = reallocfunc;
   } else {
      if (TestBit(kIsOwner)) {
         fReAllocFunc = TStorage::ReAllocChar;
      } else {
         fReAllocFunc = R__NoReAllocChar;
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetReadMode()
{
   // Set buffer in read mode.

   fMode = kRead;
}

//______________________________________________________________________________
void TBuffer::SetWriteMode()
{
   // Set buffer in write mode.

   fMode = kWrite;
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const type_info &typeinfo)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(typeinfo);
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const char *className)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(className);
}

//______________________________________________________________________________
TProcessID *TBuffer::ReadProcessID(UShort_t pidf)
{
   // Return the current PRocessID.

   if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
   return 0;
}

//______________________________________________________________________________
UShort_t TBuffer::WriteProcessID(TProcessID *)
{
   // Always return 0 (current processID).

   return 0;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------//
//                                                                            //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation  //
// and distributed under the MIT License (MIT).                               //
//                                                                            //
// Copyright (c) 2015 Guillaume Blanc                                         //
//                                                                            //
// Permission is hereby granted, free of charge, to any person obtaining a    //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation  //
// the rights to use, copy, modify, merge, publish, distribute, sublicense,   //
// and/or sell copies of the Software, and to permit persons to whom the      //
// Software is furnished to do so, subject to the following conditions:       //
//                                                                            //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software.                        //
//                                                                            //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        //
// DEALINGS IN THE SOFTWARE.                                                  //
//                                                                            //
//----------------------------------------------------------------------------//

#define OZZ_INCLUDE_PRIVATE_HEADER  // Allows to include private headers.

#include "animation/offline/fbx/fbx_animation.h"

#include "ozz/animation/runtime/skeleton.h"
#include "ozz/animation/runtime/skeleton_utils.h"
#include "ozz/animation/offline/raw_animation.h"

#include "ozz/base/log.h"

#include "ozz/base/maths/transform.h"

namespace ozz {
namespace animation {
namespace offline {
namespace fbx {

namespace {
bool ExtractAnimation(FbxSceneLoader* _scene_loader,
                      FbxAnimStack* anim_stack,
                      const Skeleton& _skeleton,
                      float _sampling_rate,
                      RawAnimation* _animation) {
  FbxScene* scene = _scene_loader->scene();
  assert(scene);

  // Setup Fbx animation evaluator.
  scene->SetCurrentAnimationStack(anim_stack);

  // Extract animation duration.
  FbxTimeSpan time_spawn;
  const FbxTakeInfo* take_info = scene->GetTakeInfo(anim_stack->GetName());
  if (take_info)
  {
    time_spawn = take_info->mLocalTimeSpan;
  } else {
    scene->GetGlobalSettings().GetTimelineDefaultTimeSpan(time_spawn);
  }

  float start = static_cast<float>(time_spawn.GetStart().GetSecondDouble());
  float end = static_cast<float>(time_spawn.GetStop().GetSecondDouble());

  // Animation duration could be 0 if it's just a pose. In this case we'll set a
  // default 1s duration.
  if (end > start) {
    _animation->duration = end - start;
  } else {
    _animation->duration = 1.f;
  }

  // Allocates all tracks with the same number of joints as the skeleton.
  // Tracks that would not be found will be set to skeleton bind-pose
  // transformation.
  _animation->tracks.resize(_skeleton.num_joints());

  // Iterate all skeleton joints and fills there track with key frames.
  FbxAnimEvaluator* evaluator = scene->GetAnimationEvaluator();
  for (int i = 0; i < _skeleton.num_joints(); i++) {
    RawAnimation::JointTrack& track = _animation->tracks[i];

    // Find a node that matches skeleton joint.
    const char* joint_name = _skeleton.joint_names()[i];
    FbxNode* node = scene->FindNodeByName(joint_name);

    if (!node) {
      // Empty joint track.
      ozz::log::Log() << "No animation track found for joint \"" << joint_name
        << "\". Using skeleton bind pose instead." << std::endl;

      // Get joint's bind pose.
      const ozz::math::Transform& bind_pose =
        ozz::animation::GetJointLocalBindPose(_skeleton, i);

      const RawAnimation::TranslationKey tkey = {0.f, bind_pose.translation};
      track.translations.push_back(tkey);

      const RawAnimation::RotationKey rkey = {0.f, bind_pose.rotation};
      track.rotations.push_back(rkey);

      const RawAnimation::ScaleKey skey = {0.f, bind_pose.scale};
      track.scales.push_back(skey);

      continue;
    }

    // Reserve keys in animation tracks (allocation strategy optimization
    // purpose).
    const float sampling_period = 1.f / _sampling_rate;
    const int max_keys =
      static_cast<int>(3.f + (end - start) / sampling_period);
    track.translations.reserve(max_keys);
    track.rotations.reserve(max_keys);
    track.scales.reserve(max_keys);

    // Evaluate joint transformation at the specified time.
    // Make sure to include "end" time, and enter the loop once at least.
    bool loop_again = true;
    for (float t = start; loop_again; t += sampling_period) {
      if (t >= end) {
        t = end;
        loop_again = false;
      }

      // Evaluate local transform at fbx_time.
      const ozz::math::Transform transform =
        _scene_loader->converter()->ConvertTransform(
          _skeleton.joint_properties()[i].parent == Skeleton::kNoParentIndex?
            evaluator->GetNodeGlobalTransform(node, FbxTimeSeconds(t)):
            evaluator->GetNodeLocalTransform(node, FbxTimeSeconds(t)));

      // Fills corresponding track.
      const float local_time = t - start;
      const RawAnimation::TranslationKey translation = {
        local_time, transform.translation};
      track.translations.push_back(translation);
      const RawAnimation::RotationKey rotation = {
        local_time, transform.rotation};
      track.rotations.push_back(rotation);
      const RawAnimation::ScaleKey scale = {
        local_time, transform.scale};
      track.scales.push_back(scale);
    }
  }

  // Output animation must be valid at that point.
  assert(_animation->Validate());

  return true;
}
}

bool ExtractAnimation(FbxSceneLoader* _scene_loader,
                      const Skeleton& _skeleton,
                      float _sampling_rate,
                      RawAnimation* _animation) {
  FbxScene* scene = _scene_loader->scene();
  assert(scene);

  int anim_stacks_count = scene->GetSrcObjectCount<FbxAnimStack>();

  // Early out if no animation's found.
  if(anim_stacks_count == 0) {
    ozz::log::Err() << "No animation found." << std::endl;
    return false;
  }

  if (anim_stacks_count > 1) {
    ozz::log::Log() << anim_stacks_count <<
      " animations found. Only the first one will be exported." << std::endl;
  }

  // Arbitrarily take the first animation of the stack.
  FbxAnimStack* anim_stack = scene->GetSrcObject<FbxAnimStack>(0);
  ozz::log::Log() << "Extracting animation \"" << anim_stack->GetName() << "\""
    << std::endl;
  return ExtractAnimation(_scene_loader,
                          anim_stack,
                          _skeleton,
                          _sampling_rate,
                          _animation);
}
}  // fbx
}  // offline
}  // animation
}  // ozz
<commit_msg>Pushes some logs from fbx2anim to LogV.<commit_after>//----------------------------------------------------------------------------//
//                                                                            //
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation  //
// and distributed under the MIT License (MIT).                               //
//                                                                            //
// Copyright (c) 2015 Guillaume Blanc                                         //
//                                                                            //
// Permission is hereby granted, free of charge, to any person obtaining a    //
// copy of this software and associated documentation files (the "Software"), //
// to deal in the Software without restriction, including without limitation  //
// the rights to use, copy, modify, merge, publish, distribute, sublicense,   //
// and/or sell copies of the Software, and to permit persons to whom the      //
// Software is furnished to do so, subject to the following conditions:       //
//                                                                            //
// The above copyright notice and this permission notice shall be included in //
// all copies or substantial portions of the Software.                        //
//                                                                            //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    //
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    //
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        //
// DEALINGS IN THE SOFTWARE.                                                  //
//                                                                            //
//----------------------------------------------------------------------------//

#define OZZ_INCLUDE_PRIVATE_HEADER  // Allows to include private headers.

#include "animation/offline/fbx/fbx_animation.h"

#include "ozz/animation/runtime/skeleton.h"
#include "ozz/animation/runtime/skeleton_utils.h"
#include "ozz/animation/offline/raw_animation.h"

#include "ozz/base/log.h"

#include "ozz/base/maths/transform.h"

namespace ozz {
namespace animation {
namespace offline {
namespace fbx {

namespace {
bool ExtractAnimation(FbxSceneLoader* _scene_loader,
                      FbxAnimStack* anim_stack,
                      const Skeleton& _skeleton,
                      float _sampling_rate,
                      RawAnimation* _animation) {
  FbxScene* scene = _scene_loader->scene();
  assert(scene);

  // Setup Fbx animation evaluator.
  scene->SetCurrentAnimationStack(anim_stack);

  // Extract animation duration.
  FbxTimeSpan time_spawn;
  const FbxTakeInfo* take_info = scene->GetTakeInfo(anim_stack->GetName());
  if (take_info)
  {
    time_spawn = take_info->mLocalTimeSpan;
  } else {
    scene->GetGlobalSettings().GetTimelineDefaultTimeSpan(time_spawn);
  }

  float start = static_cast<float>(time_spawn.GetStart().GetSecondDouble());
  float end = static_cast<float>(time_spawn.GetStop().GetSecondDouble());

  // Animation duration could be 0 if it's just a pose. In this case we'll set a
  // default 1s duration.
  if (end > start) {
    _animation->duration = end - start;
  } else {
    _animation->duration = 1.f;
  }

  // Allocates all tracks with the same number of joints as the skeleton.
  // Tracks that would not be found will be set to skeleton bind-pose
  // transformation.
  _animation->tracks.resize(_skeleton.num_joints());

  // Iterate all skeleton joints and fills there track with key frames.
  FbxAnimEvaluator* evaluator = scene->GetAnimationEvaluator();
  for (int i = 0; i < _skeleton.num_joints(); i++) {
    RawAnimation::JointTrack& track = _animation->tracks[i];

    // Find a node that matches skeleton joint.
    const char* joint_name = _skeleton.joint_names()[i];
    FbxNode* node = scene->FindNodeByName(joint_name);

    if (!node) {
      // Empty joint track.
      ozz::log::LogV() << "No animation track found for joint \"" << joint_name
        << "\". Using skeleton bind pose instead." << std::endl;

      // Get joint's bind pose.
      const ozz::math::Transform& bind_pose =
        ozz::animation::GetJointLocalBindPose(_skeleton, i);

      const RawAnimation::TranslationKey tkey = {0.f, bind_pose.translation};
      track.translations.push_back(tkey);

      const RawAnimation::RotationKey rkey = {0.f, bind_pose.rotation};
      track.rotations.push_back(rkey);

      const RawAnimation::ScaleKey skey = {0.f, bind_pose.scale};
      track.scales.push_back(skey);

      continue;
    }

    // Reserve keys in animation tracks (allocation strategy optimization
    // purpose).
    const float sampling_period = 1.f / _sampling_rate;
    const int max_keys =
      static_cast<int>(3.f + (end - start) / sampling_period);
    track.translations.reserve(max_keys);
    track.rotations.reserve(max_keys);
    track.scales.reserve(max_keys);

    // Evaluate joint transformation at the specified time.
    // Make sure to include "end" time, and enter the loop once at least.
    bool loop_again = true;
    for (float t = start; loop_again; t += sampling_period) {
      if (t >= end) {
        t = end;
        loop_again = false;
      }

      // Evaluate local transform at fbx_time.
      const ozz::math::Transform transform =
        _scene_loader->converter()->ConvertTransform(
          _skeleton.joint_properties()[i].parent == Skeleton::kNoParentIndex?
            evaluator->GetNodeGlobalTransform(node, FbxTimeSeconds(t)):
            evaluator->GetNodeLocalTransform(node, FbxTimeSeconds(t)));

      // Fills corresponding track.
      const float local_time = t - start;
      const RawAnimation::TranslationKey translation = {
        local_time, transform.translation};
      track.translations.push_back(translation);
      const RawAnimation::RotationKey rotation = {
        local_time, transform.rotation};
      track.rotations.push_back(rotation);
      const RawAnimation::ScaleKey scale = {
        local_time, transform.scale};
      track.scales.push_back(scale);
    }
  }

  // Output animation must be valid at that point.
  assert(_animation->Validate());

  return true;
}
}

bool ExtractAnimation(FbxSceneLoader* _scene_loader,
                      const Skeleton& _skeleton,
                      float _sampling_rate,
                      RawAnimation* _animation) {
  FbxScene* scene = _scene_loader->scene();
  assert(scene);

  int anim_stacks_count = scene->GetSrcObjectCount<FbxAnimStack>();

  // Early out if no animation's found.
  if(anim_stacks_count == 0) {
    ozz::log::Err() << "No animation found." << std::endl;
    return false;
  }

  if (anim_stacks_count > 1) {
    ozz::log::Log() << anim_stacks_count <<
      " animations found. Only the first one will be exported." << std::endl;
  }

  // Arbitrarily take the first animation of the stack.
  FbxAnimStack* anim_stack = scene->GetSrcObject<FbxAnimStack>(0);
  ozz::log::Log() << "Extracting animation \"" << anim_stack->GetName() << "\""
    << std::endl;
  return ExtractAnimation(_scene_loader,
                          anim_stack,
                          _skeleton,
                          _sampling_rate,
                          _animation);
}
}  // fbx
}  // offline
}  // animation
}  // ozz
<|endoftext|>


<commit_before>#include "Core.h"
#include "Tracker.h"

#include <map>

Core::Core()
  : mGameRunning( false ),
    mGameMode( MODE_UNKNOWN ),
    mOutcome( OUTCOME_UNKNOWN ),
    mOrder( ORDER_UNKNOWN ),
    mOwnClass( CLASS_UNKNOWN ),
    mOpponentClass( CLASS_UNKNOWN ),
    mDuration( 0 ),
    mRank( RANK_UNKNOWN ),
    mLegend( LEGEND_UNKNOWN ),
    mGameClientRestartRequired( false )
{
  mTimer = new QTimer( this );
  connect( mTimer, SIGNAL( timeout() ), this, SLOT( Tick() ) );
  mTimer->start( 1000 );

  // Connect log
  connect( &mLogTracker, SIGNAL( HandleOutcome(Outcome) ), this, SLOT( HandleOutcome(Outcome) ) );
  connect( &mLogTracker, SIGNAL( HandleOrder(GoingOrder) ), this, SLOT( HandleOrder(GoingOrder) ) );
  connect( &mLogTracker, SIGNAL( HandleOwnClass(Class) ), this, SLOT( HandleOwnClass(Class) ) ) ;
  connect( &mLogTracker, SIGNAL( HandleOpponentClass(Class) ), this, SLOT( HandleOpponentClass(Class) ) );
  connect( &mLogTracker, SIGNAL( HandleGameMode(GameMode) ), this, SLOT( HandleGameMode(GameMode) ) );
  connect( &mLogTracker, SIGNAL( HandleRank(int) ), this, SLOT( HandleRank(int) ) );
  connect( &mLogTracker, SIGNAL( HandleLegend(int) ), this, SLOT( HandleLegend(int) ) );
  connect( &mLogTracker, SIGNAL( HandleTurn(int) ), this, SLOT( HandleTurn(int) ) );

  connect( &mLogTracker, SIGNAL( HandleMatchStart() ), this, SLOT( HandleMatchStart() ) );
  connect( &mLogTracker, SIGNAL( HandleMatchEnd(const ::CardHistoryList&, bool) ), this, SLOT( HandleMatchEnd(const ::CardHistoryList&, bool) ) );

  ResetResult();
}

Core::~Core() {
  delete mTimer;
}

void Core::ResetResult() {
  mGameMode      = MODE_UNKNOWN;
  mOutcome       = OUTCOME_UNKNOWN;
  mOrder         = ORDER_UNKNOWN;
  mOwnClass      = CLASS_UNKNOWN;
  mOpponentClass = CLASS_UNKNOWN;
  mDuration      = 0;
  mCardHistoryList.clear();
  mRank          = RANK_UNKNOWN;
  mLegend        = LEGEND_UNKNOWN;

  mRanks.clear();
}

void Core::Tick() {
  bool wasGameRunning = mGameRunning;
  mGameRunning = Hearthstone::Instance()->Running();

  if( wasGameRunning != mGameRunning ) {
    if( mGameRunning ) {
      LOG("Hearthstone found");
    } else {
      LOG("Hearthstone was closed");
      Hearthstone::Instance()->SetRestartRequired( false );
    }
  }

  if( mGameClientRestartRequired != Hearthstone::Instance()->RestartRequired() ) {
    mGameClientRestartRequired = Hearthstone::Instance()->RestartRequired();
    emit HandleGameClientRestartRequired( mGameClientRestartRequired );
  }
}

void Core::HandleOrder( GoingOrder order ) {
  DEBUG( "HandleOrder %s", ORDER_NAMES[ order ] );
  mOrder = order;
}

void Core::HandleOutcome( Outcome outcome ) {
  DEBUG( "HandleOutcome %s", OUTCOME_NAMES[ outcome ] );
  mOutcome = outcome;
}

void Core::HandleOwnClass( Class ownClass ) {
  DEBUG( "HandleOwnClass %s", CLASS_NAMES[ ownClass ] );
  mOwnClass = ownClass;
}

void Core::HandleOpponentClass( Class opponentClass ) {
  DEBUG( "HandleOpponentClass %s", CLASS_NAMES[ opponentClass ] );
  mOpponentClass = opponentClass;
}

void Core::HandleMatchStart() {
  DEBUG( "HandleMatchStart" );
  mDurationTimer.start();
}

void Core::HandleMatchEnd( const ::CardHistoryList& cardHistoryList, bool wasSpectating ) {
  if( wasSpectating ) {
    LOG( "Ignore spectated match" );
    ResetResult();
    return;
  }

  DEBUG( "HandleMatchEnd" );
  mCardHistoryList = cardHistoryList;
  mDuration = mDurationTimer.elapsed() / 1000;
  UploadResult();
}

void Core::HandleGameMode( GameMode mode ) {
  DEBUG( "HandleGameMode %s", MODE_NAMES[ mode ] );
  mGameMode = mode;
}

void Core::HandleRank( int rank ) {
  DEBUG( "Set Rank %d", rank );
  mRank = rank;
}

void Core::HandleLegend( int legend ) {
  DEBUG( "Set Legend %d", legend );
  mLegend = legend;
}

void Core::HandleTurn( int turn ) {
  int rank = mRankClassifier.DetectCurrentRank();
  mRanks.push_back( rank );
  DEBUG( "Turn %d. Set Rank %d", turn, rank );
}

// Screen capture can be tricky
// So capture the rank a few times during the game
// and the majority vote will be the determined rank
int Core::DetermineRank() {
  std::map< int, int > votesByRank;

  int maxVote = 0;
  int maxRank = RANK_UNKNOWN;

  for( std::vector<int>::iterator it = mRanks.begin(); it != mRanks.end(); ++it ) {
    votesByRank[ *it ] += 1;
  }

  for( std::map<int,int>::iterator it = votesByRank.begin(); it != votesByRank.end(); ++it ) {
    if( (*it).second > maxVote ) {
      maxVote = (*it).second;
      maxRank = (*it).first;
    }
  }

  return maxRank;
}

void Core::UploadResult() {
  DEBUG( "UploadResult" );

  int rank = DetermineRank();

  DEBUG( "Determined Rank: %d", rank );

  Tracker::Instance()->AddResult( mGameMode,
      mOutcome,
      mOrder,
      mOwnClass,
      mOpponentClass,
      mLogTracker.CardHistoryList(),
      mDuration,
      rank,
      mLegend );

  ResetResult();
}
<commit_msg>Add debug output<commit_after>#include "Core.h"
#include "Tracker.h"

#include <map>

Core::Core()
  : mGameRunning( false ),
    mGameMode( MODE_UNKNOWN ),
    mOutcome( OUTCOME_UNKNOWN ),
    mOrder( ORDER_UNKNOWN ),
    mOwnClass( CLASS_UNKNOWN ),
    mOpponentClass( CLASS_UNKNOWN ),
    mDuration( 0 ),
    mRank( RANK_UNKNOWN ),
    mLegend( LEGEND_UNKNOWN ),
    mGameClientRestartRequired( false )
{
  mTimer = new QTimer( this );
  connect( mTimer, SIGNAL( timeout() ), this, SLOT( Tick() ) );
  mTimer->start( 1000 );

  // Connect log
  connect( &mLogTracker, SIGNAL( HandleOutcome(Outcome) ), this, SLOT( HandleOutcome(Outcome) ) );
  connect( &mLogTracker, SIGNAL( HandleOrder(GoingOrder) ), this, SLOT( HandleOrder(GoingOrder) ) );
  connect( &mLogTracker, SIGNAL( HandleOwnClass(Class) ), this, SLOT( HandleOwnClass(Class) ) ) ;
  connect( &mLogTracker, SIGNAL( HandleOpponentClass(Class) ), this, SLOT( HandleOpponentClass(Class) ) );
  connect( &mLogTracker, SIGNAL( HandleGameMode(GameMode) ), this, SLOT( HandleGameMode(GameMode) ) );
  connect( &mLogTracker, SIGNAL( HandleRank(int) ), this, SLOT( HandleRank(int) ) );
  connect( &mLogTracker, SIGNAL( HandleLegend(int) ), this, SLOT( HandleLegend(int) ) );
  connect( &mLogTracker, SIGNAL( HandleTurn(int) ), this, SLOT( HandleTurn(int) ) );

  connect( &mLogTracker, SIGNAL( HandleMatchStart() ), this, SLOT( HandleMatchStart() ) );
  connect( &mLogTracker, SIGNAL( HandleMatchEnd(const ::CardHistoryList&, bool) ), this, SLOT( HandleMatchEnd(const ::CardHistoryList&, bool) ) );

  ResetResult();
}

Core::~Core() {
  delete mTimer;
}

void Core::ResetResult() {
  mGameMode      = MODE_UNKNOWN;
  mOutcome       = OUTCOME_UNKNOWN;
  mOrder         = ORDER_UNKNOWN;
  mOwnClass      = CLASS_UNKNOWN;
  mOpponentClass = CLASS_UNKNOWN;
  mDuration      = 0;
  mCardHistoryList.clear();
  mRank          = RANK_UNKNOWN;
  mLegend        = LEGEND_UNKNOWN;

  mRanks.clear();
}

void Core::Tick() {
  bool wasGameRunning = mGameRunning;
  mGameRunning = Hearthstone::Instance()->Running();

  if( wasGameRunning != mGameRunning ) {
    if( mGameRunning ) {
      LOG("Hearthstone found");
    } else {
      LOG("Hearthstone was closed");
      Hearthstone::Instance()->SetRestartRequired( false );
    }
  }

  if( mGameClientRestartRequired != Hearthstone::Instance()->RestartRequired() ) {
    mGameClientRestartRequired = Hearthstone::Instance()->RestartRequired();
    emit HandleGameClientRestartRequired( mGameClientRestartRequired );
  }
}

void Core::HandleOrder( GoingOrder order ) {
  DEBUG( "HandleOrder %s", ORDER_NAMES[ order ] );
  mOrder = order;
}

void Core::HandleOutcome( Outcome outcome ) {
  DEBUG( "HandleOutcome %s", OUTCOME_NAMES[ outcome ] );
  mOutcome = outcome;
}

void Core::HandleOwnClass( Class ownClass ) {
  DEBUG( "HandleOwnClass %s", CLASS_NAMES[ ownClass ] );
  mOwnClass = ownClass;
}

void Core::HandleOpponentClass( Class opponentClass ) {
  DEBUG( "HandleOpponentClass %s", CLASS_NAMES[ opponentClass ] );
  mOpponentClass = opponentClass;
}

void Core::HandleMatchStart() {
  DEBUG( "HandleMatchStart" );
  mDurationTimer.start();
}

void Core::HandleMatchEnd( const ::CardHistoryList& cardHistoryList, bool wasSpectating ) {
  if( wasSpectating ) {
    LOG( "Ignore spectated match" );
    ResetResult();
    return;
  }

  DEBUG( "HandleMatchEnd" );
  mCardHistoryList = cardHistoryList;
  mDuration = mDurationTimer.elapsed() / 1000;
  UploadResult();
}

void Core::HandleGameMode( GameMode mode ) {
  DEBUG( "HandleGameMode %s", MODE_NAMES[ mode ] );
  mGameMode = mode;
}

void Core::HandleRank( int rank ) {
  DEBUG( "Set Rank %d", rank );
  mRank = rank;
}

void Core::HandleLegend( int legend ) {
  DEBUG( "Set Legend %d", legend );
  mLegend = legend;
}

void Core::HandleTurn( int turn ) {
  int rank = mRankClassifier.DetectCurrentRank();
  mRanks.push_back( rank );
  DEBUG( "Turn %d. Set Rank %d", turn, rank );
}

// Screen capture can be tricky
// So capture the rank a few times during the game
// and the majority vote will be the determined rank
int Core::DetermineRank() {
  std::map< int, int > votesByRank;

  int maxVote = 0;
  int maxRank = RANK_UNKNOWN;

  for( std::vector<int>::iterator it = mRanks.begin(); it != mRanks.end(); ++it ) {
    votesByRank[ *it ] += 1;
  }

  for( std::map<int,int>::iterator it = votesByRank.begin(); it != votesByRank.end(); ++it ) {
    DEBUG( "Rank %d has %d votes", (*it).first, (*it).second );
    if( (*it).second > maxVote ) {
      maxVote = (*it).second;
      maxRank = (*it).first;
    }
  }

  return maxRank;
}

void Core::UploadResult() {
  DEBUG( "UploadResult" );

  int rank = DetermineRank();

  DEBUG( "Determined Rank: %d", rank );

  Tracker::Instance()->AddResult( mGameMode,
      mOutcome,
      mOrder,
      mOwnClass,
      mOpponentClass,
      mLogTracker.CardHistoryList(),
      mDuration,
      rank,
      mLegend );

  ResetResult();
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <mutex>
#include <random>
#include <math.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
#include <nix/util/util.hpp>
#include <boost/random.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <nix/base/IDimensions.hpp>

using namespace std;

namespace nix {
namespace util {

// Base32hex alphabet (RFC 4648)
const char*  ID_ALPHABET = "0123456789abcdefghijklmnopqrstuv";
// Unit scaling, SI only, substitutions for micro and ohm...
const string  PREFIXES = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|u|n|p|f|a|z|y)";
const string  UNITS = "(m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L|Ohm|%|dB|rad)";
const string  POWER = "(\\^[+-]?[1-9]\\d*)";

const map<string, double> PREFIX_FACTORS = {{"y", 1.0e-24}, {"z", 1.0e-21}, {"a", 1.0e-18}, {"f", 1.0e-15},
    {"p", 1.0e-12}, {"n",1.0e-9}, {"u", 1.0e-6}, {"m", 1.0e-3}, {"c", 1.0e-2}, {"d",1.0e-1}, {"da", 1.0e1}, {"h", 1.0e2},
    {"k", 1.0e3}, {"M",1.0e6}, {"G", 1.0e9}, {"T", 1.0e12}, {"P", 1.0e15}, {"E",1.0e18}, {"Z", 1.0e21}, {"Y", 1.0e24}};

string createId() {
    static boost::mt19937 ran(std::time(0));
    static boost::uuids::basic_random_generator<boost::mt19937> gen(&ran);
    boost::uuids::uuid u = gen();
    return boost::uuids::to_string(u);
}

string timeToStr(time_t time) {
    using namespace boost::posix_time;
    ptime timetmp = from_time_t(time);
    return to_iso_string(timetmp);
}

time_t strToTime(const string &time) {
    using namespace boost::posix_time;
    ptime timetmp(from_iso_string(time));
    ptime epoch(boost::gregorian::date(1970, 1, 1));
    return (timetmp - epoch).total_seconds();
}

time_t getTime() {
    return time(NULL);
}

void deblankString(std::string &str) {
    typedef std::string::value_type char_type;

    str.erase(std::remove_if(str.begin(),
                             str.end(),
                             [](char_type c) { return std::isblank(c); }),
              str.end());
}

std::string deblankString(const std::string &str) {
    std::string str_copy = str;
    deblankString(str_copy);
    return str_copy;
}

bool nameCheck(const std::string &name) {
    return name.find("/") == std::string::npos;
}

std::string nameSanitizer(const std::string &name) {
    std::string str_copy = name;
    size_t pos = str_copy.find("/");

    while(pos != std::string::npos) {
        str_copy = str_copy.replace(pos, 1, "_");
        pos = str_copy.find("/");
    }

    return str_copy;
}

std::string unitSanitizer(const std::string &unit) {
     std::string new_unit = deblankString(unit);
     while (new_unit.find("mu") != string::npos) {
          size_t pos = new_unit.find("mu");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     while (new_unit.find("µ") != string::npos) {
          size_t pos = new_unit.find("µ");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     return new_unit;
}

void splitUnit(const string &combinedUnit, string &prefix, string &unit, string &power) {
    boost::regex prefix_and_unit_and_power(PREFIXES + UNITS + POWER);
    boost::regex prefix_and_unit(PREFIXES + UNITS);
    boost::regex unit_and_power(UNITS + POWER);
    boost::regex unit_only(UNITS);
    boost::regex prefix_only(PREFIXES);

    if (boost::regex_match(combinedUnit, prefix_and_unit_and_power)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        string suffix = m.suffix();
        boost::regex_search(suffix, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, unit_and_power)) {
        prefix = "";
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, prefix_and_unit)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        unit = m.suffix();
        power = "";
    } else {
        unit = combinedUnit;
        prefix = "";
        power = "";
    }
}

void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits) {
    string s = compoundUnit;
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    boost::regex separator("(\\*|/)");
    boost::match_results<std::string::const_iterator> m;

    while (boost::regex_search(s, m, opt_prefix_and_unit_and_power) && (m.suffix().length() > 0)) {
        string suffix = m.suffix();
        atomicUnits.push_back(m[0]);
        s = suffix.substr(1);
    }
    atomicUnits.push_back(m[0]);
}

bool isSIUnit(const string &unit) {
    return isAtomicSIUnit(unit) || isCompoundSIUnit(unit);
}

bool isAtomicSIUnit(const string &unit) {
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    return boost::regex_match(unit, opt_prefix_and_unit_and_power);
}

bool isCompoundSIUnit(const string &unit) {
    string atomic_unit = PREFIXES + "?" + UNITS + POWER + "?";
    boost::regex compound_unit("(" + atomic_unit + "(\\*|/))+"+ atomic_unit);
    return boost::regex_match(unit, compound_unit);
}

std::string dimTypeToStr(const nix::DimensionType &dtype) {
    std::stringstream s;
    s << dtype;
    return s.str();
}

bool isScalable(const string &unitA, const string &unitB) {
    if (!(isSIUnit(unitA) && isSIUnit(unitB))) {
        return false;
    }
    string a_unit, a_prefix, a_power;
    string b_unit, b_prefix, b_power;
    splitUnit(unitA, a_prefix, a_unit, a_power);
    splitUnit(unitB, b_prefix, b_unit, b_power);
    if (!(a_unit == b_unit) || !(a_power == b_power) ) {
        return false;
    }
    return true;
}

bool isScalable(const vector<string> &unitsA, const vector<string> &unitsB) {
    bool scalable = true;

    if (unitsA.size() != unitsB.size()) {
        return false;
    }

    auto itA = unitsA.begin();
    auto itB = unitsB.begin();
    while (scalable && itA != unitsA.end()) {
        scalable = isScalable(*itA, *itB);
        ++itA;
        ++itB;
    }

    return scalable;
}

bool isSetAtSamePos(const vector<string> &unitsA, const vector<string> &unitsB) {
    bool set_same = true;

    if (unitsA.size() != unitsB.size()) {
        return false;
    }

    auto itA = unitsA.begin();
    auto itB = unitsB.begin();
    while (set_same && itA != unitsA.end()) {
        set_same = (*itA).empty() == (*itB).empty();
        ++itA;
        ++itB;
    }

    return set_same;
}

double getSIScaling(const string &originUnit, const string &destinationUnit) {
    double scaling = 1.0;
    if (!isScalable(originUnit, destinationUnit)) {
        throw nix::InvalidUnit("Origin unit and destination unit are not scalable versions of the same SI unit!",
                               "nix::util::getSIScaling");
    }

    string org_unit, org_prefix, org_power;
    string dest_unit, dest_prefix, dest_power;
    splitUnit(originUnit, org_prefix, org_unit, org_power);
    splitUnit(destinationUnit, dest_prefix, dest_unit, dest_power);

    if ((org_prefix == dest_prefix) && (org_power == dest_power)) {
        return scaling;
    }
    if (dest_prefix.empty() && !org_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix);
    } else if (org_prefix.empty() && !dest_prefix.empty()) {
        scaling = 1.0 / PREFIX_FACTORS.at(dest_prefix);
    } else if (!org_prefix.empty() && !dest_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix) / PREFIX_FACTORS.at(dest_prefix);
    }
    if (!org_power.empty()) {
        int power = std::stoi(org_power);
        scaling = pow(scaling, power);
    }
    return scaling;
}

void applyPolynomial(const std::vector<double> &coefficients,
                     double origin,
                     const double *input,
                     double *output,
                     size_t n) {

    if (!coefficients.size()) {
        // if we have no coefficients, i.e no polynomial specified we
        // should still apply the the origin transformation
        for (size_t k = 0; k < n; k++) {
            output[k] = input[k] - origin;
        }

    } else {

        for (size_t k = 0; k < n; k++) {
            const double x = input[k] - origin;
            double value = 0.0;
            double term = 1.0;
            for (size_t i = 0; i < coefficients.size(); i++) {
                value += coefficients[i] * term;
                term *= x;
            }
            output[k] = value;
        }
    }
}

bool looksLikeUUID(const std::string &id) {
    // we don't want a complete check, just a glance
    // uuid form is: 8-4-4-4-12 = 36 [8, 13, 18, 23, ]
    return id.size() == 36 && id[8] == '-' && id[13] == '-' && id[18] == '-' && id[23] =='-';
}

} // namespace util
} // namespace nix
<commit_msg>[win] debankString: only pass args > 0 to isblank<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <string>
#include <cstdlib>
#include <mutex>
#include <random>
#include <math.h>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>
#include <nix/util/util.hpp>
#include <boost/random.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <nix/base/IDimensions.hpp>

using namespace std;

namespace nix {
namespace util {

// Base32hex alphabet (RFC 4648)
const char*  ID_ALPHABET = "0123456789abcdefghijklmnopqrstuv";
// Unit scaling, SI only, substitutions for micro and ohm...
const string  PREFIXES = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|u|n|p|f|a|z|y)";
const string  UNITS = "(m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L|Ohm|%|dB|rad)";
const string  POWER = "(\\^[+-]?[1-9]\\d*)";

const map<string, double> PREFIX_FACTORS = {{"y", 1.0e-24}, {"z", 1.0e-21}, {"a", 1.0e-18}, {"f", 1.0e-15},
    {"p", 1.0e-12}, {"n",1.0e-9}, {"u", 1.0e-6}, {"m", 1.0e-3}, {"c", 1.0e-2}, {"d",1.0e-1}, {"da", 1.0e1}, {"h", 1.0e2},
    {"k", 1.0e3}, {"M",1.0e6}, {"G", 1.0e9}, {"T", 1.0e12}, {"P", 1.0e15}, {"E",1.0e18}, {"Z", 1.0e21}, {"Y", 1.0e24}};

string createId() {
    static boost::mt19937 ran(std::time(0));
    static boost::uuids::basic_random_generator<boost::mt19937> gen(&ran);
    boost::uuids::uuid u = gen();
    return boost::uuids::to_string(u);
}

string timeToStr(time_t time) {
    using namespace boost::posix_time;
    ptime timetmp = from_time_t(time);
    return to_iso_string(timetmp);
}

time_t strToTime(const string &time) {
    using namespace boost::posix_time;
    ptime timetmp(from_iso_string(time));
    ptime epoch(boost::gregorian::date(1970, 1, 1));
    return (timetmp - epoch).total_seconds();
}

time_t getTime() {
    return time(NULL);
}

void deblankString(std::string &str) {
    typedef std::string::value_type char_type;

    // c > 0 check is for windows where isblank asserts c > -1 && < 256
    str.erase(std::remove_if(str.begin(),
                             str.end(),
                             [](char_type c) { return c > 0 && std::isblank(c); }),
              str.end());
}

std::string deblankString(const std::string &str) {
    std::string str_copy = str;
    deblankString(str_copy);
    return str_copy;
}

bool nameCheck(const std::string &name) {
    return name.find("/") == std::string::npos;
}

std::string nameSanitizer(const std::string &name) {
    std::string str_copy = name;
    size_t pos = str_copy.find("/");

    while(pos != std::string::npos) {
        str_copy = str_copy.replace(pos, 1, "_");
        pos = str_copy.find("/");
    }

    return str_copy;
}

std::string unitSanitizer(const std::string &unit) {
     std::string new_unit = deblankString(unit);
     while (new_unit.find("mu") != string::npos) {
          size_t pos = new_unit.find("mu");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     while (new_unit.find("µ") != string::npos) {
          size_t pos = new_unit.find("µ");
          new_unit = new_unit.replace(pos, 2, "u");
     }
     return new_unit;
}

void splitUnit(const string &combinedUnit, string &prefix, string &unit, string &power) {
    boost::regex prefix_and_unit_and_power(PREFIXES + UNITS + POWER);
    boost::regex prefix_and_unit(PREFIXES + UNITS);
    boost::regex unit_and_power(UNITS + POWER);
    boost::regex unit_only(UNITS);
    boost::regex prefix_only(PREFIXES);

    if (boost::regex_match(combinedUnit, prefix_and_unit_and_power)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        string suffix = m.suffix();
        boost::regex_search(suffix, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, unit_and_power)) {
        prefix = "";
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, unit_only);
        unit = m[0];
        power = m.suffix();
        power = power.substr(1);
    } else if (boost::regex_match(combinedUnit, prefix_and_unit)) {
        boost::match_results<std::string::const_iterator> m;
        boost::regex_search(combinedUnit, m, prefix_only);
        prefix = m[0];
        unit = m.suffix();
        power = "";
    } else {
        unit = combinedUnit;
        prefix = "";
        power = "";
    }
}

void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits) {
    string s = compoundUnit;
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    boost::regex separator("(\\*|/)");
    boost::match_results<std::string::const_iterator> m;

    while (boost::regex_search(s, m, opt_prefix_and_unit_and_power) && (m.suffix().length() > 0)) {
        string suffix = m.suffix();
        atomicUnits.push_back(m[0]);
        s = suffix.substr(1);
    }
    atomicUnits.push_back(m[0]);
}

bool isSIUnit(const string &unit) {
    return isAtomicSIUnit(unit) || isCompoundSIUnit(unit);
}

bool isAtomicSIUnit(const string &unit) {
    boost::regex opt_prefix_and_unit_and_power(PREFIXES + "?" + UNITS + POWER + "?");
    return boost::regex_match(unit, opt_prefix_and_unit_and_power);
}

bool isCompoundSIUnit(const string &unit) {
    string atomic_unit = PREFIXES + "?" + UNITS + POWER + "?";
    boost::regex compound_unit("(" + atomic_unit + "(\\*|/))+"+ atomic_unit);
    return boost::regex_match(unit, compound_unit);
}

std::string dimTypeToStr(const nix::DimensionType &dtype) {
    std::stringstream s;
    s << dtype;
    return s.str();
}

bool isScalable(const string &unitA, const string &unitB) {
    if (!(isSIUnit(unitA) && isSIUnit(unitB))) {
        return false;
    }
    string a_unit, a_prefix, a_power;
    string b_unit, b_prefix, b_power;
    splitUnit(unitA, a_prefix, a_unit, a_power);
    splitUnit(unitB, b_prefix, b_unit, b_power);
    if (!(a_unit == b_unit) || !(a_power == b_power) ) {
        return false;
    }
    return true;
}

bool isScalable(const vector<string> &unitsA, const vector<string> &unitsB) {
    bool scalable = true;

    if (unitsA.size() != unitsB.size()) {
        return false;
    }

    auto itA = unitsA.begin();
    auto itB = unitsB.begin();
    while (scalable && itA != unitsA.end()) {
        scalable = isScalable(*itA, *itB);
        ++itA;
        ++itB;
    }

    return scalable;
}

bool isSetAtSamePos(const vector<string> &unitsA, const vector<string> &unitsB) {
    bool set_same = true;

    if (unitsA.size() != unitsB.size()) {
        return false;
    }

    auto itA = unitsA.begin();
    auto itB = unitsB.begin();
    while (set_same && itA != unitsA.end()) {
        set_same = (*itA).empty() == (*itB).empty();
        ++itA;
        ++itB;
    }

    return set_same;
}

double getSIScaling(const string &originUnit, const string &destinationUnit) {
    double scaling = 1.0;
    if (!isScalable(originUnit, destinationUnit)) {
        throw nix::InvalidUnit("Origin unit and destination unit are not scalable versions of the same SI unit!",
                               "nix::util::getSIScaling");
    }

    string org_unit, org_prefix, org_power;
    string dest_unit, dest_prefix, dest_power;
    splitUnit(originUnit, org_prefix, org_unit, org_power);
    splitUnit(destinationUnit, dest_prefix, dest_unit, dest_power);

    if ((org_prefix == dest_prefix) && (org_power == dest_power)) {
        return scaling;
    }
    if (dest_prefix.empty() && !org_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix);
    } else if (org_prefix.empty() && !dest_prefix.empty()) {
        scaling = 1.0 / PREFIX_FACTORS.at(dest_prefix);
    } else if (!org_prefix.empty() && !dest_prefix.empty()) {
        scaling = PREFIX_FACTORS.at(org_prefix) / PREFIX_FACTORS.at(dest_prefix);
    }
    if (!org_power.empty()) {
        int power = std::stoi(org_power);
        scaling = pow(scaling, power);
    }
    return scaling;
}

void applyPolynomial(const std::vector<double> &coefficients,
                     double origin,
                     const double *input,
                     double *output,
                     size_t n) {

    if (!coefficients.size()) {
        // if we have no coefficients, i.e no polynomial specified we
        // should still apply the the origin transformation
        for (size_t k = 0; k < n; k++) {
            output[k] = input[k] - origin;
        }

    } else {

        for (size_t k = 0; k < n; k++) {
            const double x = input[k] - origin;
            double value = 0.0;
            double term = 1.0;
            for (size_t i = 0; i < coefficients.size(); i++) {
                value += coefficients[i] * term;
                term *= x;
            }
            output[k] = value;
        }
    }
}

bool looksLikeUUID(const std::string &id) {
    // we don't want a complete check, just a glance
    // uuid form is: 8-4-4-4-12 = 36 [8, 13, 18, 23, ]
    return id.size() == 36 && id[8] == '-' && id[13] == '-' && id[18] == '-' && id[23] =='-';
}

} // namespace util
} // namespace nix
<|endoftext|>


<commit_before>#include "scene.hh"

#include <libnova/transform.h>

#include "drawer.hh"

namespace scene
{

Scene::Scene(const std::shared_ptr<Projection> & projection)
    : projection_(projection),
      scene_{"", "root", {}}
{
}

void Scene::add_group(Group && group)
{
    scene_.elements.push_back(std::move(group));
}

namespace
{

ln_equ_posn hrz_to_equ(ln_hrz_posn in, ln_lnlat_posn observer, double t)
{
    ln_equ_posn out;
    ln_get_equ_from_hrz(&in, &observer, t, &out);
    return out;
}

void create_parallel_grid(
    scene::Group & group, const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    for (double y{grid.start.val} ; y <= grid.end.val ; y += grid.step.val)
    {
        std::vector<ln_equ_posn> path;
        for (double x{0} ; x < 360.1 ; x += grid.density.val)
        {
            switch (grid.coordinates)
            {
                case Coordinates::Equatorial:
                    path.push_back({x, y});
                    break;
                case Coordinates::Horizontal:
                    path.push_back(hrz_to_equ({x, y}, observer, t));
                    break;
            }
        }
        auto bezier(create_bezier_from_path(projection, path));
        for (auto const & b : bezier)
            group.elements.push_back(scene::Path{b});
    }
}

void create_meridian_grid(
    scene::Group & group, const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    for (double x{0} ; x <= 360.1 ; x += grid.step.val)
    {
        std::vector<ln_equ_posn> path;
        for (double y{grid.start.val} ; y <= grid.end.val ; y += grid.density.val)
        {
            switch (grid.coordinates)
            {
                case Coordinates::Equatorial:
                    path.push_back({x, y});
                    break;
                case Coordinates::Horizontal:
                    ln_hrz_posn in{x, y};
                    ln_equ_posn out;
                    ln_get_equ_from_hrz(&in, &observer, t, &out);
                    path.push_back(out);
                    break;
            }
        }
        auto bezier(create_bezier_from_path(projection, path));
        for (auto const & b : bezier)
            group.elements.push_back(scene::Path{b});
    }
}

}

scene::Group build_grid(
    const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    scene::Group group{"grid", grid.name, {}};
    switch (grid.plane)
    {
        case Plane::Parallel:
        {
            create_parallel_grid(group, grid, projection, observer, t);
            break;
        }
        case Plane::Meridian:
        {
            create_meridian_grid(group, grid, projection, observer, t);
            break;
        }
    }
    return group;
}

scene::Group build_track(
    const Track & track,
    const std::shared_ptr<Projection> & projection,
    const SolarObjectManager & solar_manager)
{
    scene::Group group{"track", track.name, {}};
    auto path(create_path_from_track(projection, track, solar_manager.get(track.name)));
    auto beziers(create_bezier_from_path(path));
    for (auto const & b : beziers)
    {
        group.elements.push_back(scene::Path{b});
    }

    if (path.size() >= 2)
    {
        auto blind_beziered(interpolate_bezier(path));
        for (int i(0), i_end(blind_beziered.size());
             i < i_end; i += track.interval_ticks)
        {
            auto p(blind_beziered[i]);
            group.elements.push_back(scene::DirectedObject{p.p, p.perpendicular});
        }
    }
    return group;
}

scene::Group build_tick(
    const Tick & tick,
    const std::shared_ptr<Projection> & projection)
{
    scene::Group group{"tick", tick.name, {}};
    switch (tick.plane)
    {
        case Plane::Parallel:
            for (double x{tick.start.val} ; x <= tick.end.val ; x += tick.step.val)
            {
                std::string str;
                if (tick.display == Tick::as_hours)
                    str = stringify(angle{x}, as_hour);
                else
                    str = stringify(angle{x}, as_degree);

                group.elements.push_back(scene::Text{str, projection->project({x, tick.base.val})});
            }
            break;
        case Plane::Meridian:
            for (double y{tick.start.val} ; y <= tick.end.val ; y += tick.step.val)
            {
                std::string str;
                if (tick.display == Tick::as_hours)
                    str = stringify(angle{y}, as_hour);
                else
                    str = stringify(angle{y}, as_degree);

                group.elements.push_back(scene::Text{str, projection->project({tick.base.val, y})});
            }
            break;
    }
    return group;
}

}
<commit_msg>extract some common code<commit_after>#include "scene.hh"

#include <libnova/transform.h>

#include "drawer.hh"

namespace scene
{

Scene::Scene(const std::shared_ptr<Projection> & projection)
    : projection_(projection),
      scene_{"", "root", {}}
{
}

void Scene::add_group(Group && group)
{
    scene_.elements.push_back(std::move(group));
}

namespace
{

ln_equ_posn convert_to_equ(Coordinates coord, std::pair<double, double> in, ln_lnlat_posn observer, double t)
{
    switch(coord)
    {
        case Coordinates::Equatorial:
            return ln_equ_posn{in.first, in.second};
        case Coordinates::Horizontal:
            ln_hrz_posn hin{in.first, in.second};
            ln_equ_posn out;
            ln_get_equ_from_hrz(&hin, &observer, t, &out);
            return out;
    }
}

void create_parallel_grid(
    scene::Group & group, const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    for (double y{grid.start.val} ; y <= grid.end.val ; y += grid.step.val)
    {
        std::vector<ln_equ_posn> path;
        for (double x{0} ; x < 360.1 ; x += grid.density.val)
        {
            path.push_back(convert_to_equ(grid.coordinates, {x, y}, observer, t));
        }
        auto bezier(create_bezier_from_path(projection, path));
        for (auto const & b : bezier)
            group.elements.push_back(scene::Path{b});
    }
}

void create_meridian_grid(
    scene::Group & group, const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    for (double x{0} ; x <= 360.1 ; x += grid.step.val)
    {
        std::vector<ln_equ_posn> path;
        for (double y{grid.start.val} ; y <= grid.end.val ; y += grid.density.val)
        {
            path.push_back(convert_to_equ(grid.coordinates, {x, y}, observer, t));
        }
        auto bezier(create_bezier_from_path(projection, path));
        for (auto const & b : bezier)
            group.elements.push_back(scene::Path{b});
    }
}

}

scene::Group build_grid(
    const Grid grid,
    const std::shared_ptr<Projection> & projection,
    ln_lnlat_posn observer, double t)
{
    scene::Group group{"grid", grid.name, {}};
    switch (grid.plane)
    {
        case Plane::Parallel:
        {
            create_parallel_grid(group, grid, projection, observer, t);
            break;
        }
        case Plane::Meridian:
        {
            create_meridian_grid(group, grid, projection, observer, t);
            break;
        }
    }
    return group;
}

scene::Group build_track(
    const Track & track,
    const std::shared_ptr<Projection> & projection,
    const SolarObjectManager & solar_manager)
{
    scene::Group group{"track", track.name, {}};
    auto path(create_path_from_track(projection, track, solar_manager.get(track.name)));
    auto beziers(create_bezier_from_path(path));
    for (auto const & b : beziers)
    {
        group.elements.push_back(scene::Path{b});
    }

    if (path.size() >= 2)
    {
        auto blind_beziered(interpolate_bezier(path));
        for (int i(0), i_end(blind_beziered.size());
             i < i_end; i += track.interval_ticks)
        {
            auto p(blind_beziered[i]);
            group.elements.push_back(scene::DirectedObject{p.p, p.perpendicular});
        }
    }
    return group;
}

scene::Group build_tick(
    const Tick & tick,
    const std::shared_ptr<Projection> & projection)
{
    scene::Group group{"tick", tick.name, {}};
    switch (tick.plane)
    {
        case Plane::Parallel:
            for (double x{tick.start.val} ; x <= tick.end.val ; x += tick.step.val)
            {
                std::string str;
                if (tick.display == Tick::as_hours)
                    str = stringify(angle{x}, as_hour);
                else
                    str = stringify(angle{x}, as_degree);

                group.elements.push_back(scene::Text{str, projection->project({x, tick.base.val})});
            }
            break;
        case Plane::Meridian:
            for (double y{tick.start.val} ; y <= tick.end.val ; y += tick.step.val)
            {
                std::string str;
                if (tick.display == Tick::as_hours)
                    str = stringify(angle{y}, as_hour);
                else
                    str = stringify(angle{y}, as_degree);

                group.elements.push_back(scene::Text{str, projection->project({tick.base.val, y})});
            }
            break;
    }
    return group;
}

}
<|endoftext|>