<commit_before>#include "network.h"
Network::Network(QString identityMessage,QObject *parent, int port, int broadcastInterval, int timeoutInterval) : QObject(parent)
{
    qRegisterMetaType<QHostAddress>("QHostAddress");

    //creates Thread for UDP and moves thread to QObject
    udpThread = new QThread;
    udp = new MyUDP(identityMessage,0, port, broadcastInterval, timeoutInterval);
    udp->moveToThread(udpThread);
    udpThread->start();

    connect(udp->cList,SIGNAL(newClientAdded(QHostAddress)),this,SLOT(newClientFoundSLOT(QHostAddress)));
    connect(udp->cList,SIGNAL(clientGotInactive(QHostAddress)),this,SLOT(clientGotInactiveSLOT(QHostAddress)));
    connect(this,SIGNAL(removeClientExternSIGNAL(QHostAddress)),udp->cList,SLOT(removeHostExtern(QHostAddress)));
    connect(udp->cList,SIGNAL(clientListchanged()),this,SLOT(clientListChangedSLOT()));

}

Network::~Network()
{
    udp->deleteLater();
    udpThread->quit();
    udpThread->wait();
    udpThread->deleteLater();
}

/*
*  returns QList of all active clients
*  To catch all changes, call function
*  after "clientListChanged()" is emitted */
QList<QHostAddress> Network::getClientList()
{
    return udp->cList->getClientList();
}

/* removes client from list due to an external
*  reason (f.e. no TCP response)
*  when the client reconnects, the signals
*  "newClientAdded" and "clientListChanged"
*  are emitted again */
void Network::removeClientExtern(QHostAddress address)
{
    emit removeClientExternSIGNAL(address);
}

// internal signal routing
void Network::clientGotInactiveSLOT(QHostAddress address)
{
    emit clientGotInactive(address);
}

// internal signal routing
void Network::newClientFoundSLOT(QHostAddress address)
{
    emit newClientFound(address);
}

// internal signal routing
void Network::clientListChangedSLOT()
{
    emit clientListChanged();
}
<commit_msg>Update network.cpp<commit_after>#include "network.h"
Network::Network(QString identityMessage,QObject *parent, int port, int broadcastInterval, int timeoutInterval) : QObject(parent)
{
    qRegisterMetaType<QHostAddress>("QHostAddress");

    //creates Thread for UDP and moves QObject to thread
    udpThread = new QThread;
    udp = new MyUDP(identityMessage,0, port, broadcastInterval, timeoutInterval);
    udp->moveToThread(udpThread);
    udpThread->start();

    connect(udp->cList,SIGNAL(newClientAdded(QHostAddress)),this,SLOT(newClientFoundSLOT(QHostAddress)));
    connect(udp->cList,SIGNAL(clientGotInactive(QHostAddress)),this,SLOT(clientGotInactiveSLOT(QHostAddress)));
    connect(this,SIGNAL(removeClientExternSIGNAL(QHostAddress)),udp->cList,SLOT(removeHostExtern(QHostAddress)));
    connect(udp->cList,SIGNAL(clientListchanged()),this,SLOT(clientListChangedSLOT()));

}

Network::~Network()
{
    udp->deleteLater();
    udpThread->quit();
    udpThread->wait();
    udpThread->deleteLater();
}

/*
*  returns QList of all active clients
*  To catch all changes, call function
*  after "clientListChanged()" is emitted */
QList<QHostAddress> Network::getClientList()
{
    return udp->cList->getClientList();
}

/* removes client from list due to an external
*  reason (f.e. no TCP response)
*  when the client reconnects, the signals
*  "newClientAdded" and "clientListChanged"
*  are emitted again */
void Network::removeClientExtern(QHostAddress address)
{
    emit removeClientExternSIGNAL(address);
}

// internal signal routing
void Network::clientGotInactiveSLOT(QHostAddress address)
{
    emit clientGotInactive(address);
}

// internal signal routing
void Network::newClientFoundSLOT(QHostAddress address)
{
    emit newClientFound(address);
}

// internal signal routing
void Network::clientListChangedSLOT()
{
    emit clientListChanged();
}
<|endoftext|>


<commit_before>/* Copyright (C) 2009-2011, Snares <snares@users.sourceforge.net>
   Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "../mumble_plugin_win32.h"

using namespace std;

BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
BYTE *hostptr;
//BYTE *teamptr;

static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
	float h = rot[0];
	float v = rot[1];

	if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
		return false;

	h *= static_cast<float>(M_PI / 180.0f);
	v *= static_cast<float>(M_PI / 180.0f);

	// Seems CSS is in inches. INCHES?!?
	opos[0] = pos[0] / 39.37f;
	opos[1] = pos[2] / 39.37f;
	opos[2] = pos[1] / 39.37f;

	front[0] = cos(v) * cos(h);
	front[1] = -sin(h);
	front[2] = sin(v) * cos(h);

	h -= static_cast<float>(M_PI / 2.0f);

	top[0] = cos(v) * cos(h);
	top[1] = -sin(h);
	top[2] = sin(v) * cos(h);

	return true;
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, string &context, wstring &) {
	for (int i=0;i<3;i++)
		avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;

	float ipos[3], rot[3];
	bool ok;
	char state;
	char chHostStr[40];
	string sHost;
	//BYTE bTeam;
	//string sTeam;
	wostringstream new_identity;
	ostringstream new_context;

	ok = peekProc(posptr, ipos, 12) &&
	     peekProc(rotptr, rot, 12) &&
	     peekProc(stateptr, &state, 1) &&
	     peekProc(hostptr, chHostStr, 40); //&&
	//peekProc(teamptr, &bTeam, 1);
	if (!ok)
		return false;

	chHostStr[39] = 0;

	sHost.assign(chHostStr);
	if (sHost.find(':')==string::npos)
		sHost.append(":27015");

	/*	switch (bTeam) {
			case 60:
				sTeam = "Terrorists";
				break;
			case 61:
				sTeam = "Counter Terrorists";
				break;
			default:
				sTeam = "Unknown";
				break;
		}
	*/

	new_context << "<context>"
	<< "<game>css</game>"
	<< "<hostport>" << sHost << "</hostport>"
	<< "</context>";
	context = new_context.str();

	//<< "<team>" << sTeam << "</team>"

	/* TODO
	new_identity << "<identity>"
			<< "<name>" << "SAS" << "</name>"
		     << "</identity>";
	identity = new_identity.str(); */

	// Check to see if you are in a server
	if (state == 0 || state == 3)
		return true; // Deactivate plugin

	ok = calcout(ipos, rot, avatar_pos, avatar_front, avatar_top);
	if (ok) {
		for (int i=0;i<3;++i) {
			camera_pos[i] = avatar_pos[i];
			camera_front[i] = avatar_front[i];
			camera_top[i] = avatar_top[i];
		}
		return true;
	}

	return false;
}

static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
	posptr = rotptr = NULL;

	if (! initialize(pids, L"hl2.exe", L"client.dll"))
		return false;

	BYTE *mod_engine=getModuleAddr(L"engine.dll");
	if (!mod_engine)
		return false;

	// Check if we really have CSS running
	/*
		position tuple:		client.dll+0x3ee0c4  (x,y,z, float)
		orientation tuple:	client.dll+0x39d504  (v,h float)
		ID string:			client.dll+0x39ee41 = "CSSpectatorGUI@@" (16 characters, text)
		spawn state:		client.dll+0x390070  (0 in main menu, 3 when at team selection menu or when not spawned, 5 for CT and 6 for T when spawned)
		ip:port string		engine.dll+0x3909C4  (zero terminated ip:port, string)
		team state:			client.dll+0x3aa133  (60 when T, 61 when CT, byte)
	*/
	// Remember addresses for later
	posptr = pModule + 0x59C8D4;
	rotptr = pModule + 0x54A4AC;
	stateptr = pModule + 0x532CE4;
	hostptr = mod_engine + 0x3E866C;
	//teamptr = pModule + 0x3aa133;

	//Gamecheck
	char sMagic[16];
	if (!peekProc(pModule + 0x54C801, sMagic, 16) || strncmp("CSSpectatorGUI@@", sMagic, 16)!=0)
		return false;

	// Check if we can get meaningful data from it
	float apos[3], afront[3], atop[3];
	float cpos[3], cfront[3], ctop[3];
	wstring sidentity;
	string scontext;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, scontext, sidentity)) {
		return true;
	} else {
		generic_unlock();
		return false;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports CSS build 4687. No identity support yet.");
}

static std::wstring description(L"Counter-Strike: Source (Build 4687)");
static std::wstring shortname(L"Counter-Strike: Source");

static int trylock1() {
	return trylock(std::multimap<std::wstring, unsigned long long int>());
}

static MumblePlugin cssplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	NULL,
	NULL,
	trylock1,
	generic_unlock,
	longdesc,
	fetch
};

static MumblePlugin2 cssplug2 = {
	MUMBLE_PLUGIN_MAGIC_2,
	MUMBLE_PLUGIN_VERSION,
	trylock
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &cssplug;
}

extern "C" __declspec(dllexport) MumblePlugin2 *getMumblePlugin2() {
	return &cssplug2;
}
<commit_msg>Update Counter Strike: Source plugin to build #4720.<commit_after>/* Copyright (C) 2009-2011, Snares <snares@users.sourceforge.net>
   Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright notice,
     this list of conditions and the following disclaimer in the documentation
     and/or other materials provided with the distribution.
   - Neither the name of the Mumble Developers nor the names of its
     contributors may be used to endorse or promote products derived from this
     software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "../mumble_plugin_win32.h"

using namespace std;

BYTE *posptr;
BYTE *rotptr;
BYTE *stateptr;
BYTE *hostptr;
//BYTE *teamptr;

static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
	float h = rot[0];
	float v = rot[1];

	if ((v < -360.0f) || (v > 360.0f) || (h < -360.0f) || (h > 360.0f))
		return false;

	h *= static_cast<float>(M_PI / 180.0f);
	v *= static_cast<float>(M_PI / 180.0f);

	// Seems CSS is in inches. INCHES?!?
	opos[0] = pos[0] / 39.37f;
	opos[1] = pos[2] / 39.37f;
	opos[2] = pos[1] / 39.37f;

	front[0] = cos(v) * cos(h);
	front[1] = -sin(h);
	front[2] = sin(v) * cos(h);

	h -= static_cast<float>(M_PI / 2.0f);

	top[0] = cos(v) * cos(h);
	top[1] = -sin(h);
	top[2] = sin(v) * cos(h);

	return true;
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, string &context, wstring &) {
	for (int i=0;i<3;i++)
		avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;

	float ipos[3], rot[3];
	bool ok;
	char state;
	char chHostStr[40];
	string sHost;
	//BYTE bTeam;
	//string sTeam;
	wostringstream new_identity;
	ostringstream new_context;

	ok = peekProc(posptr, ipos, 12) &&
	     peekProc(rotptr, rot, 12) &&
	     peekProc(stateptr, &state, 1) &&
	     peekProc(hostptr, chHostStr, 40); //&&
	//peekProc(teamptr, &bTeam, 1);
	if (!ok)
		return false;

	chHostStr[39] = 0;

	sHost.assign(chHostStr);
	if (sHost.find(':')==string::npos)
		sHost.append(":27015");

	/*	switch (bTeam) {
			case 60:
				sTeam = "Terrorists";
				break;
			case 61:
				sTeam = "Counter Terrorists";
				break;
			default:
				sTeam = "Unknown";
				break;
		}
	*/

	new_context << "<context>"
	<< "<game>css</game>"
	<< "<hostport>" << sHost << "</hostport>"
	<< "</context>";
	context = new_context.str();

	//<< "<team>" << sTeam << "</team>"

	/* TODO
	new_identity << "<identity>"
			<< "<name>" << "SAS" << "</name>"
		     << "</identity>";
	identity = new_identity.str(); */

	// Check to see if you are in a server
	if (state == 0 || state == 3)
		return true; // Deactivate plugin

	ok = calcout(ipos, rot, avatar_pos, avatar_front, avatar_top);
	if (ok) {
		for (int i=0;i<3;++i) {
			camera_pos[i] = avatar_pos[i];
			camera_front[i] = avatar_front[i];
			camera_top[i] = avatar_top[i];
		}
		return true;
	}

	return false;
}

static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
	posptr = rotptr = NULL;

	if (! initialize(pids, L"hl2.exe", L"client.dll"))
		return false;

	BYTE *mod_engine=getModuleAddr(L"engine.dll");
	if (!mod_engine)
		return false;

	// Check if we really have CSS running
	/*
		position tuple:		client.dll+0x3ee0c4  (x,y,z, float)
		orientation tuple:	client.dll+0x39d504  (v,h float)
		ID string:			client.dll+0x39ee41 = "CSSpectatorGUI@@" (16 characters, text)
		spawn state:		client.dll+0x390070  (0 in main menu, 3 when at team selection menu or when not spawned, 5 for CT and 6 for T when spawned)
		ip:port string		engine.dll+0x3909C4  (zero terminated ip:port, string)
		team state:			client.dll+0x3aa133  (60 when T, 61 when CT, byte)
	*/
	// Remember addresses for later
	posptr = pModule + 0x006C30F8;
	rotptr = pModule + 0x006C3078;
	stateptr = pModule + 0x006AA044;
	hostptr = mod_engine + 0x003E5E44;
	//teamptr = pModule + 0x3aa133;

	//Gamecheck
	char sMagic[16];
	if (!peekProc(pModule + 0x006C53C1, sMagic, 16) || strncmp("CSSpectatorGUI@@", sMagic, 16)!=0)
		return false;

	// Check if we can get meaningful data from it
	float apos[3], afront[3], atop[3];
	float cpos[3], cfront[3], ctop[3];
	wstring sidentity;
	string scontext;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, scontext, sidentity)) {
		return true;
	} else {
		generic_unlock();
		return false;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports CSS build 4720. No identity support yet.");
}

static std::wstring description(L"Counter-Strike: Source (Build 4720)");
static std::wstring shortname(L"Counter-Strike: Source");

static int trylock1() {
	return trylock(std::multimap<std::wstring, unsigned long long int>());
}

static MumblePlugin cssplug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	NULL,
	NULL,
	trylock1,
	generic_unlock,
	longdesc,
	fetch
};

static MumblePlugin2 cssplug2 = {
	MUMBLE_PLUGIN_MAGIC_2,
	MUMBLE_PLUGIN_VERSION,
	trylock
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &cssplug;
}

extern "C" __declspec(dllexport) MumblePlugin2 *getMumblePlugin2() {
	return &cssplug2;
}
<|endoftext|>


<commit_before>/*
 * Remember which servers (socket addresses) failed recently.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "failure.hxx"
#include "expiry.h"
#include "address_envelope.hxx"
#include "pool.hxx"
#include "util/djbhash.h"

#include <daemon/log.h>

#include <assert.h>
#include <string.h>
#include <time.h>
#include <errno.h>

struct failure {
    struct failure *next;

    time_t expires;

    time_t fade_expires;

    enum failure_status status;

    struct address_envelope envelope;
};

#define FAILURE_SLOTS 64

struct failure_list {
    struct pool *pool;

    struct failure *slots[FAILURE_SLOTS];
};

static struct failure_list fl;

void
failure_init(struct pool *pool)
{
    fl.pool = pool_new_libc(pool, "failure_list");
    memset(fl.slots, 0, sizeof(fl.slots));
}

void
failure_deinit(void)
{
    pool_unref(fl.pool);
}

gcc_const
static inline bool
failure_status_can_expire(enum failure_status status)
{
    return status != FAILURE_MONITOR;
}

gcc_pure
static inline bool
failure_is_expired(const struct failure *failure)
{
    assert(failure != nullptr);

    return failure_status_can_expire(failure->status) &&
        is_expired(failure->expires);
}

gcc_pure
static inline bool
failure_is_fade(const struct failure *failure)
{
    assert(failure != nullptr);

    return failure->fade_expires > 0 &&
        !is_expired(failure->fade_expires);
}

static bool
failure_override_status(struct failure *failure, time_t now,
                        enum failure_status status, unsigned duration)
{
    if (failure_is_expired(failure)) {
        /* expired: override in any case */
    } else if (status == failure->status) {
        /* same status: update expiry */
    } else if (status == FAILURE_FADE) {
        /* store "fade" expiry in special attribute, until the other
           failure status expires */
        failure->fade_expires = now + duration;
        return true;
    } else if (failure->status == FAILURE_FADE) {
        /* copy the "fade" expiry to the special attribute, and
           overwrite the FAILURE_FADE status */
        failure->fade_expires = failure->expires;
    } else if (status < failure->status)
        return false;

    failure->expires = now + duration;
    failure->status = status;
    return true;
}

void
failure_set(const struct sockaddr *addr, size_t addrlen,
            enum failure_status status, unsigned duration)
{
    assert(addr != nullptr);
    assert(status > FAILURE_OK);

    const unsigned now = now_s();

    const unsigned slot = djb_hash(addr, addrlen) % FAILURE_SLOTS;
    struct failure *failure;
    for (failure = fl.slots[slot]; failure != nullptr; failure = failure->next) {
        if (failure->envelope.length == addrlen &&
            memcmp(&failure->envelope.address, addr, addrlen) == 0) {
            failure_override_status(failure, now, status, duration);
            return;
        }
    }

    /* insert new failure object into the linked list */

    failure = (struct failure *)
        p_malloc(fl.pool, sizeof(*failure)
                 - sizeof(failure->envelope.address) + addrlen);
    failure->expires = now + duration;
    failure->fade_expires = 0;
    failure->status = status;
    failure->envelope.length = addrlen;
    memcpy(&failure->envelope.address, addr, addrlen);

    failure->next = fl.slots[slot];
    fl.slots[slot] = failure;
}

static bool
match_status(enum failure_status current, enum failure_status match)
{
    /* FAILURE_OK is a catch-all magic value */
    return match == FAILURE_OK || current == match;
}

static void
failure_unset2(struct pool *pool, struct failure **failure_r,
               struct failure *failure, enum failure_status status)
{
    if (status == FAILURE_FADE)
        failure->fade_expires = 0;

    if (!match_status(failure->status, status) &&
        !failure_is_expired(failure))
        /* don't update if the current status is more serious than the
           one to be removed */
        return;

    if (status != FAILURE_OK && failure_is_fade(failure)) {
        failure->status = FAILURE_FADE;
        failure->expires = failure->fade_expires;
        failure->fade_expires = 0;
    } else {
        *failure_r = failure->next;
        p_free(pool, failure);
    }
}

void
failure_unset(const struct sockaddr *addr, size_t addrlen,
              enum failure_status status)
{
    unsigned slot = djb_hash(addr, addrlen) % FAILURE_SLOTS;
    struct failure **failure_r, *failure;

    assert(addr != nullptr);

    for (failure_r = &fl.slots[slot], failure = *failure_r;
         failure != nullptr;
         failure_r = &failure->next, failure = *failure_r) {
        if (failure->envelope.length == addrlen &&
            memcmp(&failure->envelope.address, addr, addrlen) == 0) {
            /* found it: remove it */
            failure_unset2(fl.pool, failure_r, failure, status);
            return;
        }
    }
}

gcc_pure
static enum failure_status
failure_get_status2(const struct failure *failure)
{
    if (!failure_is_expired(failure))
        return failure->status;
    else if (failure_is_fade(failure))
        return FAILURE_FADE;
    else
        return FAILURE_OK;
}

enum failure_status
failure_get_status(const struct sockaddr *address, size_t length)
{
    unsigned slot = djb_hash(address, length) % FAILURE_SLOTS;
    struct failure *failure;

    assert(address != nullptr);
    assert(length >= sizeof(failure->envelope.address));

    for (failure = fl.slots[slot]; failure != nullptr; failure = failure->next)
        if (failure->envelope.length == length &&
            memcmp(&failure->envelope.address, address, length) == 0)
            return failure_get_status2(failure);

    return FAILURE_OK;
}
<commit_msg>failure: rename struct failure to Failure<commit_after>/*
 * Remember which servers (socket addresses) failed recently.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "failure.hxx"
#include "expiry.h"
#include "address_envelope.hxx"
#include "pool.hxx"
#include "util/djbhash.h"

#include <daemon/log.h>

#include <assert.h>
#include <string.h>
#include <time.h>
#include <errno.h>

struct Failure {
    Failure *next;

    time_t expires;

    time_t fade_expires;

    enum failure_status status;

    struct address_envelope envelope;
};

#define FAILURE_SLOTS 64

struct FailureList {
    struct pool *pool;

    Failure *slots[FAILURE_SLOTS];
};

static FailureList fl;

void
failure_init(struct pool *pool)
{
    fl.pool = pool_new_libc(pool, "failure_list");
    memset(fl.slots, 0, sizeof(fl.slots));
}

void
failure_deinit(void)
{
    pool_unref(fl.pool);
}

gcc_const
static inline bool
failure_status_can_expire(enum failure_status status)
{
    return status != FAILURE_MONITOR;
}

gcc_pure
static inline bool
failure_is_expired(const Failure *failure)
{
    assert(failure != nullptr);

    return failure_status_can_expire(failure->status) &&
        is_expired(failure->expires);
}

gcc_pure
static inline bool
failure_is_fade(const Failure *failure)
{
    assert(failure != nullptr);

    return failure->fade_expires > 0 &&
        !is_expired(failure->fade_expires);
}

static bool
failure_override_status(Failure *failure, time_t now,
                        enum failure_status status, unsigned duration)
{
    if (failure_is_expired(failure)) {
        /* expired: override in any case */
    } else if (status == failure->status) {
        /* same status: update expiry */
    } else if (status == FAILURE_FADE) {
        /* store "fade" expiry in special attribute, until the other
           failure status expires */
        failure->fade_expires = now + duration;
        return true;
    } else if (failure->status == FAILURE_FADE) {
        /* copy the "fade" expiry to the special attribute, and
           overwrite the FAILURE_FADE status */
        failure->fade_expires = failure->expires;
    } else if (status < failure->status)
        return false;

    failure->expires = now + duration;
    failure->status = status;
    return true;
}

void
failure_set(const struct sockaddr *addr, size_t addrlen,
            enum failure_status status, unsigned duration)
{
    assert(addr != nullptr);
    assert(status > FAILURE_OK);

    const unsigned now = now_s();

    const unsigned slot = djb_hash(addr, addrlen) % FAILURE_SLOTS;
    for (Failure *failure = fl.slots[slot]; failure != nullptr;
         failure = failure->next) {
        if (failure->envelope.length == addrlen &&
            memcmp(&failure->envelope.address, addr, addrlen) == 0) {
            failure_override_status(failure, now, status, duration);
            return;
        }
    }

    /* insert new failure object into the linked list */

    Failure *failure = (Failure *)
        p_malloc(fl.pool, sizeof(*failure)
                 - sizeof(failure->envelope.address) + addrlen);
    failure->expires = now + duration;
    failure->fade_expires = 0;
    failure->status = status;
    failure->envelope.length = addrlen;
    memcpy(&failure->envelope.address, addr, addrlen);

    failure->next = fl.slots[slot];
    fl.slots[slot] = failure;
}

static bool
match_status(enum failure_status current, enum failure_status match)
{
    /* FAILURE_OK is a catch-all magic value */
    return match == FAILURE_OK || current == match;
}

static void
failure_unset2(struct pool *pool, Failure **failure_r,
               Failure *failure, enum failure_status status)
{
    if (status == FAILURE_FADE)
        failure->fade_expires = 0;

    if (!match_status(failure->status, status) &&
        !failure_is_expired(failure))
        /* don't update if the current status is more serious than the
           one to be removed */
        return;

    if (status != FAILURE_OK && failure_is_fade(failure)) {
        failure->status = FAILURE_FADE;
        failure->expires = failure->fade_expires;
        failure->fade_expires = 0;
    } else {
        *failure_r = failure->next;
        p_free(pool, failure);
    }
}

void
failure_unset(const struct sockaddr *addr, size_t addrlen,
              enum failure_status status)
{
    unsigned slot = djb_hash(addr, addrlen) % FAILURE_SLOTS;
    Failure **failure_r, *failure;

    assert(addr != nullptr);

    for (failure_r = &fl.slots[slot], failure = *failure_r;
         failure != nullptr;
         failure_r = &failure->next, failure = *failure_r) {
        if (failure->envelope.length == addrlen &&
            memcmp(&failure->envelope.address, addr, addrlen) == 0) {
            /* found it: remove it */
            failure_unset2(fl.pool, failure_r, failure, status);
            return;
        }
    }
}

gcc_pure
static enum failure_status
failure_get_status2(const Failure *failure)
{
    if (!failure_is_expired(failure))
        return failure->status;
    else if (failure_is_fade(failure))
        return FAILURE_FADE;
    else
        return FAILURE_OK;
}

enum failure_status
failure_get_status(const struct sockaddr *address, size_t length)
{
    unsigned slot = djb_hash(address, length) % FAILURE_SLOTS;
    Failure *failure;

    assert(address != nullptr);
    assert(length >= sizeof(failure->envelope.address));

    for (failure = fl.slots[slot]; failure != nullptr; failure = failure->next)
        if (failure->envelope.length == length &&
            memcmp(&failure->envelope.address, address, length) == 0)
            return failure_get_status2(failure);

    return FAILURE_OK;
}
<|endoftext|>


<commit_before>#include "StressStrainDamageComputeAux.h"

template<>
InputParameters validParams<StressStrainDamageComputeAux>()
{
     InputParameters params = validParams<AuxKernel>();

     params.addParam<std::string>("quantity","stress", "output: stress, strain, pstress, pstrain or damage.");
     params.addParam<int>("component",0,"component of the stress/strain vector, 0-xx;1-yy;2-zz;3-xy;4-xz;5-yz");
     params.addParam<int>("componentb",0,"componentb of the pstress/pstrain vector, 0-xx;1-yy;2-zz");
     return params;
}

StressStrainDamageComputeAux::StressStrainDamageComputeAux(const std::string & name, InputParameters parameters)
  :AuxKernel(name, parameters),
   _quantity_string( getParam<std::string>("quantity") ),
   _component(getParam<int>("component")),
   _componentb(getParam<int>("componentb")),
   _damage_coeff(getMaterialProperty<Real>("damage_coeff")),
   _stress_normal_vector(getMaterialProperty<RealVectorValue>("stress_normal_vector")),
   _stress_shear_vector(getMaterialProperty<RealVectorValue>("stress_shear_vector")),
   _pstress_normal_vector(getMaterialProperty<RealVectorValue>("pstress_normal_vector")),
   _strain_normal_vector(getMaterialProperty<RealVectorValue>("strain_normal_vector")),
   _strain_shear_vector(getMaterialProperty<RealVectorValue>("strain_shear_vector")),
   _pstrain_normal_vector(getMaterialProperty<RealVectorValue>("pstrain_normal_vector"))
{}

Real
StressStrainDamageComputeAux::computeValue()
{

                                //damage factor
  std::transform(_quantity_string.begin(), _quantity_string.end(),
                 _quantity_string.begin(), ::tolower);
  if ( _quantity_string == "stress" )
  {
    _stress(0) = _stress_normal_vector[_qp](0);                //tau_xx
    _stress(1) = _stress_normal_vector[_qp](1);                //tau_yy
    if (_dim == 3) _stress(2) = _stress_normal_vector[_qp](2); //tau_zz
    _stress(3) = _stress_shear_vector[_qp](0);                  //tau_xy

    if (_dim == 3)
    {
      _stress(4) =  _stress_shear_vector[_qp](1);               //tau_xz
      _stress(5) =  _stress_shear_vector[_qp](2);                //tau_yz
    }
    return _stress(_component);

  }

  else if ( _quantity_string == "strain" )
  {
    _strain(0) = _strain_normal_vector[_qp](0);                //s_xx
    _strain(1) = _strain_normal_vector[_qp](1);                //s_yy
    if (_dim == 3) _strain(2) = _strain_normal_vector[_qp](2); //s_zz
    _strain(3) = _strain_shear_vector[_qp](0);                  //s_xy

    if (_dim == 3)
    {
      _strain(4) =  _strain_shear_vector[_qp](1);               //s_xz
      _strain(5) =  _strain_shear_vector[_qp](2);               //s_yz
    }
    return _strain(_component);
  }
  else if ( _quantity_string == "pstress" )
  {
    _pstress(0) = _pstress_normal_vector[_qp](0);                //ptau_xx
    _pstress(1) = _pstress_normal_vector[_qp](1);                //ptau_yy
    _pstress(2) = _pstress_normal_vector[_qp](2);                //ptau_zz

    return _pstress(_component);
  }
  else if ( _quantity_string == "pstrain" )
  {
    _pstrain(0) = _pstrain_normal_vector[_qp](0);                //ps_xx
    _pstrain(1) = _pstrain_normal_vector[_qp](1);                //ps_yy
    _pstrain(2) = _pstrain_normal_vector[_qp](2);                //ps_zz

    return _pstrain(_component);
  }
  else if ( _quantity_string == "damage" )
  {
    _damage = _damage_coeff[_qp];                              //damage factor
    return _damage;
  }
  return 0.0;

}
<commit_msg>Kay modified damaging mechanics<commit_after>#include "StressStrainDamageComputeAux.h"

template<>
InputParameters validParams<StressStrainDamageComputeAux>()
{
     InputParameters params = validParams<AuxKernel>();

     params.addParam<std::string>("quantity","stress", "output: stress, strain, pstress, pstrain or damage.");
     params.addParam<int>("component",0,"component of the stress/strain vector, 0-xx;1-yy;2-zz;3-xy;4-xz;5-yz");
     params.addParam<int>("componentb",0,"componentb of the pstress/pstrain vector, 0-xx;1-yy;2-zz");
     return params;
}

StressStrainDamageComputeAux::StressStrainDamageComputeAux(const std::string & name, InputParameters parameters)
  :AuxKernel(name, parameters),
   _quantity_string( getParam<std::string>("quantity") ),
   _component(getParam<int>("component")),
   _componentb(getParam<int>("componentb")),
   _damage_coeff(getMaterialProperty<Real>("damage_coeff")),
   _stress_normal_vector(getMaterialProperty<RealVectorValue>("stress_normal_vector")),
   _stress_shear_vector(getMaterialProperty<RealVectorValue>("stress_shear_vector")),
   _strain_normal_vector(getMaterialProperty<RealVectorValue>("strain_normal_vector")),
   _strain_shear_vector(getMaterialProperty<RealVectorValue>("strain_shear_vector")),
   _pstress_normal_vector(getMaterialProperty<RealVectorValue>("pstress_normal_vector")),
   _pstrain_normal_vector(getMaterialProperty<RealVectorValue>("pstrain_normal_vector"))
{}

Real
StressStrainDamageComputeAux::computeValue()
{

                                //damage factor
  std::transform(_quantity_string.begin(), _quantity_string.end(),
                 _quantity_string.begin(), ::tolower);
  if ( _quantity_string == "stress" )
  {
    _stress(0) = _stress_normal_vector[_qp](0);                //tau_xx
    _stress(1) = _stress_normal_vector[_qp](1);                //tau_yy
    if (_dim == 3) _stress(2) = _stress_normal_vector[_qp](2); //tau_zz
    _stress(3) = _stress_shear_vector[_qp](0);                  //tau_xy

    if (_dim == 3)
    {
      _stress(4) =  _stress_shear_vector[_qp](1);               //tau_xz
      _stress(5) =  _stress_shear_vector[_qp](2);                //tau_yz
    }
    return _stress(_component);

  }

  else if ( _quantity_string == "strain" )
  {
    _strain(0) = _strain_normal_vector[_qp](0);                //s_xx
    _strain(1) = _strain_normal_vector[_qp](1);                //s_yy
    if (_dim == 3) _strain(2) = _strain_normal_vector[_qp](2); //s_zz
    _strain(3) = _strain_shear_vector[_qp](0);                  //s_xy

    if (_dim == 3)
    {
      _strain(4) =  _strain_shear_vector[_qp](1);               //s_xz
      _strain(5) =  _strain_shear_vector[_qp](2);               //s_yz
    }
    return _strain(_component);
  }
  else if ( _quantity_string == "pstress" )
  {
    _pstress(0) = _pstress_normal_vector[_qp](0);                //ptau_xx
    _pstress(1) = _pstress_normal_vector[_qp](1);                //ptau_yy
    _pstress(2) = _pstress_normal_vector[_qp](2);                //ptau_zz

    return _pstress(_component);
  }
  else if ( _quantity_string == "pstrain" )
  {
    _pstrain(0) = _pstrain_normal_vector[_qp](0);                //ps_xx
    _pstrain(1) = _pstrain_normal_vector[_qp](1);                //ps_yy
    _pstrain(2) = _pstrain_normal_vector[_qp](2);                //ps_zz

    return _pstrain(_component);
  }
  else if ( _quantity_string == "damage" )
  {
    _damage = _damage_coeff[_qp];                              //damage factor
    return _damage;
  }
  return 0.0;

}
<|endoftext|>


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

#include <limits>

#include "chrome/browser/jankometer.h"

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "base/time.h"
#include "base/watchdog.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/common/chrome_switches.h"

#if defined(TOOLKIT_USES_GTK)
#include "chrome/browser/gtk/gtk_util.h"
#endif

using base::TimeDelta;
using base::TimeTicks;

namespace {

// The maximum threshold of delay of the message  before considering it a delay.
// For a debug build, you may want to set IO delay around 500ms.
// For a release build, setting it around 350ms is sensible.
// Visit about:histograms to see what the distribution is on your system, with
// your build. Be sure to do some work to get interesting stats.
// The numbers below came from a warm start (you'll get about 5-10 alarms with
// a cold start), and running the page-cycler for 5 rounds.
#ifdef NDEBUG
const int kMaxUIMessageDelayMs = 350;
const int kMaxIOMessageDelayMs = 200;
#else
const int kMaxUIMessageDelayMs = 500;
const int kMaxIOMessageDelayMs = 400;
#endif

// Maximum processing time (excluding queueing delay) for a message before
// considering it delayed.
const int kMaxMessageProcessingMs = 100;

// TODO(brettw) Consider making this a pref.
const bool kPlaySounds = false;

//------------------------------------------------------------------------------
// Provide a special watchdog to make it easy to set the breakpoint on this
// class only.
class JankWatchdog : public Watchdog {
 public:
  JankWatchdog(const TimeDelta& duration,
               const std::string& thread_watched_name,
               bool enabled)
      : Watchdog(duration, thread_watched_name, enabled),
        thread_name_watched_(thread_watched_name),
        alarm_count_(0) {
  }

  virtual ~JankWatchdog() {}

  virtual void Alarm() {
    // Put break point here if you want to stop threads and look at what caused
    // the jankiness.
    alarm_count_++;
    Watchdog::Alarm();
  }

 private:
  std::string thread_name_watched_;
  int alarm_count_;

  DISALLOW_COPY_AND_ASSIGN(JankWatchdog);
};

class JankObserverHelper {
 public:
  JankObserverHelper(const std::string& thread_name,
                     const TimeDelta& excessive_duration,
                     bool watchdog_enable);
  ~JankObserverHelper();

  void StartProcessingTimers(const TimeDelta& queueing_time);
  void EndProcessingTimers();

 private:
  const TimeDelta max_message_delay_;

  // Time at which the current message processing began.
  TimeTicks begin_process_message_;

  // Time the current message spent in the queue -- delta between message
  // construction time and message processing time.
  TimeDelta queueing_time_;

  // Counters for the two types of jank we measure.
  base::StatsCounter slow_processing_counter_;  // Msgs w/ long proc time.
  base::StatsCounter queueing_delay_counter_;   // Msgs w/ long queueing delay.
  scoped_refptr<base::Histogram> process_times_;  // Time spent proc. task.
  scoped_refptr<base::Histogram> total_times_;  // Total queueing plus proc.
  JankWatchdog total_time_watchdog_;  // Watching for excessive total_time.

  DISALLOW_COPY_AND_ASSIGN(JankObserverHelper);
};

JankObserverHelper::JankObserverHelper(
    const std::string& thread_name,
    const TimeDelta& excessive_duration,
    bool watchdog_enable)
    : max_message_delay_(excessive_duration),
      slow_processing_counter_(std::string("Chrome.SlowMsg") + thread_name),
      queueing_delay_counter_(std::string("Chrome.DelayMsg") + thread_name),
      total_time_watchdog_(excessive_duration, thread_name, watchdog_enable) {
  process_times_ = base::Histogram::FactoryGet(
      std::string("Chrome.ProcMsgL ") + thread_name,
      1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag);
  total_times_ = base::Histogram::FactoryGet(
      std::string("Chrome.TotalMsgL ") + thread_name,
      1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag);
}

JankObserverHelper::~JankObserverHelper() {}

// Called when a message has just begun processing, initializes
// per-message variables and timers.
void JankObserverHelper::StartProcessingTimers(const TimeDelta& queueing_time) {
  begin_process_message_ = TimeTicks::Now();
  queueing_time_ = queueing_time;

  // Simulate arming when the message entered the queue.
  total_time_watchdog_.ArmSomeTimeDeltaAgo(queueing_time_);
  if (queueing_time_ > max_message_delay_) {
    // Message is too delayed.
    queueing_delay_counter_.Increment();
#if defined(OS_WIN)
    if (kPlaySounds)
      MessageBeep(MB_ICONASTERISK);
#endif
  }
}

// Called when a message has just finished processing, finalizes
// per-message variables and timers.
void JankObserverHelper::EndProcessingTimers() {
  total_time_watchdog_.Disarm();
  TimeTicks now = TimeTicks::Now();
  if (begin_process_message_ != TimeTicks()) {
    TimeDelta processing_time = now - begin_process_message_;
    process_times_->AddTime(processing_time);
    total_times_->AddTime(queueing_time_ + processing_time);
  }
  if (now - begin_process_message_ >
      TimeDelta::FromMilliseconds(kMaxMessageProcessingMs)) {
    // Message took too long to process.
    slow_processing_counter_.Increment();
#if defined(OS_WIN)
    if (kPlaySounds)
      MessageBeep(MB_ICONHAND);
#endif
  }

  // Reset message specific times.
  begin_process_message_ = base::TimeTicks();
  queueing_time_ = base::TimeDelta();
}

//------------------------------------------------------------------------------
class IOJankObserver : public base::RefCountedThreadSafe<IOJankObserver>,
                       public MessageLoopForIO::IOObserver,
                       public MessageLoop::TaskObserver {
 public:
  IOJankObserver(const char* thread_name,
                 TimeDelta excessive_duration,
                 bool watchdog_enable)
      : helper_(thread_name, excessive_duration, watchdog_enable) {}

  ~IOJankObserver() {}

  // Attaches the observer to the current thread's message loop. You can only
  // attach to the current thread, so this function can be invoked on another
  // thread to attach it.
  void AttachToCurrentThread() {
    MessageLoop::current()->AddTaskObserver(this);
    MessageLoopForIO::current()->AddIOObserver(this);
  }

  // Detaches the observer to the current thread's message loop.
  void DetachFromCurrentThread() {
    MessageLoopForIO::current()->RemoveIOObserver(this);
    MessageLoop::current()->RemoveTaskObserver(this);
  }

  virtual void WillProcessIOEvent() {
    helper_.StartProcessingTimers(base::TimeDelta());
  }

  virtual void DidProcessIOEvent() {
    helper_.EndProcessingTimers();
  }

  virtual void WillProcessTask(const Task* task) {
    base::TimeTicks now = base::TimeTicks::Now();
    const base::TimeDelta queueing_time = now - task->tracked_birth_time();
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessTask(const Task* task) {
    helper_.EndProcessingTimers();
  }

 private:
  friend class base::RefCountedThreadSafe<IOJankObserver>;

  JankObserverHelper helper_;

  DISALLOW_COPY_AND_ASSIGN(IOJankObserver);
};

//------------------------------------------------------------------------------
class UIJankObserver : public base::RefCountedThreadSafe<UIJankObserver>,
                       public MessageLoop::TaskObserver,
                       public MessageLoopForUI::Observer {
 public:
  UIJankObserver(const char* thread_name,
                 TimeDelta excessive_duration,
                 bool watchdog_enable)
      : helper_(thread_name, excessive_duration, watchdog_enable) {}

  // Attaches the observer to the current thread's message loop. You can only
  // attach to the current thread, so this function can be invoked on another
  // thread to attach it.
  void AttachToCurrentThread() {
    DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
    MessageLoopForUI::current()->AddObserver(this);
    MessageLoop::current()->AddTaskObserver(this);
  }

  // Detaches the observer to the current thread's message loop.
  void DetachFromCurrentThread() {
    DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
    MessageLoop::current()->RemoveTaskObserver(this);
    MessageLoopForUI::current()->RemoveObserver(this);
  }

  virtual void WillProcessTask(const Task* task) {
    base::TimeTicks now = base::TimeTicks::Now();
    const base::TimeDelta queueing_time = now - task->tracked_birth_time();
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessTask(const Task* task) {
    helper_.EndProcessingTimers();
  }

#if defined(OS_WIN)
  virtual void WillProcessMessage(const MSG& msg) {
    // GetMessageTime returns a LONG (signed 32-bit) and GetTickCount returns
    // a DWORD (unsigned 32-bit). They both wrap around when the time is longer
    // than they can hold. I'm not sure if GetMessageTime wraps around to 0,
    // or if the original time comes from GetTickCount, it might wrap around
    // to -1.
    //
    // Therefore, I cast to DWORD so if it wraps to -1 we will correct it. If
    // it doesn't, then our time delta will be negative if a message happens
    // to straddle the wraparound point, it will still be OK.
    DWORD cur_message_issue_time = static_cast<DWORD>(msg.time);
    DWORD cur_time = GetTickCount();
    base::TimeDelta queueing_time =
        base::TimeDelta::FromMilliseconds(cur_time - cur_message_issue_time);

    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessMessage(const MSG& msg) {
    helper_.EndProcessingTimers();
  }
#elif defined(TOOLKIT_USES_GTK)
  virtual void WillProcessEvent(GdkEvent* event) {
    // TODO(evanm): we want to set queueing_time_ using
    // gdk_event_get_time, but how do you convert that info
    // into a delta?
    // guint event_time = gdk_event_get_time(event);
    base::TimeDelta queueing_time = base::TimeDelta::FromMilliseconds(0);
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessEvent(GdkEvent* event) {
    helper_.EndProcessingTimers();
  }
#endif

 private:
  friend class base::RefCountedThreadSafe<UIJankObserver>;

  ~UIJankObserver() {}

  JankObserverHelper helper_;

  DISALLOW_COPY_AND_ASSIGN(UIJankObserver);
};

// These objects are created by InstallJankometer and leaked.
const scoped_refptr<UIJankObserver>* ui_observer = NULL;
const scoped_refptr<IOJankObserver>* io_observer = NULL;

}  // namespace

void InstallJankometer(const CommandLine& parsed_command_line) {
  if (ui_observer || io_observer) {
    NOTREACHED() << "Initializing jank-o-meter twice";
    return;
  }

  bool ui_watchdog_enabled = false;
  bool io_watchdog_enabled = false;
  if (parsed_command_line.HasSwitch(switches::kEnableWatchdog)) {
    std::string list =
        parsed_command_line.GetSwitchValueASCII(switches::kEnableWatchdog);
    if (list.npos != list.find("ui"))
      ui_watchdog_enabled = true;
    if (list.npos != list.find("io"))
      io_watchdog_enabled = true;
  }

  // Install on the UI thread.
  ui_observer = new scoped_refptr<UIJankObserver>(
      new UIJankObserver(
          "UI",
          TimeDelta::FromMilliseconds(kMaxUIMessageDelayMs),
          ui_watchdog_enabled));
  (*ui_observer)->AttachToCurrentThread();

  // Now install on the I/O thread. Hiccups on that thread will block
  // interaction with web pages. We must proxy to that thread before we can
  // add our observer.
  io_observer = new scoped_refptr<IOJankObserver>(
      new IOJankObserver(
          "IO",
          TimeDelta::FromMilliseconds(kMaxIOMessageDelayMs),
          io_watchdog_enabled));
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(io_observer->get(),
                        &IOJankObserver::AttachToCurrentThread));
}

void UninstallJankometer() {
  if (ui_observer) {
    (*ui_observer)->DetachFromCurrentThread();
    delete ui_observer;
    ui_observer = NULL;
  }
  if (io_observer) {
    // IO thread can't be running when we remove observers.
    DCHECK((!g_browser_process) || !(g_browser_process->io_thread()));
    delete io_observer;
    io_observer = NULL;
  }
}
<commit_msg>Reduce Jankometer measurements by only periodically sampling<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <limits>

#include "chrome/browser/jankometer.h"

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/ref_counted.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "base/time.h"
#include "base/watchdog.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/common/chrome_switches.h"

#if defined(TOOLKIT_USES_GTK)
#include "chrome/browser/gtk/gtk_util.h"
#endif

using base::TimeDelta;
using base::TimeTicks;

namespace {

// The maximum threshold of delay of the message  before considering it a delay.
// For a debug build, you may want to set IO delay around 500ms.
// For a release build, setting it around 350ms is sensible.
// Visit about:histograms to see what the distribution is on your system, with
// your build. Be sure to do some work to get interesting stats.
// The numbers below came from a warm start (you'll get about 5-10 alarms with
// a cold start), and running the page-cycler for 5 rounds.
#ifdef NDEBUG
const int kMaxUIMessageDelayMs = 350;
const int kMaxIOMessageDelayMs = 200;
#else
const int kMaxUIMessageDelayMs = 500;
const int kMaxIOMessageDelayMs = 400;
#endif

// Maximum processing time (excluding queueing delay) for a message before
// considering it delayed.
const int kMaxMessageProcessingMs = 100;

// TODO(brettw) Consider making this a pref.
const bool kPlaySounds = false;

//------------------------------------------------------------------------------
// Provide a special watchdog to make it easy to set the breakpoint on this
// class only.
class JankWatchdog : public Watchdog {
 public:
  JankWatchdog(const TimeDelta& duration,
               const std::string& thread_watched_name,
               bool enabled)
      : Watchdog(duration, thread_watched_name, enabled),
        thread_name_watched_(thread_watched_name),
        alarm_count_(0) {
  }

  virtual ~JankWatchdog() {}

  virtual void Alarm() {
    // Put break point here if you want to stop threads and look at what caused
    // the jankiness.
    alarm_count_++;
    Watchdog::Alarm();
  }

 private:
  std::string thread_name_watched_;
  int alarm_count_;

  DISALLOW_COPY_AND_ASSIGN(JankWatchdog);
};

class JankObserverHelper {
 public:
  JankObserverHelper(const std::string& thread_name,
                     const TimeDelta& excessive_duration,
                     bool watchdog_enable);
  ~JankObserverHelper();

  void StartProcessingTimers(const TimeDelta& queueing_time);
  void EndProcessingTimers();

  // Indicate if we will bother to measuer this message.
  bool MessageWillBeMeasured();

  static void SetDefaultMessagesToSkip(int count) { discard_count_ = count; }

 private:
  const TimeDelta max_message_delay_;

  // Indicate if we'll bother measuring this message.
  bool measure_current_message_;

  // Down counter which will periodically hit 0, and only then bother to measure
  // the corresponding message.
  int events_till_measurement_;

  // The value to re-initialize events_till_measurement_ after it reaches 0.
  static int discard_count_;

  // Time at which the current message processing began.
  TimeTicks begin_process_message_;

  // Time the current message spent in the queue -- delta between message
  // construction time and message processing time.
  TimeDelta queueing_time_;

  // Counters for the two types of jank we measure.
  base::StatsCounter slow_processing_counter_;  // Msgs w/ long proc time.
  base::StatsCounter queueing_delay_counter_;   // Msgs w/ long queueing delay.
  scoped_refptr<base::Histogram> process_times_;  // Time spent proc. task.
  scoped_refptr<base::Histogram> total_times_;  // Total queueing plus proc.
  JankWatchdog total_time_watchdog_;  // Watching for excessive total_time.

  DISALLOW_COPY_AND_ASSIGN(JankObserverHelper);
};

JankObserverHelper::JankObserverHelper(
    const std::string& thread_name,
    const TimeDelta& excessive_duration,
    bool watchdog_enable)
    : max_message_delay_(excessive_duration),
      measure_current_message_(true),
      events_till_measurement_(0),
      slow_processing_counter_(std::string("Chrome.SlowMsg") + thread_name),
      queueing_delay_counter_(std::string("Chrome.DelayMsg") + thread_name),
      total_time_watchdog_(excessive_duration, thread_name, watchdog_enable) {
  process_times_ = base::Histogram::FactoryGet(
      std::string("Chrome.ProcMsgL ") + thread_name,
      1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag);
  total_times_ = base::Histogram::FactoryGet(
      std::string("Chrome.TotalMsgL ") + thread_name,
      1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag);
  if (discard_count_ > 0) {
    // Select a vaguely random sample-start-point.
    events_till_measurement_ =
        (TimeTicks::Now() - TimeTicks()).InSeconds() % (discard_count_ + 1);
  }
}

JankObserverHelper::~JankObserverHelper() {}

// Called when a message has just begun processing, initializes
// per-message variables and timers.
void JankObserverHelper::StartProcessingTimers(const TimeDelta& queueing_time) {
  DCHECK(measure_current_message_);
  begin_process_message_ = TimeTicks::Now();
  queueing_time_ = queueing_time;

  // Simulate arming when the message entered the queue.
  total_time_watchdog_.ArmSomeTimeDeltaAgo(queueing_time_);
  if (queueing_time_ > max_message_delay_) {
    // Message is too delayed.
    queueing_delay_counter_.Increment();
#if defined(OS_WIN)
    if (kPlaySounds)
      MessageBeep(MB_ICONASTERISK);
#endif
  }
}

// Called when a message has just finished processing, finalizes
// per-message variables and timers.
void JankObserverHelper::EndProcessingTimers() {
  if (!measure_current_message_)
    return;
  total_time_watchdog_.Disarm();
  TimeTicks now = TimeTicks::Now();
  if (begin_process_message_ != TimeTicks()) {
    TimeDelta processing_time = now - begin_process_message_;
    process_times_->AddTime(processing_time);
    total_times_->AddTime(queueing_time_ + processing_time);
  }
  if (now - begin_process_message_ >
      TimeDelta::FromMilliseconds(kMaxMessageProcessingMs)) {
    // Message took too long to process.
    slow_processing_counter_.Increment();
#if defined(OS_WIN)
    if (kPlaySounds)
      MessageBeep(MB_ICONHAND);
#endif
  }

  // Reset message specific times.
  begin_process_message_ = base::TimeTicks();
  queueing_time_ = base::TimeDelta();
}

bool JankObserverHelper::MessageWillBeMeasured() {
  measure_current_message_ = events_till_measurement_ <= 0;
  if (!measure_current_message_)
    --events_till_measurement_;
  else
    events_till_measurement_ = discard_count_;
  return measure_current_message_;
}

// static
int JankObserverHelper::discard_count_ = 99;  // Measure only 1 in 100.

//------------------------------------------------------------------------------
class IOJankObserver : public base::RefCountedThreadSafe<IOJankObserver>,
                       public MessageLoopForIO::IOObserver,
                       public MessageLoop::TaskObserver {
 public:
  IOJankObserver(const char* thread_name,
                 TimeDelta excessive_duration,
                 bool watchdog_enable)
      : helper_(thread_name, excessive_duration, watchdog_enable) {}

  ~IOJankObserver() {}

  // Attaches the observer to the current thread's message loop. You can only
  // attach to the current thread, so this function can be invoked on another
  // thread to attach it.
  void AttachToCurrentThread() {
    MessageLoop::current()->AddTaskObserver(this);
    MessageLoopForIO::current()->AddIOObserver(this);
  }

  // Detaches the observer to the current thread's message loop.
  void DetachFromCurrentThread() {
    MessageLoopForIO::current()->RemoveIOObserver(this);
    MessageLoop::current()->RemoveTaskObserver(this);
  }

  virtual void WillProcessIOEvent() {
    if (!helper_.MessageWillBeMeasured())
      return;
    helper_.StartProcessingTimers(base::TimeDelta());
  }

  virtual void DidProcessIOEvent() {
    helper_.EndProcessingTimers();
  }

  virtual void WillProcessTask(const Task* task) {
    if (!helper_.MessageWillBeMeasured())
      return;
    base::TimeTicks now = base::TimeTicks::Now();
    const base::TimeDelta queueing_time = now - task->tracked_birth_time();
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessTask(const Task* task) {
    helper_.EndProcessingTimers();
  }

 private:
  friend class base::RefCountedThreadSafe<IOJankObserver>;

  JankObserverHelper helper_;

  DISALLOW_COPY_AND_ASSIGN(IOJankObserver);
};

//------------------------------------------------------------------------------
class UIJankObserver : public base::RefCountedThreadSafe<UIJankObserver>,
                       public MessageLoop::TaskObserver,
                       public MessageLoopForUI::Observer {
 public:
  UIJankObserver(const char* thread_name,
                 TimeDelta excessive_duration,
                 bool watchdog_enable)
      : helper_(thread_name, excessive_duration, watchdog_enable) {}

  // Attaches the observer to the current thread's message loop. You can only
  // attach to the current thread, so this function can be invoked on another
  // thread to attach it.
  void AttachToCurrentThread() {
    DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
    MessageLoopForUI::current()->AddObserver(this);
    MessageLoop::current()->AddTaskObserver(this);
  }

  // Detaches the observer to the current thread's message loop.
  void DetachFromCurrentThread() {
    DCHECK_EQ(MessageLoop::current()->type(), MessageLoop::TYPE_UI);
    MessageLoop::current()->RemoveTaskObserver(this);
    MessageLoopForUI::current()->RemoveObserver(this);
  }

  virtual void WillProcessTask(const Task* task) {
    if (!helper_.MessageWillBeMeasured())
      return;
    base::TimeTicks now = base::TimeTicks::Now();
    const base::TimeDelta queueing_time = now - task->tracked_birth_time();
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessTask(const Task* task) {
    helper_.EndProcessingTimers();
  }

#if defined(OS_WIN)
  virtual void WillProcessMessage(const MSG& msg) {
    if (!helper_.MessageWillBeMeasured())
      return;
    // GetMessageTime returns a LONG (signed 32-bit) and GetTickCount returns
    // a DWORD (unsigned 32-bit). They both wrap around when the time is longer
    // than they can hold. I'm not sure if GetMessageTime wraps around to 0,
    // or if the original time comes from GetTickCount, it might wrap around
    // to -1.
    //
    // Therefore, I cast to DWORD so if it wraps to -1 we will correct it. If
    // it doesn't, then our time delta will be negative if a message happens
    // to straddle the wraparound point, it will still be OK.
    DWORD cur_message_issue_time = static_cast<DWORD>(msg.time);
    DWORD cur_time = GetTickCount();
    base::TimeDelta queueing_time =
        base::TimeDelta::FromMilliseconds(cur_time - cur_message_issue_time);

    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessMessage(const MSG& msg) {
    helper_.EndProcessingTimers();
  }
#elif defined(TOOLKIT_USES_GTK)
  virtual void WillProcessEvent(GdkEvent* event) {
    if (!helper_.MessageWillBeMeasured())
      return;
    // TODO(evanm): we want to set queueing_time_ using
    // gdk_event_get_time, but how do you convert that info
    // into a delta?
    // guint event_time = gdk_event_get_time(event);
    base::TimeDelta queueing_time = base::TimeDelta::FromMilliseconds(0);
    helper_.StartProcessingTimers(queueing_time);
  }

  virtual void DidProcessEvent(GdkEvent* event) {
    helper_.EndProcessingTimers();
  }
#endif

 private:
  friend class base::RefCountedThreadSafe<UIJankObserver>;

  ~UIJankObserver() {}

  JankObserverHelper helper_;

  DISALLOW_COPY_AND_ASSIGN(UIJankObserver);
};

// These objects are created by InstallJankometer and leaked.
const scoped_refptr<UIJankObserver>* ui_observer = NULL;
const scoped_refptr<IOJankObserver>* io_observer = NULL;

}  // namespace

void InstallJankometer(const CommandLine& parsed_command_line) {
  if (ui_observer || io_observer) {
    NOTREACHED() << "Initializing jank-o-meter twice";
    return;
  }

  bool ui_watchdog_enabled = false;
  bool io_watchdog_enabled = false;
  if (parsed_command_line.HasSwitch(switches::kEnableWatchdog)) {
    std::string list =
        parsed_command_line.GetSwitchValueASCII(switches::kEnableWatchdog);
    if (list.npos != list.find("ui"))
      ui_watchdog_enabled = true;
    if (list.npos != list.find("io"))
      io_watchdog_enabled = true;
  }

  if (ui_watchdog_enabled || io_watchdog_enabled)
    JankObserverHelper::SetDefaultMessagesToSkip(0);  // Watch everything.

  // Install on the UI thread.
  ui_observer = new scoped_refptr<UIJankObserver>(
      new UIJankObserver(
          "UI",
          TimeDelta::FromMilliseconds(kMaxUIMessageDelayMs),
          ui_watchdog_enabled));
  (*ui_observer)->AttachToCurrentThread();

  // Now install on the I/O thread. Hiccups on that thread will block
  // interaction with web pages. We must proxy to that thread before we can
  // add our observer.
  io_observer = new scoped_refptr<IOJankObserver>(
      new IOJankObserver(
          "IO",
          TimeDelta::FromMilliseconds(kMaxIOMessageDelayMs),
          io_watchdog_enabled));
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(io_observer->get(),
                        &IOJankObserver::AttachToCurrentThread));
}

void UninstallJankometer() {
  if (ui_observer) {
    (*ui_observer)->DetachFromCurrentThread();
    delete ui_observer;
    ui_observer = NULL;
  }
  if (io_observer) {
    // IO thread can't be running when we remove observers.
    DCHECK((!g_browser_process) || !(g_browser_process->io_thread()));
    delete io_observer;
    io_observer = NULL;
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <unistd.h>
#include <crdr_chibios/sys/sys.h>
#include <uavcan_stm32/uavcan_stm32.hpp>
#include <uavcan/protocol/global_time_sync_slave.hpp>

namespace app
{
namespace
{

uavcan_stm32::CanInitHelper<128> can;

typedef uavcan::Node<16384> Node;

uavcan::LazyConstructor<Node> node_;

Node& getNode()
{
    if (!node_.isConstructed())
    {
        node_.construct<uavcan::ICanDriver&, uavcan::ISystemClock&>(can.driver, uavcan_stm32::SystemClock::instance());
    }
    return *node_;
}

void ledSet(bool state)
{
    palWritePad(GPIO_PORT_LED, GPIO_PIN_LED, state);
}

int init()
{
    int res = 0;

    halInit();
    chibios_rt::System::init();
    sdStart(&STDOUT_SD, NULL);

    res = can.init(1000000);
    if (res < 0)
    {
        goto leave;
    }

leave:
    return res;
}

__attribute__((noreturn))
void die(int status)
{
    lowsyslog("Now I am dead x_x %i\n", status);
    while (1)
    {
        ledSet(false);
        sleep(1);
        ledSet(true);
        sleep(1);
    }
}

class : public chibios_rt::BaseStaticThread<8192>
{
public:
    msg_t main()
    {
        /*
         * Setting up the node parameters
         */
        Node& node = app::getNode();

        node.setNodeID(64);
        node.setName("org.uavcan.stm32_test_stm32f107");

        /*
         * Initializing the UAVCAN node - this may take a while
         */
        while (true)
        {
            // Calling start() multiple times is OK - only the first successfull call will be effective
            int res = node.start();

#if !UAVCAN_TINY
            uavcan::NetworkCompatibilityCheckResult ncc_result;
            if (res >= 0)
            {
                lowsyslog("Checking network compatibility...\n");
                res = node.checkNetworkCompatibility(ncc_result);
            }
#endif

            if (res < 0)
            {
                lowsyslog("Node initialization failure: %i, will try agin soon\n", res);
            }
#if !UAVCAN_TINY
            else if (!ncc_result.isOk())
            {
                lowsyslog("Network conflict with %u, will try again soon\n", ncc_result.conflicting_node.get());
            }
#endif
            else
            {
                break;
            }
            ::sleep(3);
        }

        /*
         * Time synchronizer
         */
        static uavcan::GlobalTimeSyncSlave time_sync_slave(node);
        {
            const int res = time_sync_slave.start();
            if (res < 0)
            {
                die(res);
            }
        }

        /*
         * Main loop
         */
        lowsyslog("UAVCAN node started\n");
        node.setStatusOk();
        while (true)
        {
            const int spin_res = node.spin(uavcan::MonotonicDuration::fromMSec(5000));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }

            lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get()));

            lowsyslog("Memory usage: used=%u free=%u\n",
                      node.getAllocator().getNumUsedBlocks(), node.getAllocator().getNumFreeBlocks());

            lowsyslog("CAN errors: %lu %lu\n",
                      static_cast<unsigned long>(can.driver.getIface(0)->getErrorCount()),
                      static_cast<unsigned long>(can.driver.getIface(1)->getErrorCount()));

#if !UAVCAN_TINY
            node.getLogger().setLevel(uavcan::protocol::debug::LogLevel::INFO);
            node.logInfo("app", "UTC %* sec, %* corr, %* jumps",
                         uavcan_stm32::clock::getUtc().toMSec() / 1000,
                         uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                         uavcan_stm32::clock::getUtcAjdustmentJumpCount());
#endif
        }
        return msg_t();
    }
} uavcan_node_thread;

}
}

int main()
{
    const int init_res = app::init();
    if (init_res != 0)
    {
        app::die(init_res);
    }

    lowsyslog("Starting the UAVCAN thread\n");
    app::uavcan_node_thread.start(LOWPRIO);

    while (true)
    {
        for (int i = 0; i < 200; i++)
        {
            app::ledSet(app::can.driver.hadActivity());
            ::usleep(25000);
        }

        const uavcan::UtcTime utc = uavcan_stm32::clock::getUtc();
        lowsyslog("UTC %lu sec   Absolute correction: %li usec   Speed correction: %liPPM   Jumps: %lu\n",
                  static_cast<unsigned long>(utc.toMSec() / 1000),
                  static_cast<long>(uavcan_stm32::clock::getPrevUtcAdjustment().toUSec()),
                  uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                  uavcan_stm32::clock::getUtcAjdustmentJumpCount());
    }
}
<commit_msg>#ifdef for GCC-specific attribute<commit_after>/*
 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
 */

#include <unistd.h>
#include <crdr_chibios/sys/sys.h>
#include <uavcan_stm32/uavcan_stm32.hpp>
#include <uavcan/protocol/global_time_sync_slave.hpp>

namespace app
{
namespace
{

uavcan_stm32::CanInitHelper<128> can;

typedef uavcan::Node<16384> Node;

uavcan::LazyConstructor<Node> node_;

Node& getNode()
{
    if (!node_.isConstructed())
    {
        node_.construct<uavcan::ICanDriver&, uavcan::ISystemClock&>(can.driver, uavcan_stm32::SystemClock::instance());
    }
    return *node_;
}

void ledSet(bool state)
{
    palWritePad(GPIO_PORT_LED, GPIO_PIN_LED, state);
}

int init()
{
    int res = 0;

    halInit();
    chibios_rt::System::init();
    sdStart(&STDOUT_SD, NULL);

    res = can.init(1000000);
    if (res < 0)
    {
        goto leave;
    }

leave:
    return res;
}

#if __GNUC__
__attribute__((noreturn))
#endif
void die(int status)
{
    lowsyslog("Now I am dead x_x %i\n", status);
    while (1)
    {
        ledSet(false);
        sleep(1);
        ledSet(true);
        sleep(1);
    }
}

class : public chibios_rt::BaseStaticThread<8192>
{
public:
    msg_t main()
    {
        /*
         * Setting up the node parameters
         */
        Node& node = app::getNode();

        node.setNodeID(64);
        node.setName("org.uavcan.stm32_test_stm32f107");

        /*
         * Initializing the UAVCAN node - this may take a while
         */
        while (true)
        {
            // Calling start() multiple times is OK - only the first successfull call will be effective
            int res = node.start();

#if !UAVCAN_TINY
            uavcan::NetworkCompatibilityCheckResult ncc_result;
            if (res >= 0)
            {
                lowsyslog("Checking network compatibility...\n");
                res = node.checkNetworkCompatibility(ncc_result);
            }
#endif

            if (res < 0)
            {
                lowsyslog("Node initialization failure: %i, will try agin soon\n", res);
            }
#if !UAVCAN_TINY
            else if (!ncc_result.isOk())
            {
                lowsyslog("Network conflict with %u, will try again soon\n", ncc_result.conflicting_node.get());
            }
#endif
            else
            {
                break;
            }
            ::sleep(3);
        }

        /*
         * Time synchronizer
         */
        static uavcan::GlobalTimeSyncSlave time_sync_slave(node);
        {
            const int res = time_sync_slave.start();
            if (res < 0)
            {
                die(res);
            }
        }

        /*
         * Main loop
         */
        lowsyslog("UAVCAN node started\n");
        node.setStatusOk();
        while (true)
        {
            const int spin_res = node.spin(uavcan::MonotonicDuration::fromMSec(5000));
            if (spin_res < 0)
            {
                lowsyslog("Spin failure: %i\n", spin_res);
            }

            lowsyslog("Time sync master: %u\n", unsigned(time_sync_slave.getMasterNodeID().get()));

            lowsyslog("Memory usage: used=%u free=%u\n",
                      node.getAllocator().getNumUsedBlocks(), node.getAllocator().getNumFreeBlocks());

            lowsyslog("CAN errors: %lu %lu\n",
                      static_cast<unsigned long>(can.driver.getIface(0)->getErrorCount()),
                      static_cast<unsigned long>(can.driver.getIface(1)->getErrorCount()));

#if !UAVCAN_TINY
            node.getLogger().setLevel(uavcan::protocol::debug::LogLevel::INFO);
            node.logInfo("app", "UTC %* sec, %* corr, %* jumps",
                         uavcan_stm32::clock::getUtc().toMSec() / 1000,
                         uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                         uavcan_stm32::clock::getUtcAjdustmentJumpCount());
#endif
        }
        return msg_t();
    }
} uavcan_node_thread;

}
}

int main()
{
    const int init_res = app::init();
    if (init_res != 0)
    {
        app::die(init_res);
    }

    lowsyslog("Starting the UAVCAN thread\n");
    app::uavcan_node_thread.start(LOWPRIO);

    while (true)
    {
        for (int i = 0; i < 200; i++)
        {
            app::ledSet(app::can.driver.hadActivity());
            ::usleep(25000);
        }

        const uavcan::UtcTime utc = uavcan_stm32::clock::getUtc();
        lowsyslog("UTC %lu sec   Absolute correction: %li usec   Speed correction: %liPPM   Jumps: %lu\n",
                  static_cast<unsigned long>(utc.toMSec() / 1000),
                  static_cast<long>(uavcan_stm32::clock::getPrevUtcAdjustment().toUSec()),
                  uavcan_stm32::clock::getUtcSpeedCorrectionPPM(),
                  uavcan_stm32::clock::getUtcAjdustmentJumpCount());
    }
}
<|endoftext|>


<commit_before>#include "mugen_animation.h"

#include <string>
#include <vector>

#include "mugen_sprite.h"
#include "mugen_util.h"

#include "util/bitmap.h"

static void renderCollision( const std::vector< MugenArea > &vec, Bitmap &bmp, int x, int y, int color ){
    for( unsigned int i = 0; i < vec.size(); ++i ){
	bmp.rectangle( x + vec[i].x1, y + vec[i].y1, x + vec[i].x2, y + vec[i].y2, color );
    }
}

/// area
MugenArea::MugenArea():
x1(0),
y1(0),
x2(0),
y2(0){
}

MugenArea::MugenArea( const MugenArea &copy ){
    this->x1 = copy.x1;
    this->y1 = copy.y1;
    this->x2 = copy.x2;
    this->y2 = copy.y2;
}

MugenArea & MugenArea::operator=( const MugenArea &copy ){
    this->x1 = copy.x1;
    this->y1 = copy.y1;
    this->x2 = copy.x2;
    this->y2 = copy.y2;

    return *this;
}

MugenArea::~MugenArea(){
}

/*
Frame
*/
MugenFrame::MugenFrame():
loopstart(false),
sprite(0),
xoffset(0),
yoffset(0),
time(0),
flipHorizontal(false),
flipVertical(false),
colorAdd(""),
bmp(0){
}
MugenFrame::MugenFrame( const MugenFrame &copy ){
    this->loopstart = copy.loopstart;
    this->sprite = copy.sprite;
    this->xoffset = copy.xoffset;
    this->yoffset = copy.yoffset;
    this->time = copy.time;
    this->flipHorizontal = copy.flipHorizontal;
    this->flipVertical = copy.flipVertical;
    this->colorAdd = copy.colorAdd;
    if( copy.bmp )this->bmp = new Bitmap(*copy.bmp);

}

MugenFrame & MugenFrame::operator=( const MugenFrame &copy ){
    this->loopstart = copy.loopstart;
    this->sprite = copy.sprite;
    this->xoffset = copy.xoffset;
    this->yoffset = copy.yoffset;
    this->time = copy.time;
    this->flipHorizontal = copy.flipHorizontal;
    this->flipVertical = copy.flipVertical;
    this->colorAdd = copy.colorAdd;
    if( copy.bmp )this->bmp = new Bitmap(*copy.bmp);

    return *this;

}

MugenFrame::~MugenFrame(){
    // Kill bitmap
    if( bmp )delete bmp;
}

/*
Holds mugen animations, ie: player.air
*/
MugenAnimation::MugenAnimation():
loopPosition(0),
position(0),
type(UNKNOWN),
showDefense(false),
showOffense(false),
ticks(0){
}
MugenAnimation::MugenAnimation( const MugenAnimation &copy ){
    this->frames = copy.frames;
    this->loopPosition = copy.loopPosition;
    this->position = copy.position;
    this->type = copy.type;
    this->showDefense = copy.showDefense;
    this->showOffense = copy.showOffense;
}
MugenAnimation::~MugenAnimation(){
    for( std::vector< MugenFrame * >::iterator i = frames.begin() ; i != frames.end() ; ++i ){
	if( (*i) )delete (*i);
    }
}

void MugenAnimation::addFrame( MugenFrame *frame ){
    // This gets deleted by frame, so don't worry, be happy
    if( !frame->bmp ){
	if( frame->sprite )frame->bmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) frame->sprite->pcx, frame->sprite->newlength));
	else frame->bmp = new Bitmap();
    }
    if( frame->loopstart ) loopPosition = frames.size();
    frames.push_back( frame );
}

const MugenFrame *MugenAnimation::getNext(){
    if( position < frames.size() -1 )position++;
    else position = loopPosition;

    return frames[position];
}

void MugenAnimation::logic(){
    if( frames[position]->time != -1 ){
	ticks++;
	if(ticks >= 15 + frames[position]->time){
		ticks = 0;
		if( position < frames.size() -1 )position++;
		else position = loopPosition;
	}
    }
}

void MugenAnimation::render( int xaxis, int yaxis, Bitmap &work ){
    const int spritex = frames[position]->sprite ? frames[position]->sprite->x : 0;
    const int spritey = frames[position]->sprite ? frames[position]->sprite->y : 0;
    const int placex = (xaxis - spritex ) + frames[position]->xoffset;
    const int placey = (yaxis - spritey ) + frames[position]->yoffset;

    if( frames[position]->flipHorizontal && ! frames[position]->flipVertical ){
	frames[position]->bmp->drawHFlip(placex, placey, work);
    }
    else if( frames[position]->flipVertical && ! frames[position]->flipHorizontal ){
	frames[position]->bmp->drawVFlip(placex, placey, work);
    }
    else if( frames[position]->flipVertical && frames[position]->flipHorizontal ){
	frames[position]->bmp->drawHVFlip(placex, placey,work);
    }
    else frames[position]->bmp->draw(placex, placey, work);

    if( showDefense )renderCollision( frames[position]->defenseCollision, work, xaxis, yaxis, Bitmap::makeColor( 0,255,0 ) );
    if( showOffense )renderCollision( frames[position]->attackCollision, work, xaxis, yaxis,  Bitmap::makeColor( 255,0,0 ) );
}

void MugenAnimation::forwardFrame(){
    if( position < frames.size() -1 )position++;
    else position = loopPosition;
}

void MugenAnimation::backFrame(){
    if( position > loopPosition )position--;
    else position = position = frames.size() - 1;
}

// Get name of type of animation
const std::string MugenAnimation::getName(const MugenAnimationType t){
    switch( t ){
	case STANDING: return "Standing";break;
	case STAND_TURNING: return "Stand turning";break;
	case CROUCH_TURNING: return "Crouch turning";break;
	case STAND_TO_CROUCH: return "Stand to crouch";break;
	case CROUCHING: return "Crouching";break;
	case CROUCH_TO_STAND: return "Crouch to stand";break;
	case WALKING_FORWARDS: return "Walking forwards";break;
	case WALKING_BACKWARDS: return "Walking backwards";break;
	case JUMP_START: return "Jump start (on ground)";break;
	case JUMP_NEUTRAL_UP: return "Jump neutral (upwards)";break;
	case JUMP_FORWARDS_UP: return "Jump forwards (upwards)";break;
	case JUMP_BACK_UP: return "Jump back (upwards)";break;
	case JUMP_NEUTRAL_DOWN: return "Jump neutral (downwards)";break;
	case JUMP_FORWARDS_DOWN: return "Jump fwd (downwards)";break;
	case JUMP_BACK_DOWN: return "Jump back (downwards)";break;
	case JUMP_LANDING: return "Jump landing";break;
	case RUN_FORWARDS: return "Run fwd/hop forward";break;
	case HOP_BACK: return "Hop back";break;
	case START_GUARD_STAND: return "Start guarding (stand)";break;
	case START_GUARD_CROUCH: return "Start guarding (crouch)";break;
	case START_GUARD_AIR: return "Start guarding (air)";break;
	case GUARD_STAND: return "Guard (stand)";break;
	case GUARD_CROUCH: return "Guard (crouch)";break;
	case GUARD_AIR: return "Guard (air)";break;
	case STOP_GUARD_STAND: return "Stop guarding (stand)";break;
	case STOP_GUARD_CROUCH: return "Stop guarding (crouch)";break;
	case STOP_GUARD_AIR: return "Stop guarding (air)";break;
	case GUARD_HIT_STAND: return "Guarding a hit (stand)";break;
	case GUARD_HIT_CROUCH: return "Guarding a hit (crouch)";break;
	case GUARD_HIT_AIR: return "Guarding a hit (air)";break;
	case LOSE: return "opt   Lose";break;
	case DRAW: return "opt   Time Over drawgame";break;
	case WIN: return "opt   Win";break;
	case INTRO: return "opt   Intro";break;
	case TAUNT: return "opt   Taunt";break;
	case HIT_HIGH_LIGHT: return "Stand/Air Hit high (light)";break;
	case HIT_HIGH_MEDIUM: return "Stand/Air Hit high (medium)";break;
	case HIT_HIGH_HARD: return "Stand/Air Hit high (hard)";break;
	case STAND_RECOVER_HIGH_LIGHT: return "Stand Recover high (light)";break;
	case STAND_RECOVER_HIGH_MEDIUM: return "Stand Recover high (medium)";break;
	case STAND_RECOVER_HIGH_HARD: return "Stand Recover high (hard)";break;
	case HIT_LOW_LIGHT: return "Stand/Air Hit low (light)";break;
	case HIT_LOW_MEDIUM: return "Stand/Air Hit low (medium)";break;
	case HIT_LOW_HARD: return "Stand/Air Hit low (hard)";break;
	case STAND_RECOVER_LOW_LIGHT: return "Stand Recover low (light)";break;
	case STAND_RECOVER_LOW_MEDIUM: return "Stand Recover low (medium)";break;
	case STAND_RECOVER_LOW_HARD: return "Stand Recover low (hard)";break;
	case CROUCH_HIT_LIGHT: return "Crouch Hit (light)";break;
	case CROUCH_HIT_MEDIUM: return "Crouch Hit (medium)";break;
	case CROUCH_HIT_HARD: return "Crouch Hit (hard)";break;
	case CROUCH_RECOVER_LIGHT: return "Crouch Recover (light)";break;
	case CROUCH_RECOVER_MEDIUM: return "Crouch Recover (medium)";break;
	case CROUCH_RECOVER_HARD: return "Crouch Recover (hard)";break;
	case HIT_BACK: return "Stand/Air Hit back";break;
	case HIT_TRANSITION: return "opt  Stand/Air Hit transition";break;
	case AIR_RECOVER: return "Air Recover";break;
	case AIR_FALL: return "Air Fall";break;
	case AIR_FALL_COMING_DOWN: return "opt  Air Fall (coming down)";break;
	case TRIPPED: return "Tripped";break;
	case LIEDOWN_HIT_STAYDOWN: return "LieDown Hit (stay down)";break;
	case LIEDOWN_HIT_INTOAIR: return "LieDown Hit (hit up into air)";break;
	case HIT_GROUND_FROM_FALL: return "Hitting ground from fall";break;
	case BOUNCE_INTO_AIR: return "Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE: return "Hit ground from bounce";break;
	case LIEDOWN: return "LieDown";break;
	case GET_UP_FROM_LIEDOWN: return "Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND: return "opt  LieDead (final round)";break;
	case FALL_RECOVERY_NEAR_GROUND: return "Fall-recovery near ground";break;
	case FALL_RECOVERY_MIDAIR: return "Fall-recovery in mid-air";break;
	case DIZZY: return "Dizzy";break;
	case CONTINUE: return "opt  \"Continue?\" screen";break;
	case YES_CONTINUE: return "opt  \"Yes\" to \"Continue\"";break;
	case NO_CONTINUE: return "opt  \"No\" to \"Continue\"";break;
	case AIR_FALL_HIT_UP: return "opt  Air fall -- hit up";break;
	case FALL_FROM_HIT_UP: return "opt  Coming down from hit up";break;
	case LIEDOWN_HIT_STAYDOWN2: return "opt  LieDown Hit (stay down)";break;
	case BOUNCE_FROM_GROUND_INTO_AIR: return "opt  Bounce from ground into air";break;
	case BOUNCE_INTO_AIR2: return "opt  Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE2: return "opt  Hit ground from bounce";break;
	case LIEDOWN2: return "opt  LieDown";break;
	case GET_UP_FROM_LIEDOWN2: return "opt  Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS2: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND2: return "opt  LieDead (final round)";break;
	case AIR_FALL_HIT_UP2: return "opt  Air fall -- hit up";break;
	case FALL_FROM_HIT_UP2: return "opt  Coming down from hit up";break;
	case LIEDOWN_HIT_STAYDOWN3: return "opt  LieDown Hit (stay down)";break;
	case BOUNCE_FROM_GROUND_INTO_AIR2: return "opt  Bounce from ground into air";break;
	case BOUNCE_INTO_AIR3: return "opt  Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE3: return "opt  Hit ground from bounce";break;
	case LIEDOWN3: return "opt  LieDown";break;
	case GET_UP_FROM_LIEDOWN3: return "opt  Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS3: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND3: return "opt  LieDead (final round)";break;
	case UNKNOWN:
	default: return "Custom or Optional Animation";break;
    }
}

<commit_msg>Corrected animation time<commit_after>#include "mugen_animation.h"

#include <string>
#include <vector>

#include "mugen_sprite.h"
#include "mugen_util.h"

#include "util/bitmap.h"

static void renderCollision( const std::vector< MugenArea > &vec, Bitmap &bmp, int x, int y, int color ){
    for( unsigned int i = 0; i < vec.size(); ++i ){
	bmp.rectangle( x + vec[i].x1, y + vec[i].y1, x + vec[i].x2, y + vec[i].y2, color );
    }
}

/// area
MugenArea::MugenArea():
x1(0),
y1(0),
x2(0),
y2(0){
}

MugenArea::MugenArea( const MugenArea &copy ){
    this->x1 = copy.x1;
    this->y1 = copy.y1;
    this->x2 = copy.x2;
    this->y2 = copy.y2;
}

MugenArea & MugenArea::operator=( const MugenArea &copy ){
    this->x1 = copy.x1;
    this->y1 = copy.y1;
    this->x2 = copy.x2;
    this->y2 = copy.y2;

    return *this;
}

MugenArea::~MugenArea(){
}

/*
Frame
*/
MugenFrame::MugenFrame():
loopstart(false),
sprite(0),
xoffset(0),
yoffset(0),
time(0),
flipHorizontal(false),
flipVertical(false),
colorAdd(""),
bmp(0){
}
MugenFrame::MugenFrame( const MugenFrame &copy ){
    this->loopstart = copy.loopstart;
    this->sprite = copy.sprite;
    this->xoffset = copy.xoffset;
    this->yoffset = copy.yoffset;
    this->time = copy.time;
    this->flipHorizontal = copy.flipHorizontal;
    this->flipVertical = copy.flipVertical;
    this->colorAdd = copy.colorAdd;
    if( copy.bmp )this->bmp = new Bitmap(*copy.bmp);

}

MugenFrame & MugenFrame::operator=( const MugenFrame &copy ){
    this->loopstart = copy.loopstart;
    this->sprite = copy.sprite;
    this->xoffset = copy.xoffset;
    this->yoffset = copy.yoffset;
    this->time = copy.time;
    this->flipHorizontal = copy.flipHorizontal;
    this->flipVertical = copy.flipVertical;
    this->colorAdd = copy.colorAdd;
    if( copy.bmp )this->bmp = new Bitmap(*copy.bmp);

    return *this;

}

MugenFrame::~MugenFrame(){
    // Kill bitmap
    if( bmp )delete bmp;
}

/*
Holds mugen animations, ie: player.air
*/
MugenAnimation::MugenAnimation():
loopPosition(0),
position(0),
type(UNKNOWN),
showDefense(false),
showOffense(false),
ticks(0){
}
MugenAnimation::MugenAnimation( const MugenAnimation &copy ){
    this->frames = copy.frames;
    this->loopPosition = copy.loopPosition;
    this->position = copy.position;
    this->type = copy.type;
    this->showDefense = copy.showDefense;
    this->showOffense = copy.showOffense;
}
MugenAnimation::~MugenAnimation(){
    for( std::vector< MugenFrame * >::iterator i = frames.begin() ; i != frames.end() ; ++i ){
	if( (*i) )delete (*i);
    }
}

void MugenAnimation::addFrame( MugenFrame *frame ){
    // This gets deleted by frame, so don't worry, be happy
    if( !frame->bmp ){
	if( frame->sprite )frame->bmp = new Bitmap(Bitmap::memoryPCX((unsigned char*) frame->sprite->pcx, frame->sprite->newlength));
	else frame->bmp = new Bitmap();
    }
    if( frame->loopstart ) loopPosition = frames.size();
    frames.push_back( frame );
}

const MugenFrame *MugenAnimation::getNext(){
    if( position < frames.size() -1 )position++;
    else position = loopPosition;

    return frames[position];
}

void MugenAnimation::logic(){
    if( frames[position]->time != -1 ){
	ticks++;
	if(ticks >= frames[position]->time){
		ticks = 0;
		if( position < frames.size() -1 )position++;
		else position = loopPosition;
	}
    }
}

void MugenAnimation::render( int xaxis, int yaxis, Bitmap &work ){
    const int spritex = frames[position]->sprite ? frames[position]->sprite->x : 0;
    const int spritey = frames[position]->sprite ? frames[position]->sprite->y : 0;
    const int placex = (xaxis - spritex ) + frames[position]->xoffset;
    const int placey = (yaxis - spritey ) + frames[position]->yoffset;

    if( frames[position]->flipHorizontal && ! frames[position]->flipVertical ){
	frames[position]->bmp->drawHFlip(placex, placey, work);
    }
    else if( frames[position]->flipVertical && ! frames[position]->flipHorizontal ){
	frames[position]->bmp->drawVFlip(placex, placey, work);
    }
    else if( frames[position]->flipVertical && frames[position]->flipHorizontal ){
	frames[position]->bmp->drawHVFlip(placex, placey,work);
    }
    else frames[position]->bmp->draw(placex, placey, work);

    if( showDefense )renderCollision( frames[position]->defenseCollision, work, xaxis, yaxis, Bitmap::makeColor( 0,255,0 ) );
    if( showOffense )renderCollision( frames[position]->attackCollision, work, xaxis, yaxis,  Bitmap::makeColor( 255,0,0 ) );
}

void MugenAnimation::forwardFrame(){
    if( position < frames.size() -1 )position++;
    else position = loopPosition;
}

void MugenAnimation::backFrame(){
    if( position > loopPosition )position--;
    else position = position = frames.size() - 1;
}

// Get name of type of animation
const std::string MugenAnimation::getName(const MugenAnimationType t){
    switch( t ){
	case STANDING: return "Standing";break;
	case STAND_TURNING: return "Stand turning";break;
	case CROUCH_TURNING: return "Crouch turning";break;
	case STAND_TO_CROUCH: return "Stand to crouch";break;
	case CROUCHING: return "Crouching";break;
	case CROUCH_TO_STAND: return "Crouch to stand";break;
	case WALKING_FORWARDS: return "Walking forwards";break;
	case WALKING_BACKWARDS: return "Walking backwards";break;
	case JUMP_START: return "Jump start (on ground)";break;
	case JUMP_NEUTRAL_UP: return "Jump neutral (upwards)";break;
	case JUMP_FORWARDS_UP: return "Jump forwards (upwards)";break;
	case JUMP_BACK_UP: return "Jump back (upwards)";break;
	case JUMP_NEUTRAL_DOWN: return "Jump neutral (downwards)";break;
	case JUMP_FORWARDS_DOWN: return "Jump fwd (downwards)";break;
	case JUMP_BACK_DOWN: return "Jump back (downwards)";break;
	case JUMP_LANDING: return "Jump landing";break;
	case RUN_FORWARDS: return "Run fwd/hop forward";break;
	case HOP_BACK: return "Hop back";break;
	case START_GUARD_STAND: return "Start guarding (stand)";break;
	case START_GUARD_CROUCH: return "Start guarding (crouch)";break;
	case START_GUARD_AIR: return "Start guarding (air)";break;
	case GUARD_STAND: return "Guard (stand)";break;
	case GUARD_CROUCH: return "Guard (crouch)";break;
	case GUARD_AIR: return "Guard (air)";break;
	case STOP_GUARD_STAND: return "Stop guarding (stand)";break;
	case STOP_GUARD_CROUCH: return "Stop guarding (crouch)";break;
	case STOP_GUARD_AIR: return "Stop guarding (air)";break;
	case GUARD_HIT_STAND: return "Guarding a hit (stand)";break;
	case GUARD_HIT_CROUCH: return "Guarding a hit (crouch)";break;
	case GUARD_HIT_AIR: return "Guarding a hit (air)";break;
	case LOSE: return "opt   Lose";break;
	case DRAW: return "opt   Time Over drawgame";break;
	case WIN: return "opt   Win";break;
	case INTRO: return "opt   Intro";break;
	case TAUNT: return "opt   Taunt";break;
	case HIT_HIGH_LIGHT: return "Stand/Air Hit high (light)";break;
	case HIT_HIGH_MEDIUM: return "Stand/Air Hit high (medium)";break;
	case HIT_HIGH_HARD: return "Stand/Air Hit high (hard)";break;
	case STAND_RECOVER_HIGH_LIGHT: return "Stand Recover high (light)";break;
	case STAND_RECOVER_HIGH_MEDIUM: return "Stand Recover high (medium)";break;
	case STAND_RECOVER_HIGH_HARD: return "Stand Recover high (hard)";break;
	case HIT_LOW_LIGHT: return "Stand/Air Hit low (light)";break;
	case HIT_LOW_MEDIUM: return "Stand/Air Hit low (medium)";break;
	case HIT_LOW_HARD: return "Stand/Air Hit low (hard)";break;
	case STAND_RECOVER_LOW_LIGHT: return "Stand Recover low (light)";break;
	case STAND_RECOVER_LOW_MEDIUM: return "Stand Recover low (medium)";break;
	case STAND_RECOVER_LOW_HARD: return "Stand Recover low (hard)";break;
	case CROUCH_HIT_LIGHT: return "Crouch Hit (light)";break;
	case CROUCH_HIT_MEDIUM: return "Crouch Hit (medium)";break;
	case CROUCH_HIT_HARD: return "Crouch Hit (hard)";break;
	case CROUCH_RECOVER_LIGHT: return "Crouch Recover (light)";break;
	case CROUCH_RECOVER_MEDIUM: return "Crouch Recover (medium)";break;
	case CROUCH_RECOVER_HARD: return "Crouch Recover (hard)";break;
	case HIT_BACK: return "Stand/Air Hit back";break;
	case HIT_TRANSITION: return "opt  Stand/Air Hit transition";break;
	case AIR_RECOVER: return "Air Recover";break;
	case AIR_FALL: return "Air Fall";break;
	case AIR_FALL_COMING_DOWN: return "opt  Air Fall (coming down)";break;
	case TRIPPED: return "Tripped";break;
	case LIEDOWN_HIT_STAYDOWN: return "LieDown Hit (stay down)";break;
	case LIEDOWN_HIT_INTOAIR: return "LieDown Hit (hit up into air)";break;
	case HIT_GROUND_FROM_FALL: return "Hitting ground from fall";break;
	case BOUNCE_INTO_AIR: return "Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE: return "Hit ground from bounce";break;
	case LIEDOWN: return "LieDown";break;
	case GET_UP_FROM_LIEDOWN: return "Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND: return "opt  LieDead (final round)";break;
	case FALL_RECOVERY_NEAR_GROUND: return "Fall-recovery near ground";break;
	case FALL_RECOVERY_MIDAIR: return "Fall-recovery in mid-air";break;
	case DIZZY: return "Dizzy";break;
	case CONTINUE: return "opt  \"Continue?\" screen";break;
	case YES_CONTINUE: return "opt  \"Yes\" to \"Continue\"";break;
	case NO_CONTINUE: return "opt  \"No\" to \"Continue\"";break;
	case AIR_FALL_HIT_UP: return "opt  Air fall -- hit up";break;
	case FALL_FROM_HIT_UP: return "opt  Coming down from hit up";break;
	case LIEDOWN_HIT_STAYDOWN2: return "opt  LieDown Hit (stay down)";break;
	case BOUNCE_FROM_GROUND_INTO_AIR: return "opt  Bounce from ground into air";break;
	case BOUNCE_INTO_AIR2: return "opt  Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE2: return "opt  Hit ground from bounce";break;
	case LIEDOWN2: return "opt  LieDown";break;
	case GET_UP_FROM_LIEDOWN2: return "opt  Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS2: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND2: return "opt  LieDead (final round)";break;
	case AIR_FALL_HIT_UP2: return "opt  Air fall -- hit up";break;
	case FALL_FROM_HIT_UP2: return "opt  Coming down from hit up";break;
	case LIEDOWN_HIT_STAYDOWN3: return "opt  LieDown Hit (stay down)";break;
	case BOUNCE_FROM_GROUND_INTO_AIR2: return "opt  Bounce from ground into air";break;
	case BOUNCE_INTO_AIR3: return "opt  Bounce into air";break;
	case HIT_GROUND_FROM_BOUNCE3: return "opt  Hit ground from bounce";break;
	case LIEDOWN3: return "opt  LieDown";break;
	case GET_UP_FROM_LIEDOWN3: return "opt  Get up from LieDown";break;
	case LIEDEAD_FIRST_ROUNDS3: return "opt  LieDead (first rounds)";break;
	case LIEDEAD_FINAL_ROUND3: return "opt  LieDead (final round)";break;
	case UNKNOWN:
	default: return "Custom or Optional Animation";break;
    }
}

<|endoftext|>