<commit_before>#include "Game.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

Game::Game() :
	_screenWidth(640),
	_screenHeight(480),
	_gameState(GameState::PLAY),
	_previousTime(0.0)
{
}

Game::~Game()
{
}

void Game::run()
{
	initSystems();
	initShaders();
	gameLoop();

	// Clean up
	glDeleteVertexArrays(1, &_vao);
	glDeleteProgram(_program);
	glfwDestroyWindow(_window);
	glfwTerminate();
}

void Game::initSystems()
{
	// Set the error callback
	glfwSetErrorCallback(errorCallback);

	// Initialize the library
	if (!glfwInit())
	{
		exit(EXIT_FAILURE);
	}

	// Create a windowed mode window and its OpenGL context
	_window = glfwCreateWindow(640, 480, "OpenGL Learning Lab", NULL, NULL);

	if (!_window)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// Make the window's context current
	glfwMakeContextCurrent(_window);

	// The minimum number of screen updates to wait for until the buffers are swapped
	glfwSwapInterval(1);

	// Set up the key callbacks
	glfwSetKeyCallback(_window, keyCallback);

	// start GLEW extension handler
	glewExperimental = true;

	// Setup GLEW
	if (glewInit() != GLEW_OK)
	{
		fprintf(stderr, "GLEW failed to initialize");
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// get version info
	const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
	const GLubyte* version = glGetString(GL_VERSION); // version as a string
	printf("Renderer: %s\n", renderer);
	printf("OpenGL version supported %s\n", version);

	//Set the background color to blue
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

	// Create our OpenGL program
	_program = glCreateProgram();
}

void Game::initShaders()
{
	// INTIALIZE OPENGL
	static const char * vs_source[] =
	{
		"#version 450 core                                                 \n"
		"                                                                  \n"
		"// 'offset' is an input vertex attribute                          \n"
		"layout (location = 0) in vec4 offset;                             \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n"
		"                                                                  \n"
		"    // Add 'offset' to our hard-coded vertex position             \n"
		"    gl_Position = vertices[gl_VertexID] + offset;                 \n"
		"}                                                                 \n"
	};

	static const char * fs_source[] =
	{
		"#version 420 core                                                 \n"
		"                                                                  \n"
		"out vec4 color;                                                   \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    color = vec4(0.0, 0.8, 1.0, 1.0);                             \n"
		"}                                                                 \n"
	};

	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, fs_source, NULL);
	glCompileShader(fs);

	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, vs_source, NULL);
	glCompileShader(vs);

	glAttachShader(_program, vs);
	glAttachShader(_program, fs);

	glLinkProgram(_program);

	glGenVertexArrays(1, &_vao);
	glBindVertexArray(_vao);
}

void Game::gameLoop()
{
	//Will loop until we set _gameState to EXIT
	while (_gameState != GameState::EXIT && !glfwWindowShouldClose(_window))
	{
		updateGame((float)(glfwGetTime() - _previousTime));
		drawGame();

		// Poll for and process events
		glfwPollEvents();

		// Set up previous time
		_previousTime = glfwGetTime();
	}
}

void Game::updateGame(float deltaTime)
{
}

void Game::drawGame()
{
	float ratio;
	int width, height;

	glfwGetFramebufferSize(_window, &width, &height);
	ratio = width / (float)height;

	// Sets the viewport to the screen dimensions
	glViewport(0, 0, width, height);

	// Clear the color and depth buffers
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Render OpenGL here
	static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
	glClearBufferfv(GL_COLOR, 0, green);

	// Use the program object we created earlier for rendering
	glUseProgram(_program);

	GLfloat attrib[] = { (float)sin(glfwGetTime()) * 0.5f,
		(float)cos(glfwGetTime()) * 0.6f,
		0.0f, 0.0f };

	// Pass our offset to vertex data to the vertex shader
	glVertexAttrib4fv(0, attrib);

	glDrawArrays(GL_TRIANGLES, 0, 3);

	// Swap front and back buffers
	glfwSwapBuffers(_window);
}

void Game::errorCallback(int error, const char * description)
{
	fputs(description, stderr);
}

void Game::keyCallback(GLFWwindow * window, int key, int scancode, int action, int mods)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}

	if (key == GLFW_KEY_Q && action == GLFW_PRESS)
	{
		std::cout << "Quit" << std::endl;
	}
}
<commit_msg>Minor changes<commit_after>#include "Game.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

Game::Game() :
	_window(nullptr),
	_screenWidth(640),
	_screenHeight(480),
	_gameState(GameState::PLAY),
	_previousTime(0.0)
{
}

Game::~Game()
{
}

void Game::run()
{
	initSystems();
	initShaders();
	gameLoop();

	// Clean up
	glDeleteVertexArrays(1, &_vao);
	glDeleteProgram(_program);
	glfwDestroyWindow(_window);
	glfwTerminate();
}

void Game::initSystems()
{
	// Set the error callback
	glfwSetErrorCallback(errorCallback);

	// Initialize the library
	if (!glfwInit())
	{
		exit(EXIT_FAILURE);
	}

	// Create a windowed mode window and its OpenGL context
	_window = glfwCreateWindow(640, 480, "OpenGL Learning Lab", NULL, NULL);

	if (!_window)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// Make the window's context current
	glfwMakeContextCurrent(_window);

	// The minimum number of screen updates to wait for until the buffers are swapped
	glfwSwapInterval(1);

	// Set up the key callbacks
	glfwSetKeyCallback(_window, keyCallback);

	// start GLEW extension handler
	glewExperimental = true;

	// Setup GLEW
	if (glewInit() != GLEW_OK)
	{
		fprintf(stderr, "GLEW failed to initialize");
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	// get version info
	const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
	const GLubyte* version = glGetString(GL_VERSION); // version as a string
	printf("Renderer: %s\n", renderer);
	printf("OpenGL version supported %s\n", version);

	//Set the background color to blue
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

	// Create our OpenGL program
	_program = glCreateProgram();
}

void Game::initShaders()
{
	// INTIALIZE OPENGL
	static const char * vs_source[] =
	{
		"#version 450 core                                                 \n"
		"                                                                  \n"
		"// 'offset' is an input vertex attribute                          \n"
		"layout (location = 0) in vec4 offset;                             \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4(-0.25, -0.25, 0.5, 1.0),  \n"
		"                                   vec4( 0.25,  0.25, 0.5, 1.0)); \n"
		"                                                                  \n"
		"    // Add 'offset' to our hard-coded vertex position             \n"
		"    gl_Position = vertices[gl_VertexID] + offset;                 \n"
		"}                                                                 \n"
	};

	static const char * fs_source[] =
	{
		"#version 420 core                                                 \n"
		"                                                                  \n"
		"out vec4 color;                                                   \n"
		"                                                                  \n"
		"void main(void)                                                   \n"
		"{                                                                 \n"
		"    color = vec4(0.0, 0.8, 1.0, 1.0);                             \n"
		"}                                                                 \n"
	};

	GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fs, 1, fs_source, NULL);
	glCompileShader(fs);

	GLuint vs = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vs, 1, vs_source, NULL);
	glCompileShader(vs);

	glAttachShader(_program, vs);
	glAttachShader(_program, fs);

	glLinkProgram(_program);

	glGenVertexArrays(1, &_vao);
	glBindVertexArray(_vao);
}

void Game::gameLoop()
{
	//Will loop until we set _gameState to EXIT
	while (_gameState != GameState::EXIT && !glfwWindowShouldClose(_window))
	{
		updateGame((float)(glfwGetTime() - _previousTime));
		drawGame();

		// Poll for and process events
		glfwPollEvents();

		// Set up previous time
		_previousTime = glfwGetTime();
	}
}

void Game::updateGame(float deltaTime)
{
}

void Game::drawGame()
{
	float ratio;
	int width, height;

	glfwGetFramebufferSize(_window, &width, &height);
	ratio = width / (float)height;

	// Sets the viewport to the screen dimensions
	glViewport(0, 0, width, height);

	//Set the base depth to 1.0
	glClearDepth(1.0);

	// Clear the color and depth buffers
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Render OpenGL here
	static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
	glClearBufferfv(GL_COLOR, 0, green);

	// Use the program object we created earlier for rendering
	glUseProgram(_program);

	GLfloat attrib[] = { (float)sin(glfwGetTime()) * 0.5f,
		(float)cos(glfwGetTime()) * 0.6f,
		0.0f, 0.0f };

	// Pass our offset to vertex data to the vertex shader
	glVertexAttrib4fv(0, attrib);

	glDrawArrays(GL_TRIANGLES, 0, 3);

	// Swap front and back buffers
	glfwSwapBuffers(_window);
}

void Game::errorCallback(int error, const char * description)
{
	fputs(description, stderr);
}

void Game::keyCallback(GLFWwindow * window, int key, int scancode, int action, int mods)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, GL_TRUE);
	}

	if (key == GLFW_KEY_Q && action == GLFW_PRESS)
	{
		std::cout << "Quit" << std::endl;
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. 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.
// 3. The name of the author may not be used to endorse or promote products
//    derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.

// This file is a replacement for the original auth.c PC/SC-Lite internal
// implementation file.

extern "C" {
#include "auth.h"
}

unsigned IsClientAuthorized(
    int socket, const char* action, const char* reader) {
  // This naclport of pcsc-lite library don't have a polkit authorization of
  // clients, so just allowing arbitrary client connections here.
  return 1;
}
<commit_msg>Fix a typo<commit_after>// Copyright 2016 Google Inc.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. 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.
// 3. The name of the author may not be used to endorse or promote products
//    derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.

// This file is a replacement for the original auth.c PC/SC-Lite internal
// implementation file.

extern "C" {
#include "auth.h"
}

unsigned IsClientAuthorized(
    int socket, const char* action, const char* reader) {
  // This naclport of pcsc-lite library doesn't have a polkit authorization of
  // clients, so just allowing arbitrary client connections here.
  return 1;
}
<|endoftext|>


<commit_before>#include "setupdialog.h"

#include <QDateTime>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QStandardPaths>

// This is used for QHostInfo::localHostName().  It could be replaced with
// QSysInfo::machineHostName() to remove the dependency on the Qt network
// library, but only if we require Qt 5.6+.
#include <QHostInfo>

#include "ui_setupdialog.h"

#include "debug.h"
#include "utils.h"

#include <TSettings.h>

SetupDialog::SetupDialog(QWidget *parent)
    : QDialog(parent),
      _ui(new Ui::SetupDialog),
      _loadingAnimation(":/icons/loading.gif")
{
    _ui->setupUi(this);
    setWindowFlags((windowFlags() | Qt::CustomizeWindowHint)
                   & ~Qt::WindowMaximizeButtonHint);

    // These should be done before connecting objects to
    // validateAdvancedSetupPage() to avoid calling that function
    // unnecessarily.
    _tarsnapDir = Utils::findTarsnapClientInPath("", true);
    _ui->tarsnapPathLineEdit->setText(_tarsnapDir);
    _ui->machineNameLineEdit->setText(QHostInfo::localHostName());
    _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);

    _appDataDir = QStandardPaths::writableLocation(APPDATA);
    QDir keysDir(_appDataDir);
    if(!keysDir.exists())
        keysDir.mkpath(_appDataDir);
    _ui->appDataPathLineEdit->setText(_appDataDir);

    // find existing keys
    for(const QFileInfo &file : Utils::findKeysInPath(_appDataDir))
        _ui->machineKeyCombo->addItem(file.canonicalFilePath());

    _tarsnapCacheDir =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
    QDir cacheDir(_tarsnapCacheDir);
    if(!cacheDir.exists())
        cacheDir.mkpath(_tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(_tarsnapCacheDir);

    _ui->loadingIconLabel->setMovie(&_loadingAnimation);
    _ui->advancedCLIWidget->hide();

    // All pages
    connect(_ui->backButton, &QPushButton::clicked, this,
            &SetupDialog::backButtonClicked);
    connect(_ui->nextButton, &QPushButton::clicked, this,
            &SetupDialog::nextButtonClicked);
    connect(_ui->welcomePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->advancedPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->registerPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->donePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);

    connect(_ui->wizardStackedWidget, &QStackedWidget::currentChanged, this,
            &SetupDialog::wizardPageChanged);

    // Advanced setup page
    connect(_ui->advancedCLIButton, &QPushButton::toggled,
            _ui->advancedCLIWidget, &QWidget::setVisible);
    connect(_ui->tarsnapPathBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapPathBrowse);
    connect(_ui->tarsnapPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->tarsnapCacheBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapCacheBrowse);
    connect(_ui->tarsnapCacheLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->appDataBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showAppDataBrowse);
    connect(_ui->appDataPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);

    // Register page
    connect(_ui->restoreNoButton, &QPushButton::clicked, this,
            &SetupDialog::restoreNo);
    connect(_ui->restoreYesButton, &QPushButton::clicked, this,
            &SetupDialog::restoreYes);
    connect(_ui->tarsnapUserLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->tarsnapPasswordLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineNameLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineKeyCombo, &QComboBox::currentTextChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->browseKeyButton, &QPushButton::clicked, this,
            &SetupDialog::registerHaveKeyBrowse);

    wizardPageChanged(0);
}

SetupDialog::~SetupDialog()
{
    delete _ui;
}

void SetupDialog::wizardPageChanged(int)
{
    // Values which might be overwritten below.
    _ui->backButton->setText(tr("Back"));
    _ui->nextButton->setText(tr("Next"));
    _ui->nextButton->setEnabled(true);

    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->welcomePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup wizard"));
        _ui->backButton->setText(tr("Skip wizard"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->advancedPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Command-line utilities"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->registerPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Register with server"));
        _ui->nextButton->setText(tr("Register machine"));
        if(_ui->machineKeyCombo->count() > 0)
        {
            _ui->restoreYesButton->setChecked(true);
            restoreYes();
        }
        else
        {
            _ui->restoreNoButton->setChecked(true);
            restoreNo();
        }
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
    {
        _ui->donePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup complete!"));
        _ui->nextButton->setText(tr("Start using Tarsnap"));
    }
}

void SetupDialog::backButtonClicked()
{
    int nextIndex = _ui->wizardStackedWidget->currentIndex() - 1;
    if(nextIndex < 0)
        commitSettings(true);
    else
        _ui->wizardStackedWidget->setCurrentIndex(nextIndex);
}

void SetupDialog::nextButtonClicked()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
        registerMachine();
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
        commitSettings(false);
    else
        setNextPage();
}

void SetupDialog::skipToPage()
{
    if(sender() == _ui->welcomePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);
    else if(sender() == _ui->advancedPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
    else if(sender() == _ui->registerPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
    else if(sender() == _ui->donePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
}

void SetupDialog::setNextPage()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
        _ui->advancedPageRadioButton->setEnabled(true);
        bool advancedOk = validateAdvancedSetupPage();
        _ui->advancedCLIButton->setChecked(!advancedOk);
        if(advancedOk)
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
        _ui->registerPageRadioButton->setEnabled(true);
        if(validateRegisterPage())
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
        _ui->donePageRadioButton->setEnabled(true);
    }
}

void SetupDialog::showTarsnapPathBrowse()
{
    QString tarsnapPath =
        QFileDialog::getExistingDirectory(this, tr("Find Tarsnap client"), "");
    _ui->tarsnapPathLineEdit->setText(tarsnapPath);
}

void SetupDialog::showTarsnapCacheBrowse()
{
    QString tarsnapCacheDir =
        QFileDialog::getExistingDirectory(this, tr("Tarsnap cache location"),
                                          _tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(tarsnapCacheDir);
}

void SetupDialog::showAppDataBrowse()
{
    QString appDataDir =
        QFileDialog::getExistingDirectory(this, tr("App data location"), "");
    _ui->appDataPathLineEdit->setText(appDataDir);
}

bool SetupDialog::validateAdvancedSetupPage()
{
    bool result = true;

    _appDataDir = Utils::validateAppDataDir(_ui->appDataPathLineEdit->text());
    if(_appDataDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(tr("Invalid App data directory "
                                                 "set."));
        result = false;
    }

    _tarsnapCacheDir =
        Utils::validateTarsnapCache(_ui->tarsnapCacheLineEdit->text());
    if(result && _tarsnapCacheDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Invalid Tarsnap cache directory"
               " set."));
        result = false;
    }

    _tarsnapDir =
        Utils::findTarsnapClientInPath(_ui->tarsnapPathLineEdit->text(), true);
    if(result && _tarsnapDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap utilities not found. Visit "
               "tarsnap.com "
               "for help with acquiring them."));
        result = false;
    }
    else if(result)
    {
        emit getTarsnapVersion(_tarsnapDir);
    }

    _ui->nextButton->setEnabled(result);

    return result;
}

void SetupDialog::restoreNo()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyNoPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyNoLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

void SetupDialog::restoreYes()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyYesPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyYesLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

bool SetupDialog::validateRegisterPage()
{
    bool result = false;
    if(_ui->restoreYesButton->isChecked())
    {
        // user specified key
        QFileInfo machineKeyFile(_ui->machineKeyCombo->currentText());
        if(!_ui->machineNameLineEdit->text().isEmpty() && machineKeyFile.exists()
           && machineKeyFile.isFile() && machineKeyFile.isReadable())
        {
            result = true;
        }
    }
    else
    {
        if(!_ui->tarsnapUserLineEdit->text().isEmpty()
           && !_ui->tarsnapPasswordLineEdit->text().isEmpty()
           && !_ui->machineNameLineEdit->text().isEmpty())
        {
            result = true;
        }
    }

    _ui->nextButton->setEnabled(result);
    return result;
}

void SetupDialog::registerHaveKeyBrowse()
{
    QString keyFilter = tr("Tarsnap key files (*.key *.keys)");
    QString existingMachineKey =
        QFileDialog::getOpenFileName(this,
                                     tr("Browse for existing machine key"), "",
                                     tr("All files (*);;") + keyFilter,
                                     &keyFilter);
    if(!existingMachineKey.isEmpty())
        _ui->machineKeyCombo->setCurrentText(existingMachineKey);
}

void SetupDialog::registerMachine()
{
    _ui->nextButton->setEnabled(false);
    _ui->statusLabel->clear();
    _ui->statusLabel->setStyleSheet("");
    if(_ui->restoreYesButton->isChecked())
    {
        _ui->statusLabel->setText("Verifying archive integrity...");
        _tarsnapKeyFile = _ui->machineKeyCombo->currentText();
    }
    else
    {
        _ui->statusLabel->setText("Generating keyfile...");
        _tarsnapKeyFile =
            _appDataDir + QDir::separator() + _ui->machineNameLineEdit->text()
            + "-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")
            + ".key";
    }

    emit requestRegisterMachine(_ui->tarsnapUserLineEdit->text(),
                                _ui->tarsnapPasswordLineEdit->text(),
                                _ui->machineNameLineEdit->text(),
                                _tarsnapKeyFile, _tarsnapDir, _tarsnapCacheDir);
}

void SetupDialog::registerMachineStatus(TaskStatus status, QString reason)
{
    switch(status)
    {
    case TaskStatus::Completed:
        _ui->statusLabel->clear();
        _ui->doneKeyFileNameLabel->setText(
            QString("%2")
                .arg(QUrl::fromLocalFile(
                         QFileInfo(_tarsnapKeyFile).absolutePath())
                         .toString())
                .arg(_tarsnapKeyFile));
        _ui->nextButton->setEnabled(true);
        setNextPage();
        break;
    case TaskStatus::Failed:
        _ui->statusLabel->setText(reason);
        _ui->statusLabel->setStyleSheet("#statusLabel { color: darkred; }");
        _ui->nextButton->setEnabled(true);
        break;
    case Initialized:
    case Queued:
    case Running:
    case Paused:
    default:
        break;
    }
}

void SetupDialog::updateLoadingAnimation(bool idle)
{
    if(idle)
    {
        _loadingAnimation.stop();
        _ui->loadingIconLabel->hide();
    }
    else
    {
        _loadingAnimation.start();
        _ui->loadingIconLabel->show();
    }
}

void SetupDialog::setTarsnapVersion(QString versionString)
{
    _tarsnapVersion = versionString;
    if(!_tarsnapVersion.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + _tarsnapVersion + tr(" detected.  ✔"));
    }
}

void SetupDialog::commitSettings(bool skipped)
{
    TSettings settings;

    settings.setValue("app/wizard_done", true);

    if(!skipped)
    {
        settings.setValue("app/app_data", _appDataDir);
        settings.setValue("tarsnap/path", _tarsnapDir);
        settings.setValue("tarsnap/version", _tarsnapVersion);
        settings.setValue("tarsnap/cache", _tarsnapCacheDir);
        settings.setValue("tarsnap/key", _tarsnapKeyFile);
        settings.setValue("tarsnap/user", _ui->tarsnapUserLineEdit->text());
        settings.setValue("tarsnap/machine", _ui->machineNameLineEdit->text());
    }
    settings.sync();

    // We initialize/verify the cache with fsck-prune for existing keys
    // anyway, so we only need to initialize for new keys here.
    if(!skipped && _ui->restoreNoButton->isChecked())
        emit initializeCache();

    accept();
}
<commit_msg>SetupDialog: remove unneeded "default:"<commit_after>#include "setupdialog.h"

#include <QDateTime>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QStandardPaths>

// This is used for QHostInfo::localHostName().  It could be replaced with
// QSysInfo::machineHostName() to remove the dependency on the Qt network
// library, but only if we require Qt 5.6+.
#include <QHostInfo>

#include "ui_setupdialog.h"

#include "debug.h"
#include "utils.h"

#include <TSettings.h>

SetupDialog::SetupDialog(QWidget *parent)
    : QDialog(parent),
      _ui(new Ui::SetupDialog),
      _loadingAnimation(":/icons/loading.gif")
{
    _ui->setupUi(this);
    setWindowFlags((windowFlags() | Qt::CustomizeWindowHint)
                   & ~Qt::WindowMaximizeButtonHint);

    // These should be done before connecting objects to
    // validateAdvancedSetupPage() to avoid calling that function
    // unnecessarily.
    _tarsnapDir = Utils::findTarsnapClientInPath("", true);
    _ui->tarsnapPathLineEdit->setText(_tarsnapDir);
    _ui->machineNameLineEdit->setText(QHostInfo::localHostName());
    _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);

    _appDataDir = QStandardPaths::writableLocation(APPDATA);
    QDir keysDir(_appDataDir);
    if(!keysDir.exists())
        keysDir.mkpath(_appDataDir);
    _ui->appDataPathLineEdit->setText(_appDataDir);

    // find existing keys
    for(const QFileInfo &file : Utils::findKeysInPath(_appDataDir))
        _ui->machineKeyCombo->addItem(file.canonicalFilePath());

    _tarsnapCacheDir =
        QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
    QDir cacheDir(_tarsnapCacheDir);
    if(!cacheDir.exists())
        cacheDir.mkpath(_tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(_tarsnapCacheDir);

    _ui->loadingIconLabel->setMovie(&_loadingAnimation);
    _ui->advancedCLIWidget->hide();

    // All pages
    connect(_ui->backButton, &QPushButton::clicked, this,
            &SetupDialog::backButtonClicked);
    connect(_ui->nextButton, &QPushButton::clicked, this,
            &SetupDialog::nextButtonClicked);
    connect(_ui->welcomePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->advancedPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->registerPageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);
    connect(_ui->donePageRadioButton, &QRadioButton::clicked, this,
            &SetupDialog::skipToPage);

    connect(_ui->wizardStackedWidget, &QStackedWidget::currentChanged, this,
            &SetupDialog::wizardPageChanged);

    // Advanced setup page
    connect(_ui->advancedCLIButton, &QPushButton::toggled,
            _ui->advancedCLIWidget, &QWidget::setVisible);
    connect(_ui->tarsnapPathBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapPathBrowse);
    connect(_ui->tarsnapPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->tarsnapCacheBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showTarsnapCacheBrowse);
    connect(_ui->tarsnapCacheLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);
    connect(_ui->appDataBrowseButton, &QPushButton::clicked, this,
            &SetupDialog::showAppDataBrowse);
    connect(_ui->appDataPathLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateAdvancedSetupPage);

    // Register page
    connect(_ui->restoreNoButton, &QPushButton::clicked, this,
            &SetupDialog::restoreNo);
    connect(_ui->restoreYesButton, &QPushButton::clicked, this,
            &SetupDialog::restoreYes);
    connect(_ui->tarsnapUserLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->tarsnapPasswordLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineNameLineEdit, &QLineEdit::textChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->machineKeyCombo, &QComboBox::currentTextChanged, this,
            &SetupDialog::validateRegisterPage);
    connect(_ui->browseKeyButton, &QPushButton::clicked, this,
            &SetupDialog::registerHaveKeyBrowse);

    wizardPageChanged(0);
}

SetupDialog::~SetupDialog()
{
    delete _ui;
}

void SetupDialog::wizardPageChanged(int)
{
    // Values which might be overwritten below.
    _ui->backButton->setText(tr("Back"));
    _ui->nextButton->setText(tr("Next"));
    _ui->nextButton->setEnabled(true);

    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->welcomePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup wizard"));
        _ui->backButton->setText(tr("Skip wizard"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->advancedPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Command-line utilities"));
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->registerPageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Register with server"));
        _ui->nextButton->setText(tr("Register machine"));
        if(_ui->machineKeyCombo->count() > 0)
        {
            _ui->restoreYesButton->setChecked(true);
            restoreYes();
        }
        else
        {
            _ui->restoreNoButton->setChecked(true);
            restoreNo();
        }
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
    {
        _ui->donePageRadioButton->setChecked(true);
        _ui->titleLabel->setText(tr("Setup complete!"));
        _ui->nextButton->setText(tr("Start using Tarsnap"));
    }
}

void SetupDialog::backButtonClicked()
{
    int nextIndex = _ui->wizardStackedWidget->currentIndex() - 1;
    if(nextIndex < 0)
        commitSettings(true);
    else
        _ui->wizardStackedWidget->setCurrentIndex(nextIndex);
}

void SetupDialog::nextButtonClicked()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
        registerMachine();
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->donePage)
        commitSettings(false);
    else
        setNextPage();
}

void SetupDialog::skipToPage()
{
    if(sender() == _ui->welcomePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->welcomePage);
    else if(sender() == _ui->advancedPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
    else if(sender() == _ui->registerPageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
    else if(sender() == _ui->donePageRadioButton)
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
}

void SetupDialog::setNextPage()
{
    if(_ui->wizardStackedWidget->currentWidget() == _ui->welcomePage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->advancedPage);
        _ui->advancedPageRadioButton->setEnabled(true);
        bool advancedOk = validateAdvancedSetupPage();
        _ui->advancedCLIButton->setChecked(!advancedOk);
        if(advancedOk)
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->advancedPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->registerPage);
        _ui->registerPageRadioButton->setEnabled(true);
        if(validateRegisterPage())
            _ui->nextButton->setFocus();
    }
    else if(_ui->wizardStackedWidget->currentWidget() == _ui->registerPage)
    {
        _ui->wizardStackedWidget->setCurrentWidget(_ui->donePage);
        _ui->donePageRadioButton->setEnabled(true);
    }
}

void SetupDialog::showTarsnapPathBrowse()
{
    QString tarsnapPath =
        QFileDialog::getExistingDirectory(this, tr("Find Tarsnap client"), "");
    _ui->tarsnapPathLineEdit->setText(tarsnapPath);
}

void SetupDialog::showTarsnapCacheBrowse()
{
    QString tarsnapCacheDir =
        QFileDialog::getExistingDirectory(this, tr("Tarsnap cache location"),
                                          _tarsnapCacheDir);
    _ui->tarsnapCacheLineEdit->setText(tarsnapCacheDir);
}

void SetupDialog::showAppDataBrowse()
{
    QString appDataDir =
        QFileDialog::getExistingDirectory(this, tr("App data location"), "");
    _ui->appDataPathLineEdit->setText(appDataDir);
}

bool SetupDialog::validateAdvancedSetupPage()
{
    bool result = true;

    _appDataDir = Utils::validateAppDataDir(_ui->appDataPathLineEdit->text());
    if(_appDataDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(tr("Invalid App data directory "
                                                 "set."));
        result = false;
    }

    _tarsnapCacheDir =
        Utils::validateTarsnapCache(_ui->tarsnapCacheLineEdit->text());
    if(result && _tarsnapCacheDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Invalid Tarsnap cache directory"
               " set."));
        result = false;
    }

    _tarsnapDir =
        Utils::findTarsnapClientInPath(_ui->tarsnapPathLineEdit->text(), true);
    if(result && _tarsnapDir.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap utilities not found. Visit "
               "tarsnap.com "
               "for help with acquiring them."));
        result = false;
    }
    else if(result)
    {
        emit getTarsnapVersion(_tarsnapDir);
    }

    _ui->nextButton->setEnabled(result);

    return result;
}

void SetupDialog::restoreNo()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyNoPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyNoLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

void SetupDialog::restoreYes()
{
    _ui->registerKeyStackedWidget->setCurrentWidget(_ui->keyYesPage);
    // Share machineNameLineEdit in both pages of the keyStackedWidget
    _ui->gridKeyYesLayout->addWidget(_ui->machineNameLineEdit, 1, 1);
    _ui->statusLabel->clear();
    if(validateRegisterPage())
        _ui->nextButton->setFocus();
}

bool SetupDialog::validateRegisterPage()
{
    bool result = false;
    if(_ui->restoreYesButton->isChecked())
    {
        // user specified key
        QFileInfo machineKeyFile(_ui->machineKeyCombo->currentText());
        if(!_ui->machineNameLineEdit->text().isEmpty() && machineKeyFile.exists()
           && machineKeyFile.isFile() && machineKeyFile.isReadable())
        {
            result = true;
        }
    }
    else
    {
        if(!_ui->tarsnapUserLineEdit->text().isEmpty()
           && !_ui->tarsnapPasswordLineEdit->text().isEmpty()
           && !_ui->machineNameLineEdit->text().isEmpty())
        {
            result = true;
        }
    }

    _ui->nextButton->setEnabled(result);
    return result;
}

void SetupDialog::registerHaveKeyBrowse()
{
    QString keyFilter = tr("Tarsnap key files (*.key *.keys)");
    QString existingMachineKey =
        QFileDialog::getOpenFileName(this,
                                     tr("Browse for existing machine key"), "",
                                     tr("All files (*);;") + keyFilter,
                                     &keyFilter);
    if(!existingMachineKey.isEmpty())
        _ui->machineKeyCombo->setCurrentText(existingMachineKey);
}

void SetupDialog::registerMachine()
{
    _ui->nextButton->setEnabled(false);
    _ui->statusLabel->clear();
    _ui->statusLabel->setStyleSheet("");
    if(_ui->restoreYesButton->isChecked())
    {
        _ui->statusLabel->setText("Verifying archive integrity...");
        _tarsnapKeyFile = _ui->machineKeyCombo->currentText();
    }
    else
    {
        _ui->statusLabel->setText("Generating keyfile...");
        _tarsnapKeyFile =
            _appDataDir + QDir::separator() + _ui->machineNameLineEdit->text()
            + "-" + QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")
            + ".key";
    }

    emit requestRegisterMachine(_ui->tarsnapUserLineEdit->text(),
                                _ui->tarsnapPasswordLineEdit->text(),
                                _ui->machineNameLineEdit->text(),
                                _tarsnapKeyFile, _tarsnapDir, _tarsnapCacheDir);
}

void SetupDialog::registerMachineStatus(TaskStatus status, QString reason)
{
    switch(status)
    {
    case TaskStatus::Completed:
        _ui->statusLabel->clear();
        _ui->doneKeyFileNameLabel->setText(
            QString("%2")
                .arg(QUrl::fromLocalFile(
                         QFileInfo(_tarsnapKeyFile).absolutePath())
                         .toString())
                .arg(_tarsnapKeyFile));
        _ui->nextButton->setEnabled(true);
        setNextPage();
        break;
    case TaskStatus::Failed:
        _ui->statusLabel->setText(reason);
        _ui->statusLabel->setStyleSheet("#statusLabel { color: darkred; }");
        _ui->nextButton->setEnabled(true);
        break;
    case Initialized:
    case Queued:
    case Running:
    case Paused:
        break;
    }
}

void SetupDialog::updateLoadingAnimation(bool idle)
{
    if(idle)
    {
        _loadingAnimation.stop();
        _ui->loadingIconLabel->hide();
    }
    else
    {
        _loadingAnimation.start();
        _ui->loadingIconLabel->show();
    }
}

void SetupDialog::setTarsnapVersion(QString versionString)
{
    _tarsnapVersion = versionString;
    if(!_tarsnapVersion.isEmpty())
    {
        _ui->advancedValidationLabel->setText(
            tr("Tarsnap CLI version ") + _tarsnapVersion + tr(" detected.  ✔"));
    }
}

void SetupDialog::commitSettings(bool skipped)
{
    TSettings settings;

    settings.setValue("app/wizard_done", true);

    if(!skipped)
    {
        settings.setValue("app/app_data", _appDataDir);
        settings.setValue("tarsnap/path", _tarsnapDir);
        settings.setValue("tarsnap/version", _tarsnapVersion);
        settings.setValue("tarsnap/cache", _tarsnapCacheDir);
        settings.setValue("tarsnap/key", _tarsnapKeyFile);
        settings.setValue("tarsnap/user", _ui->tarsnapUserLineEdit->text());
        settings.setValue("tarsnap/machine", _ui->machineNameLineEdit->text());
    }
    settings.sync();

    // We initialize/verify the cache with fsck-prune for existing keys
    // anyway, so we only need to initialize for new keys here.
    if(!skipped && _ui->restoreNoButton->isChecked())
        emit initializeCache();

    accept();
}
<|endoftext|>


<commit_before>//Names should contain a comma seperated list of cut settings
//Current options: all, electrons, TTreeCuts, V0_TPCcorr, V0_ITScorr
AliAnalysisTask *AddTask_acapon(TString outputFileName = "AnalysisResult.root", TString names ="electrons",
                                Bool_t SDDstatus = kFALSE, Bool_t getFromAlien = kFALSE,
                                Bool_t doPairing = kTRUE,  Bool_t doMixing = kTRUE,
                                Bool_t useTPCcorr = kFALSE, Bool_t useITScorr = kFALSE){

		TObjArray *arrNames = names.Tokenize(";");
		Int_t nDie = arrNames->GetEntries();
    Printf("Number of implemented cuts: %i", nDie);

    //get the current analysis manager
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        Error("AddTask_acapon", "No analysis manager found.");
        return 0;
    }

    Bool_t bESDANA=kFALSE; //Autodetect via InputHandler

    //TString configBasePath("/home/aaron/analyses/LHC16q/eeFrameworkQA/"); //Local
    TString configBasePath("$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/"); //AliPhysics
    TString configFile("Config_acapon.C");
    TString configLMEECutLib("LMEECutLib_acapon.C");

    //Load updated macros from private ALIEN path
    TString myConfig ="alien_cp alien:///alice/cern.ch/user/a/acapon/dielectronShizzle/Config_acapon.C .";
    TString myCutLib ="alien_cp alien:///alice/cern.ch/user/a/acapon/dielectronShizzle/LMEECutLib_acapon.C .";
    if (getFromAlien && (!gSystem->Exec(myConfig)) && (!gSystem->Exec(myCutLib))){

        std::cout << "Copy config from Alien" << std::endl;
        configBasePath=Form("%s/",gSystem->pwd());
    }

    TString configFilePath(configBasePath+configFile);
    TString configLMEECutLibPath(configBasePath+configLMEECutLib);

    //load dielectron configuration files
    if(!gROOT->GetListOfGlobalFunctions()->FindObject(configLMEECutLib.Data())){
        gROOT->LoadMacro(configLMEECutLibPath.Data());
    }
    if(!gROOT->GetListOfGlobalFunctions()->FindObject(configFile.Data())){
        gROOT->LoadMacro(configFilePath.Data());
    }

    // cut lib
    LMEECutLib* cutlib = new LMEECutLib(SDDstatus);

    //Do we have an MC handler?
    Bool_t hasMC=(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()! = 0x0);

    //AOD Usage currently tested with Input handler
    if (mgr->GetInputEventHandler()->IsA()==AliAODInputHandler::Class()){
        ::Info("AddTask_acapon", "no dedicated AOD configuration"); //Prepended :: ensures resolution occurs from global namespace, not current one
    }
    else if (mgr->GetInputEventHandler()->IsA()==AliESDInputHandler::Class()){
        ::Info("AddTask_acapon","switching on ESD specific code");
        bESDANA=kTRUE;
    }

    //create task and add it to the manager
    AliAnalysisTaskMultiDielectron *task = new AliAnalysisTaskMultiDielectron("DielectronTask");
		if(!task){
			::Error("AddTask_acapon", "MultiDielectron trask not created");
			return 0x0;
		}

		//Add event filter
    Int_t triggerNames = (AliVEvent::kINT7);
    task->SetEventFilter(cutlib->GetEventCuts(LMEECutLib::kAllSpecies));
    task->SelectCollisionCandidates(triggerNames);
    task->SetTriggerMask(triggerNames);
    //task->SetRejectPileup();
    // Note: event cuts are identical for all analysis 'cutDefinition's that run together!

    // Add the task to the manager
    mgr->AddTask(task);
    //add dielectron analysis with different cuts to the task
    for (Int_t i=0; i<nDie; ++i){
        //MB
				TString dielTaskName(arrNames->At(i)->GetName());
        AliDielectron *diel_low = Config_acapon(dielTaskName, hasMC, bESDANA, SDDstatus, doPairing, doMixing, useTPCcorr, useITScorr);
        if(!diel_low){ continue; }
        task->AddDielectron(diel_low);
        printf("successfully added AliDielectron: %s\n",diel_low->GetName());
    }//loop

    //create output container
    AliAnalysisDataContainer *coutput1 =
    mgr->CreateContainer("acapon_tree",
                         TTree::Class(),
                         AliAnalysisManager::kExchangeContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist1 =
    mgr->CreateContainer("acapon_out",
                         TList::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist2 =
    mgr->CreateContainer("acapon_CF",
                         TList::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist3 =
    mgr->CreateContainer("acapon_EventStat",
                         TH1D::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    mgr->ConnectInput(task,  0, mgr->GetCommonInputContainer());
    mgr->ConnectOutput(task, 0, coutput1 );
    mgr->ConnectOutput(task, 1, cOutputHist1);
    mgr->ConnectOutput(task, 2, cOutputHist2);
    mgr->ConnectOutput(task, 3, cOutputHist3);

    return task;
}
<commit_msg>AddTask_acapon: Unique outputs for train runs<commit_after>//Names should contain a comma seperated list of cut settings
//Current options: all, electrons, TTreeCuts, V0_TPCcorr, V0_ITScorr
AliAnalysisTask *AddTask_acapon(TString outputFileName = "AnalysisResult.root", TString names ="electrons",
                                Bool_t SDDstatus = kFALSE, Bool_t getFromAlien = kFALSE,
                                Bool_t doPairing = kTRUE,  Bool_t doMixing = kTRUE,
                                Bool_t useTPCcorr = kFALSE, Bool_t useITScorr = kFALSE,
																Int_t wagonNum = 0){

		TObjArray *arrNames = names.Tokenize(";");
		Int_t nDie = arrNames->GetEntries();
    Printf("Number of implemented cuts: %i", nDie);

    //get the current analysis manager
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
        Error("AddTask_acapon", "No analysis manager found.");
        return 0;
    }

    Bool_t bESDANA=kFALSE; //Autodetect via InputHandler

    //TString configBasePath("/home/aaron/analyses/LHC16q/eeFrameworkQA/"); //Local
    TString configBasePath("$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/"); //AliPhysics
    TString configFile("Config_acapon.C");
    TString configLMEECutLib("LMEECutLib_acapon.C");

    //Load updated macros from private ALIEN path
    TString myConfig ="alien_cp alien:///alice/cern.ch/user/a/acapon/dielectronShizzle/Config_acapon.C .";
    TString myCutLib ="alien_cp alien:///alice/cern.ch/user/a/acapon/dielectronShizzle/LMEECutLib_acapon.C .";
    if (getFromAlien && (!gSystem->Exec(myConfig)) && (!gSystem->Exec(myCutLib))){

        std::cout << "Copy config from Alien" << std::endl;
        configBasePath=Form("%s/",gSystem->pwd());
    }

    TString configFilePath(configBasePath+configFile);
    TString configLMEECutLibPath(configBasePath+configLMEECutLib);

    //load dielectron configuration files
    if(!gROOT->GetListOfGlobalFunctions()->FindObject(configLMEECutLib.Data())){
        gROOT->LoadMacro(configLMEECutLibPath.Data());
    }
    if(!gROOT->GetListOfGlobalFunctions()->FindObject(configFile.Data())){
        gROOT->LoadMacro(configFilePath.Data());
    }

    // cut lib
    LMEECutLib* cutlib = new LMEECutLib(SDDstatus);

    //Do we have an MC handler?
    Bool_t hasMC=(AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler()! = 0x0);

    //AOD Usage currently tested with Input handler
    if (mgr->GetInputEventHandler()->IsA()==AliAODInputHandler::Class()){
        ::Info("AddTask_acapon", "no dedicated AOD configuration"); //Prepended :: ensures resolution occurs from global namespace, not current one
    }
    else if (mgr->GetInputEventHandler()->IsA()==AliESDInputHandler::Class()){
        ::Info("AddTask_acapon","switching on ESD specific code");
        bESDANA=kTRUE;
    }

    //create task and add it to the manager
    AliAnalysisTaskMultiDielectron *task = new AliAnalysisTaskMultiDielectron(Form("DielectronTask%d", wagonNum));
		if(!task){
			::Error("AddTask_acapon", "MultiDielectron trask not created");
			return 0x0;
		}

		//Add event filter
    Int_t triggerNames = (AliVEvent::kINT7);
    task->SetEventFilter(cutlib->GetEventCuts(LMEECutLib::kAllSpecies));
    task->SelectCollisionCandidates(triggerNames);
    task->SetTriggerMask(triggerNames);
    //task->SetRejectPileup();
    // Note: event cuts are identical for all analysis 'cutDefinition's that run together!

    // Add the task to the manager
    mgr->AddTask(task);
    //add dielectron analysis with different cuts to the task
    for (Int_t i=0; i<nDie; ++i){
        //MB
				TString dielTaskName(arrNames->At(i)->GetName());
        AliDielectron *diel_low = Config_acapon(dielTaskName, hasMC, bESDANA, SDDstatus, doPairing, doMixing, useTPCcorr, useITScorr);
        if(!diel_low){ continue; }
        task->AddDielectron(diel_low);
        printf("successfully added AliDielectron: %s\n",diel_low->GetName());
    }//loop

    //create output container
    AliAnalysisDataContainer *coutput1 =
    mgr->CreateContainer(Form("acapon_tree_%d",wagonNum),
                         TTree::Class(),
                         AliAnalysisManager::kExchangeContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist1 =
    mgr->CreateContainer(Form("acapon_out_%d", wagonNum),
                         TList::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist2 =
    mgr->CreateContainer(Form("acapon_CF_%d", wagonNum),
                         TList::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    AliAnalysisDataContainer *cOutputHist3 =
    mgr->CreateContainer(Form("acapon_EventStat_%d", wagonNum),
                         TH1D::Class(),
                         AliAnalysisManager::kOutputContainer,
                         outputFileName.Data());

    mgr->ConnectInput(task,  0, mgr->GetCommonInputContainer());
    mgr->ConnectOutput(task, 0, coutput1 );
    mgr->ConnectOutput(task, 1, cOutputHist1);
    mgr->ConnectOutput(task, 2, cOutputHist2);
    mgr->ConnectOutput(task, 3, cOutputHist3);

    return task;
}
<|endoftext|>


<commit_before>#include "Action.h"

#include <Exd/ExdDataGenerated.h>
#include <Util/Util.h>
#include "Framework.h"
#include "Script/ScriptMgr.h"

#include "Actor/Player.h"

#include <Network/CommonActorControl.h>
#include "Network/PacketWrappers/ActorControlPacket142.h"
#include "Network/PacketWrappers/ActorControlPacket143.h"
#include "Network/PacketWrappers/ActorControlPacket144.h"

using namespace Sapphire::Common;
using namespace Sapphire::Network;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;

Sapphire::Action::Action::Action() = default;
Sapphire::Action::Action::~Action() = default;

Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
                                  Data::ActionPtr action, FrameworkPtr fw ) :
                                  m_pSource( std::move( caster ) ),
                                  m_pFw( std::move( fw ) ),
                                  m_id( actionId ),
                                  m_startTime( 0 ),
                                  m_interruptType( Common::ActionInterruptType::None ),
                                  m_hasResidentTarget( false )
{
  m_castTime = static_cast< uint32_t >( action->cast100ms * 100 );
  m_recastTime = static_cast< uint16_t >( action->recast100ms * 100 );
  m_cooldownGroup = action->cooldownGroup;

  m_actionCost.fill( { Common::ActionCostType::None, 0 } );

  m_actionCost[ 0 ] = {
    static_cast< Common::ActionCostType >( action->costType ),
    action->cost
  };

  calculateActionCost();
}

uint32_t Sapphire::Action::Action::getId() const
{
  return m_id;
}

void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos )
{
  m_pos = pos;
}

Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Action::Action::getPos() const
{
  return m_pos;
}

void Sapphire::Action::Action::setTargetChara( Sapphire::Entity::CharaPtr chara )
{
  assert( chara );

  m_pTarget = chara;
  m_targetId = chara->getId();
}

void Sapphire::Action::Action::setResidentTargetId( uint64_t targetId )
{
  m_targetId = targetId;
  m_hasResidentTarget = true;
}

bool Sapphire::Action::Action::hasResidentTarget() const
{
  return m_hasResidentTarget;
}

Sapphire::Entity::CharaPtr Sapphire::Action::Action::getTargetChara() const
{
  return m_pTarget;
}

bool Sapphire::Action::Action::isInterrupted() const
{
  return m_interruptType != Common::ActionInterruptType::None;
}

void Sapphire::Action::Action::setInterrupted( Common::ActionInterruptType type )
{
  m_interruptType = type;
}

void Sapphire::Action::Action::start()
{
  m_startTime = Util::getTimeMs();

  onStart();
}

uint32_t Sapphire::Action::Action::getCastTime() const
{
  return m_castTime;
}

void Sapphire::Action::Action::setCastTime( uint32_t castTime )
{
  m_castTime = castTime;
}

bool Sapphire::Action::Action::isCastedAction() const
{
  return m_castTime > 0;
}

Sapphire::Entity::CharaPtr Sapphire::Action::Action::getActionSource() const
{
  return m_pSource;
}

bool Sapphire::Action::Action::update()
{
  // action has not been started yet
  if( m_startTime == 0 )
    return false;

  if( isInterrupted() )
  {
    onInterrupt();
    return true;
  }

  if( !hasResidentTarget() )
  {
    // todo: check if the target is still in range
  }

  uint64_t currTime = Util::getTimeMs();

  if( !isCastedAction() || std::difftime( currTime, m_startTime ) > m_castTime )
  {
    onFinish();
    return true;
  }

  return false;
}

void Sapphire::Action::Action::onStart()
{
  assert( m_pSource );

  auto player = m_pSource->getAsPlayer();
  if( player )
  {
    player->sendDebug( "onCastStart()" );
  }

  if( isCastedAction() )
  {
    auto castPacket = makeZonePacket< Server::FFXIVIpcActorCast >( getId() );

    castPacket->data().action_id = static_cast< uint16_t >( m_id );
    castPacket->data().skillType = Common::SkillType::Normal;
    castPacket->data().unknown_1 = m_id;
    // This is used for the cast bar above the target bar of the caster.
    castPacket->data().cast_time = m_castTime / 1000.f;
    castPacket->data().target_id = static_cast< uint32_t >( m_targetId );

    m_pSource->sendToInRangeSet( castPacket, true );

    if( player )
    {
      player->setStateFlag( PlayerStateFlag::Casting );
    }
  }
}

void Sapphire::Action::Action::onInterrupt()
{
  assert( m_pSource );

  // things that aren't players don't care about cooldowns and state flags
  if( m_pSource->isPlayer() )
  {
    auto player = m_pSource->getAsPlayer();

    auto resetCooldownPkt = makeActorControl143( m_pSource->getId(), ActorControlType::SetActionCooldown, 1, getId(), 0 );
    player->queuePacket( resetCooldownPkt );

    // todo: reset cooldown for actual player

    // reset state flag
    //player->unsetStateFlag( PlayerStateFlag::Occupied1 );
    player->unsetStateFlag( PlayerStateFlag::Casting );

    player->sendDebug( "onCastInterrupt()" );
  }

  if( isCastedAction() )
  {
    uint8_t interruptEffect = 0;
    if( m_interruptType == ActionInterruptType::DamageInterrupt )
      interruptEffect = 1;

    // Note: When cast interrupt from taking too much damage, set the last value to 1.
    // This enables the cast interrupt effect.
    auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastInterrupt,
                                        0x219, 1, m_id, interruptEffect );

    m_pSource->sendToInRangeSet( control, true );
  }
}

void Sapphire::Action::Action::onFinish()
{
  assert( m_pSource );

  auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();

  auto pPlayer = m_pSource->getAsPlayer();
  pPlayer->sendDebug( "onFinish()" );

  if( isCastedAction() )
  {
    /*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7,
                                            0x219, m_id, m_id, m_id, m_id );
    m_pSource->sendToInRangeSet( control, true );*/

  }

  if( !hasResidentTarget() )
  {
    pScriptMgr->onCastFinish( *m_pSource, *this );
  }
  else
  {
    pScriptMgr->onEObjHit( *pPlayer, m_targetId );
    return;
  }

  // todo: calculate final hit targets and call onCharaHit in action script
}

void Sapphire::Action::Action::buildEffectPacket()
{
  for( int i = 0; i < EffectPacketIdentity::MAX_ACTION_EFFECT_PACKET_IDENT; ++i )
  {
    auto& packetData = m_effects[ static_cast< EffectPacketIdentity >( i ) ];

    // todo: this
  }
}

void Sapphire::Action::Action::damageTarget( uint32_t amount, Entity::Chara& chara,
                                             Common::ActionAspect aspect )
{
  Common::EffectEntry entry{};

  // todo: handle cases where the action misses/is blocked?
  entry.effectType = Common::ActionEffectType::Damage;

  // todo: handle crits
  entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;

  // todo: handle > 65535 damage values, not sure if this is right?
  if( amount > 65535 )
  {
    entry.value = static_cast< int16_t >( amount / 10 );
    // todo: rename this? need to confirm how it works again
    entry.bonusPercent = 1;
  }
  else
    entry.value = static_cast< int16_t >( amount );

  // todo: aspected damage?
  chara.takeDamage( amount );

  m_effects[ EffectPacketIdentity::DamageEffect ].m_entries.emplace_back( entry );

  // todo: make sure that we don't add the same actor more than once
  m_effects[ EffectPacketIdentity::DamageEffect ].m_hitActors.emplace_back( chara.getId() );
}

void Sapphire::Action::Action::healTarget( uint32_t amount, Entity::Chara& chara )
{
  Common::EffectEntry entry{};

  entry.effectType = Common::ActionEffectType::Heal;

  // todo: handle crits
  entry.hitSeverity = Common::ActionHitSeverityType::NormalHeal;

  // todo: handle > 65535 healing values, not sure if this is right?
  if( amount > 65535 )
  {
    entry.value = static_cast< int16_t >( amount / 10 );
    // todo: rename this? need to confirm how it works again
    entry.bonusPercent = 1;
  }
  else
    entry.value = static_cast< int16_t >( amount );

  chara.heal( amount );

  m_effects[ EffectPacketIdentity::HealingEffect ].m_entries.emplace_back( entry );

  // todo: make sure that we don't add the same actor more than once
  m_effects[ EffectPacketIdentity::HealingEffect ].m_hitActors.emplace_back( chara.getId() );
}

const Sapphire::Action::Action::ActionCostArray& Sapphire::Action::Action::getCostArray() const
{
  return m_actionCost;
}

void Sapphire::Action::Action::calculateActionCost()
{
  for( uint8_t i = 0; i < m_actionCost.size(); ++i )
  {
    auto& entry = m_actionCost[ i ];

    if( entry.m_costType == ActionCostType::MagicPoints )
      calculateMPCost( i );
  }
}

void Sapphire::Action::Action::calculateMPCost( uint8_t costArrayIndex )
{
  auto level = m_pSource->getLevel();

  // each level range is 1-10, 11-20, 21-30, ... therefore:
  // level 50 should be in the 4th group, not the 5th
  // dividing by 10 on the border will break this unless we subtract 1
  auto levelGroup = std::max< uint8_t >( level - 1, 1 ) / 10;

  auto& costEntry = m_actionCost[ costArrayIndex ];

  float cost = costEntry.m_cost;

  // thanks to andrew for helping me figure this shit out, should be pretty accurate
  switch( levelGroup )
  {
    // level 1-10
    case 0:
    {
      // r^2 = 0.9999
      cost = 0.0952f * level + 0.9467f;
      break;
    }

      // level 11-20
    case 1:
    {
      // r^2 = 1
      cost = 0.19f * level;
      break;
    }

      // level 21-30
    case 2:
    {
      // r^2 = 1
      cost = 0.38f * level - 3.8f;
      break;
    }

      // level 31-40
    case 3:
    {
      // r^2 = 1
      cost = 0.6652f * level - 12.358f;
      break;
    }

      // level 41-50
    case 4:
    {
      // r^2 = 1
      cost = 1.2352f * level - 35.159f;
      break;
    }

      // level 51-60
    case 5:
    {
      // r^2 = 1
      cost = 0.0654f * std::exp( 0.1201f * level );
      break;
    }

      // level 61-70
    case 6:
    {
      // r^2 = 0.9998
      cost = 0.2313f * ( level * level ) - 26.98f * level + 875.21f;
      break;
    }

    default:
      return;
  }

  // m_cost is the base cost, cost is the multiplier for the current player level
  costEntry.m_cost = static_cast< uint16_t >( std::round( cost * costEntry.m_cost ) );
}<commit_msg>correctly call action script callbacks + some mp debug output<commit_after>#include "Action.h"

#include <Exd/ExdDataGenerated.h>
#include <Util/Util.h>
#include "Framework.h"
#include "Script/ScriptMgr.h"

#include "Actor/Player.h"

#include <Network/CommonActorControl.h>
#include "Network/PacketWrappers/ActorControlPacket142.h"
#include "Network/PacketWrappers/ActorControlPacket143.h"
#include "Network/PacketWrappers/ActorControlPacket144.h"

using namespace Sapphire::Common;
using namespace Sapphire::Network;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::Server;
using namespace Sapphire::Network::ActorControl;

Sapphire::Action::Action::Action() = default;
Sapphire::Action::Action::~Action() = default;

Sapphire::Action::Action::Action( Entity::CharaPtr caster, uint32_t actionId,
                                  Data::ActionPtr action, FrameworkPtr fw ) :
                                  m_pSource( std::move( caster ) ),
                                  m_pFw( std::move( fw ) ),
                                  m_id( actionId ),
                                  m_startTime( 0 ),
                                  m_interruptType( Common::ActionInterruptType::None ),
                                  m_hasResidentTarget( false )
{
  m_castTime = static_cast< uint32_t >( action->cast100ms * 100 );
  m_recastTime = static_cast< uint16_t >( action->recast100ms * 100 );
  m_cooldownGroup = action->cooldownGroup;

  m_actionCost.fill( { Common::ActionCostType::None, 0 } );

  m_actionCost[ 0 ] = {
    static_cast< Common::ActionCostType >( action->costType ),
    action->cost
  };

  calculateActionCost();
}

uint32_t Sapphire::Action::Action::getId() const
{
  return m_id;
}

void Sapphire::Action::Action::setPos( Sapphire::Common::FFXIVARR_POSITION3 pos )
{
  m_pos = pos;
}

Sapphire::Common::FFXIVARR_POSITION3 Sapphire::Action::Action::getPos() const
{
  return m_pos;
}

void Sapphire::Action::Action::setTargetChara( Sapphire::Entity::CharaPtr chara )
{
  assert( chara );

  m_pTarget = chara;
  m_targetId = chara->getId();
}

void Sapphire::Action::Action::setResidentTargetId( uint64_t targetId )
{
  m_targetId = targetId;
  m_hasResidentTarget = true;
}

bool Sapphire::Action::Action::hasResidentTarget() const
{
  return m_hasResidentTarget;
}

Sapphire::Entity::CharaPtr Sapphire::Action::Action::getTargetChara() const
{
  return m_pTarget;
}

bool Sapphire::Action::Action::isInterrupted() const
{
  return m_interruptType != Common::ActionInterruptType::None;
}

void Sapphire::Action::Action::setInterrupted( Common::ActionInterruptType type )
{
  m_interruptType = type;
}

void Sapphire::Action::Action::start()
{
  m_startTime = Util::getTimeMs();

  onStart();
}

uint32_t Sapphire::Action::Action::getCastTime() const
{
  return m_castTime;
}

void Sapphire::Action::Action::setCastTime( uint32_t castTime )
{
  m_castTime = castTime;
}

bool Sapphire::Action::Action::isCastedAction() const
{
  return m_castTime > 0;
}

Sapphire::Entity::CharaPtr Sapphire::Action::Action::getActionSource() const
{
  return m_pSource;
}

bool Sapphire::Action::Action::update()
{
  // action has not been started yet
  if( m_startTime == 0 )
    return false;

  if( isInterrupted() )
  {
    onInterrupt();
    return true;
  }

  if( !hasResidentTarget() )
  {
    // todo: check if the target is still in range
  }

  uint64_t currTime = Util::getTimeMs();

  if( !isCastedAction() || std::difftime( currTime, m_startTime ) > m_castTime )
  {
    onFinish();
    return true;
  }

  return false;
}

void Sapphire::Action::Action::onStart()
{
  assert( m_pSource );

  auto player = m_pSource->getAsPlayer();
  if( player )
  {
    player->sendDebug( "onStart()" );
  }

  if( isCastedAction() )
  {
    auto castPacket = makeZonePacket< Server::FFXIVIpcActorCast >( getId() );

    castPacket->data().action_id = static_cast< uint16_t >( m_id );
    castPacket->data().skillType = Common::SkillType::Normal;
    castPacket->data().unknown_1 = m_id;
    // This is used for the cast bar above the target bar of the caster.
    castPacket->data().cast_time = m_castTime / 1000.f;
    castPacket->data().target_id = static_cast< uint32_t >( m_targetId );

    m_pSource->sendToInRangeSet( castPacket, true );

    if( player )
    {
      player->setStateFlag( PlayerStateFlag::Casting );
    }
  }

  auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
  pScriptMgr->onCastStart( *m_pSource, *this );
}

void Sapphire::Action::Action::onInterrupt()
{
  assert( m_pSource );

  // things that aren't players don't care about cooldowns and state flags
  if( m_pSource->isPlayer() )
  {
    auto player = m_pSource->getAsPlayer();

    auto resetCooldownPkt = makeActorControl143( m_pSource->getId(), ActorControlType::SetActionCooldown, 1, getId(), 0 );
    player->queuePacket( resetCooldownPkt );

    // todo: reset cooldown for actual player

    // reset state flag
    //player->unsetStateFlag( PlayerStateFlag::Occupied1 );
    player->unsetStateFlag( PlayerStateFlag::Casting );

    player->sendDebug( "onInterrupt()" );
  }

  if( isCastedAction() )
  {
    uint8_t interruptEffect = 0;
    if( m_interruptType == ActionInterruptType::DamageInterrupt )
      interruptEffect = 1;

    // Note: When cast interrupt from taking too much damage, set the last value to 1.
    // This enables the cast interrupt effect.
    auto control = makeActorControl142( m_pSource->getId(), ActorControlType::CastInterrupt,
                                        0x219, 1, m_id, interruptEffect );

    m_pSource->sendToInRangeSet( control, true );
  }

  auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();
  pScriptMgr->onCastInterrupt( *m_pSource, *this );
}

void Sapphire::Action::Action::onFinish()
{
  assert( m_pSource );

  auto pScriptMgr = m_pFw->get< Scripting::ScriptMgr >();

  auto pPlayer = m_pSource->getAsPlayer();
  pPlayer->sendDebug( "onFinish()" );

  if( isCastedAction() )
  {
    /*auto control = ActorControlPacket143( m_pTarget->getId(), ActorControlType::Unk7,
                                            0x219, m_id, m_id, m_id, m_id );
    m_pSource->sendToInRangeSet( control, true );*/

  }

  pScriptMgr->onCastFinish( *m_pSource, *this );

  if( !hasResidentTarget() )
  {
    // todo: calculate final hit targets and call onCharaHit in action script
  }
  else
  {
    pScriptMgr->onEObjHit( *pPlayer, m_targetId );
    return;
  }

}

void Sapphire::Action::Action::buildEffectPacket()
{
  for( int i = 0; i < EffectPacketIdentity::MAX_ACTION_EFFECT_PACKET_IDENT; ++i )
  {
    auto& packetData = m_effects[ static_cast< EffectPacketIdentity >( i ) ];

    // todo: this
  }
}

void Sapphire::Action::Action::damageTarget( uint32_t amount, Entity::Chara& chara,
                                             Common::ActionAspect aspect )
{
  Common::EffectEntry entry{};

  // todo: handle cases where the action misses/is blocked?
  entry.effectType = Common::ActionEffectType::Damage;

  // todo: handle crits
  entry.hitSeverity = Common::ActionHitSeverityType::NormalDamage;

  // todo: handle > 65535 damage values, not sure if this is right?
  if( amount > 65535 )
  {
    entry.value = static_cast< int16_t >( amount / 10 );
    // todo: rename this? need to confirm how it works again
    entry.bonusPercent = 1;
  }
  else
    entry.value = static_cast< int16_t >( amount );

  // todo: aspected damage?
  chara.takeDamage( amount );

  m_effects[ EffectPacketIdentity::DamageEffect ].m_entries.emplace_back( entry );

  // todo: make sure that we don't add the same actor more than once
  m_effects[ EffectPacketIdentity::DamageEffect ].m_hitActors.emplace_back( chara.getId() );
}

void Sapphire::Action::Action::healTarget( uint32_t amount, Entity::Chara& chara )
{
  Common::EffectEntry entry{};

  entry.effectType = Common::ActionEffectType::Heal;

  // todo: handle crits
  entry.hitSeverity = Common::ActionHitSeverityType::NormalHeal;

  // todo: handle > 65535 healing values, not sure if this is right?
  if( amount > 65535 )
  {
    entry.value = static_cast< int16_t >( amount / 10 );
    // todo: rename this? need to confirm how it works again
    entry.bonusPercent = 1;
  }
  else
    entry.value = static_cast< int16_t >( amount );

  chara.heal( amount );

  m_effects[ EffectPacketIdentity::HealingEffect ].m_entries.emplace_back( entry );

  // todo: make sure that we don't add the same actor more than once
  m_effects[ EffectPacketIdentity::HealingEffect ].m_hitActors.emplace_back( chara.getId() );
}

const Sapphire::Action::Action::ActionCostArray& Sapphire::Action::Action::getCostArray() const
{
  return m_actionCost;
}

void Sapphire::Action::Action::calculateActionCost()
{
  for( uint8_t i = 0; i < m_actionCost.size(); ++i )
  {
    auto& entry = m_actionCost[ i ];

    if( entry.m_costType == ActionCostType::MagicPoints )
      calculateMPCost( i );
  }
}

void Sapphire::Action::Action::calculateMPCost( uint8_t costArrayIndex )
{
  auto level = m_pSource->getLevel();

  // each level range is 1-10, 11-20, 21-30, ... therefore:
  // level 50 should be in the 4th group, not the 5th
  // dividing by 10 on the border will break this unless we subtract 1
  auto levelGroup = std::max< uint8_t >( level - 1, 1 ) / 10;

  auto& costEntry = m_actionCost[ costArrayIndex ];

  float cost = costEntry.m_cost;

  // thanks to andrew for helping me figure this shit out, should be pretty accurate
  switch( levelGroup )
  {
    // level 1-10
    case 0:
    {
      // r^2 = 0.9999
      cost = 0.0952f * level + 0.9467f;
      break;
    }

      // level 11-20
    case 1:
    {
      // r^2 = 1
      cost = 0.19f * level;
      break;
    }

      // level 21-30
    case 2:
    {
      // r^2 = 1
      cost = 0.38f * level - 3.8f;
      break;
    }

      // level 31-40
    case 3:
    {
      // r^2 = 1
      cost = 0.6652f * level - 12.358f;
      break;
    }

      // level 41-50
    case 4:
    {
      // r^2 = 1
      cost = 1.2352f * level - 35.159f;
      break;
    }

      // level 51-60
    case 5:
    {
      // r^2 = 1
      cost = 0.0654f * std::exp( 0.1201f * level );
      break;
    }

      // level 61-70
    case 6:
    {
      // r^2 = 0.9998
      cost = 0.2313f * ( level * level ) - 26.98f * level + 875.21f;
      break;
    }

    default:
      return;
  }

  // m_cost is the base cost, cost is the multiplier for the current player level
  costEntry.m_cost = static_cast< uint16_t >( std::round( cost * costEntry.m_cost ) );

  if( auto player = m_pSource->getAsPlayer() )
    player->sendDebug( "calculated mp cost: {0}", costEntry.m_cost );
}<|endoftext|>