<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef HAVE_LIBVLC
# error This file requires libvlc
#endif

#include "Common.hpp"
#include "Media.h"
#include "utils/Filename.h"
namespace medialibrary
{

bool medialibrary::MetadataCommon::startPlayback( VLC::Media& media,
                                                  VLC::MediaPlayer& mp,
                                                  compat::Mutex& mutex,
                                                  compat::ConditionVariable& cond )
{
    bool hasVideoTrack = false;
    bool failedToStart = false;
    bool hasAnyTrack = false;
    bool success = false;
    // Use a copy of the event manager to automatically unregister all events as soon
    // as we leave this method.
    auto em = mp.eventManager();

    em.onESAdded([&mutex, &cond, &hasVideoTrack, &hasAnyTrack]( libvlc_track_type_t type, int ) {
        std::lock_guard<compat::Mutex> lock( mutex );
        if ( type == libvlc_track_video )
            hasVideoTrack = true;
        hasAnyTrack = true;
        cond.notify_all();
    });
    em.onEncounteredError([&mutex, &cond, &failedToStart]() {
        std::lock_guard<compat::Mutex> lock( mutex );
        failedToStart = true;
        cond.notify_all();
    });

    bool metaArtworkChanged = false;
    bool watchForArtworkChange = false;
    auto mem = media.eventManager();
    if ( utils::file::schemeIs( "attachment", media.meta( libvlc_meta_ArtworkURL ) ) == true )
    {
        watchForArtworkChange = true;
        mem.onMetaChanged([&mutex, &cond, &metaArtworkChanged, &media]( libvlc_meta_t meta ) {
            if ( meta != libvlc_meta_ArtworkURL
                 || metaArtworkChanged == true
                 || utils::file::schemeIs( "attachment", media.meta( libvlc_meta_ArtworkURL ) ) == true )
                return;
            std::lock_guard<compat::Mutex> lock( mutex );
            metaArtworkChanged = true;
            cond.notify_all();
        });
    }

    std::unique_lock<compat::Mutex> lock( mutex );
    mp.play();
    success = cond.wait_for( lock, std::chrono::seconds( 3 ), [&failedToStart, &hasAnyTrack]() {
        return failedToStart == true || hasAnyTrack == true;
    });

    // In case the playback failed, we probably won't fetch anything interesting anyway.
    if ( failedToStart == true || success == false )
        return false;

    // If we have any kind of track, but not a video track, we don't have to wait long, tracks are usually
    // being discovered together.
    if ( hasVideoTrack == false )
    {
        if ( watchForArtworkChange == true )
        {
            cond.wait_for( lock, std::chrono::milliseconds( 500 ), [&metaArtworkChanged]() {
                return metaArtworkChanged == true;
            });
        }
        else
        {
            cond.wait_for( lock, std::chrono::seconds( 1 ), [&hasVideoTrack]() {
                return hasVideoTrack == true;
            });
        }
    }

    return true;
}

}
<commit_msg>metadata: vlc common: Fix potential lock inversion<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015-2019 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifndef HAVE_LIBVLC
# error This file requires libvlc
#endif

#include "Common.hpp"
#include "Media.h"
#include "utils/Filename.h"
namespace medialibrary
{

bool medialibrary::MetadataCommon::startPlayback( VLC::Media& media,
                                                  VLC::MediaPlayer& mp,
                                                  compat::Mutex& mutex,
                                                  compat::ConditionVariable& cond )
{
    bool hasVideoTrack = false;
    bool failedToStart = false;
    bool hasAnyTrack = false;
    bool success = false;
    // Use a copy of the event manager to automatically unregister all events as soon
    // as we leave this method.
    auto em = mp.eventManager();

    em.onESAdded([&mutex, &cond, &hasVideoTrack, &hasAnyTrack]( libvlc_track_type_t type, int ) {
        std::lock_guard<compat::Mutex> lock( mutex );
        if ( type == libvlc_track_video )
            hasVideoTrack = true;
        hasAnyTrack = true;
        cond.notify_all();
    });
    em.onEncounteredError([&mutex, &cond, &failedToStart]() {
        std::lock_guard<compat::Mutex> lock( mutex );
        failedToStart = true;
        cond.notify_all();
    });

    bool metaArtworkChanged = false;
    bool watchForArtworkChange = false;
    auto mem = media.eventManager();
    if ( utils::file::schemeIs( "attachment", media.meta( libvlc_meta_ArtworkURL ) ) == true )
    {
        watchForArtworkChange = true;
        mem.onMetaChanged([&mutex, &cond, &metaArtworkChanged, &media]( libvlc_meta_t meta ) {
            if ( meta != libvlc_meta_ArtworkURL
                 || metaArtworkChanged == true
                 || utils::file::schemeIs( "attachment", media.meta( libvlc_meta_ArtworkURL ) ) == true )
                return;
            std::lock_guard<compat::Mutex> lock( mutex );
            metaArtworkChanged = true;
            cond.notify_all();
        });
    }

    mp.play();
    std::unique_lock<compat::Mutex> lock( mutex );
    success = cond.wait_for( lock, std::chrono::seconds( 3 ), [&failedToStart, &hasAnyTrack]() {
        return failedToStart == true || hasAnyTrack == true;
    });

    // In case the playback failed, we probably won't fetch anything interesting anyway.
    if ( failedToStart == true || success == false )
        return false;

    // If we have any kind of track, but not a video track, we don't have to wait long, tracks are usually
    // being discovered together.
    if ( hasVideoTrack == false )
    {
        if ( watchForArtworkChange == true )
        {
            cond.wait_for( lock, std::chrono::milliseconds( 500 ), [&metaArtworkChanged]() {
                return metaArtworkChanged == true;
            });
        }
        else
        {
            cond.wait_for( lock, std::chrono::seconds( 1 ), [&hasVideoTrack]() {
                return hasVideoTrack == true;
            });
        }
    }

    return true;
}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Kamil Michalak <kmichalak8@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "inc/getissueaction.hpp"
#include "inc/config.hpp"
#include "inc/restclient.hpp"

using namespace jippi;

GetIssueAction::GetIssueAction()
{

}

GetIssueAction::~GetIssueAction()
{

}

void GetIssueAction::perform()
{
	Config *configuration = new Config(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCATION);
	configuration->readConfigurationFromFile();
	const std::string jiraUrl = configuration->getProperty(JIRA_GROUP, JIRA_URL);
	delete configuration;

	RestClient *restClient = new RestClient();
	rest_response response = restClient->doHttpPut(jiraUrl, "", "");
	delete restClient;
	std::cout << response.code << " : " << response.body << std::endl;

}

<commit_msg>Specify content type for the getIssue action request<commit_after>/*
 * Copyright 2014 Kamil Michalak <kmichalak8@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "inc/getissueaction.hpp"
#include "inc/config.hpp"
#include "inc/restclient.hpp"

using namespace jippi;

GetIssueAction::GetIssueAction()
{

}

GetIssueAction::~GetIssueAction()
{

}

void GetIssueAction::perform()
{
	Config *configuration = new Config(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_LOCATION);
	configuration->readConfigurationFromFile();
	const std::string jiraUrl = configuration->getProperty(JIRA_GROUP, JIRA_URL) + "/search";
	delete configuration;

	RestClient *restClient = new RestClient();
	rest_response response = restClient->doHttpPut(jiraUrl, "application/json", "");
	delete restClient;
	std::cout << response.code << " : " << response.body << std::endl;

}

<|endoftext|>


<commit_before><commit_msg>Allow link drags from the bookmark manager out to the Gnome desktop (nautilus).  This should create a shortcut to the site rather than downloading the file to the desktop.<commit_after><|endoftext|>


<commit_before><commit_msg>Initialize dragged tab backing store to null.<commit_after><|endoftext|>


<commit_before><commit_msg>Changed default notification method to 'transitional'.<commit_after><|endoftext|>


<commit_before><commit_msg>forgot this file<commit_after><|endoftext|>


<commit_before><commit_msg>Change NOTREACHED() to LOG(ERROR) when we cannot initialize the web database.  This is not a programming error.  This can happen if we run an old version of Chrome with a new version of user data directory.<commit_after><|endoftext|>


<commit_before>#include "stdafx.h"
#include "SkeletonBasics.h"

void CSkeletonBasics::delimited_output(std::string delimiter, std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".txt";
	CSkeletonBasics::fout.open(outputFile);
	//End elaborate date and time filename setup

	fout << "HIP_CENTER" << ',' << ',' << ',';
	fout << "SPINE" << ',' << ',' << ',';
	fout << "SHOULDER_CENTER" << ',' << ',' << ',';
	fout << "HEAD" << ',' << ',' << ',';
	fout << "SHOULDER_LEFT" << ',' << ',' << ',';
	fout << "ELBOW_LEFT" << ',' << ',' << ',';
	fout << "WRIST_LEFT" << ',' << ',' << ',';
	fout << "HAND_LEFT" << ',' << ',' << ',';
	fout << "SHOULDER_RIGHT" << ',' << ',' << ',';
	fout << "ELBOW_RIGHT" << ',' << ',' << ',';
	fout << "WRIST_RIGHT" << ',' << ',' << ',';
	fout << "HAND_RIGHT" << ',' << ',' << ',';
	fout << "HIP_LEFT" << ',' << ',' << ',';
	fout << "KNEE_LEFT" << ',' << ',' << ',';
	fout << "ANKLE_LEFT" << ',' << ',' << ',';
	fout << "FOOT_LEFT" << ',' << ',' << ',';
	fout << "HIP_RIGHT" << ',' << ',' << ',';
	fout << "KNEE_RIGHT" << ',' << ',' << ',';
	fout << "ANKLE_RIGHT" << ',' << ',' << ',';
	fout << "FOOT_RIGHT" << ',' << ',' << ',';

	fout << "NECK_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "TORSO_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';

	fout << "NECK_ENERGY" << ',' << ',' << ',';
	fout << "TORSO_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "COMBINED_ENERGY" << ',';
	fout << "TOTAL_ENERGY" << ',';

	fout << std::endl;

	for (int p = 0; p < 39; p++){
		fout << 'x' << ',' << 'y' << ',' << 'z' << ',';
	}

	fout << std::endl;

	fout.close();
}

void CSkeletonBasics::COM_output(std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".csv";
	fout.open(outputFile);

	fout << "HIP_CENTER" << ',' << ',' << ',';
	fout << "SPINE" << ',' << ',' << ',';
	fout << "SHOULDER_CENTER" << ',' << ',' << ',';
	fout << "HEAD" << ',' << ',' << ',';
	fout << "SHOULDER_LEFT" << ',' << ',' << ',';
	fout << "ELBOW_LEFT" << ',' << ',' << ',';
	fout << "WRIST_LEFT" << ',' << ',' << ',';
	fout << "HAND_LEFT" << ',' << ',' << ',';
	fout << "SHOULDER_RIGHT" << ',' << ',' << ',';
	fout << "ELBOW_RIGHT" << ',' << ',' << ',';
	fout << "WRIST_RIGHT" << ',' << ',' << ',';
	fout << "HAND_RIGHT" << ',' << ',' << ',';
	fout << "HIP_LEFT" << ',' << ',' << ',';
	fout << "KNEE_LEFT" << ',' << ',' << ',';
	fout << "ANKLE_LEFT" << ',' << ',' << ',';
	fout << "FOOT_LEFT" << ',' << ',' << ',';
	fout << "HIP_RIGHT" << ',' << ',' << ',';
	fout << "KNEE_RIGHT" << ',' << ',' << ',';
	fout << "ANKLE_RIGHT" << ',' << ',' << ',';
	fout << "FOOT_RIGHT" << ',' << ',' << ',';

	fout << "NECK CoM" << ',' << ',' << ',';
	fout << "TORSO_CoM" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_CoM" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_CoM" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_CoM" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_CoM" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_CoM" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_CoM" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_CoM" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_CoM" << ',' << ',' << ',';

	fout << std::endl;
	for (int a = 0; a < 30; a++){
		fout << 'x' << ',' << 'y' << ',' << 'z' << ',';
	}

	fout << "Neck" << ',';
	fout << "Torso" << ',';
	fout << "Right_Upper_Arm" << ',';
	fout << "Right_Lower_Arm" << ',';
	fout << "Left_Upper_Arm" << ',';
	fout << "Left_Lower_Arm" << ',';
	fout << "Right_Upper_Leg" << ',';
	fout << "Right_Lower_Leg" << ',';
	fout << "Left_Upper_Leg" << ',';
	fout << "Left_Lower_Leg" << ',';

	fout << "Energy Expended This Frame" << ',';
	fout << "Total Energy Expended" << ',';

	fout << std::endl;

	for (int i = 0; i < coords.size() - 1; i++){

		distanceDeviationCheck(i);

		for (int j = 0; j < coords[j].size() - 1; j++){
			fout << coords[i][j].x << ',';
			fout << coords[i][j].y << ',';
			fout << coords[i][j].z << ',';
		}

		fout << COMSES[i].NECK.x << ',';
		fout << COMSES[i].NECK.y << ',';
		fout << COMSES[i].NECK.z << ',';

		fout << COMSES[i].TORSO.x << ',';
		fout << COMSES[i].TORSO.y << ',';
		fout << COMSES[i].TORSO.z << ',';

		fout << COMSES[i].RIGHT_UPPER_ARM.x << ',';
		fout << COMSES[i].RIGHT_UPPER_ARM.y << ',';
		fout << COMSES[i].RIGHT_UPPER_ARM.z << ',';

		fout << COMSES[i].RIGHT_LOWER_ARM.x << ',';
		fout << COMSES[i].RIGHT_LOWER_ARM.y << ',';
		fout << COMSES[i].RIGHT_LOWER_ARM.z << ',';

		fout << COMSES[i].LEFT_UPPER_ARM.x << ',';
		fout << COMSES[i].LEFT_UPPER_ARM.y << ',';
		fout << COMSES[i].LEFT_UPPER_ARM.z << ',';

		fout << COMSES[i].LEFT_LOWER_ARM.x << ',';
		fout << COMSES[i].LEFT_LOWER_ARM.y << ',';
		fout << COMSES[i].LEFT_LOWER_ARM.z << ',';

		fout << COMSES[i].RIGHT_UPPER_LEG.x << ',';
		fout << COMSES[i].RIGHT_UPPER_LEG.y << ',';
		fout << COMSES[i].RIGHT_UPPER_LEG.z << ',';

		fout << COMSES[i].RIGHT_LOWER_LEG.x << ',';
		fout << COMSES[i].RIGHT_LOWER_LEG.y << ',';
		fout << COMSES[i].RIGHT_LOWER_LEG.z << ',';

		fout << COMSES[i].LEFT_UPPER_LEG.x << ',';
		fout << COMSES[i].LEFT_UPPER_LEG.y << ',';
		fout << COMSES[i].LEFT_UPPER_LEG.z << ',';

		fout << COMSES[i].LEFT_LOWER_LEG.x << ',';
		fout << COMSES[i].LEFT_LOWER_LEG.y << ',';
		fout << COMSES[i].LEFT_LOWER_LEG.z << ',';

		fout << energyskels[i].NECK_ENERGY << ',';
		fout << energyskels[i].TORSO_ENERGY << ',';
		fout << energyskels[i].RIGHT_UPPER_ARM_ENERGY << ',';
		fout << energyskels[i].RIGHT_LOWER_ARM_ENERGY << ',';
		fout << energyskels[i].LEFT_UPPER_ARM_ENERGY << ',';
		fout << energyskels[i].LEFT_LOWER_ARM_ENERGY << ',';
		fout << energyskels[i].RIGHT_UPPER_LEG_ENERGY << ',';
		fout << energyskels[i].RIGHT_LOWER_LEG_ENERGY << ',';
		fout << energyskels[i].LEFT_UPPER_LEG_ENERGY << ',';
		fout << energyskels[i].LEFT_LOWER_LEG_ENERGY << ',';

		fout << Energy(energyskels[i]) << ',';
		fout << currentTotalEnergyExpended[i] << ',';

		fout << std::endl;
	}

	fout << std::endl;
}

void CSkeletonBasics::playback_output(std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".txt";
	CSkeletonBasics::fout.open(outputFile);
	for (int i = 0; i < coords.size(); i++){
		for (int j = 0; j < coords[i].size(); j++){
			fout << coords[i][j].x << std::endl;
			fout << coords[i][j].y << std::endl;
			fout << coords[i][j].z << std::endl;
		}
	}
}
<commit_msg>Update output.cpp<commit_after>#include "stdafx.h"
#include "SkeletonBasics.h"

void CSkeletonBasics::delimited_output(std::string delimiter, std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".txt";
	CSkeletonBasics::fout.open(outputFile);
	//End elaborate date and time filename setup

	fout << "HIP_CENTER" << ',' << ',' << ',';
	fout << "SPINE" << ',' << ',' << ',';
	fout << "SHOULDER_CENTER" << ',' << ',' << ',';
	fout << "HEAD" << ',' << ',' << ',';
	fout << "SHOULDER_LEFT" << ',' << ',' << ',';
	fout << "ELBOW_LEFT" << ',' << ',' << ',';
	fout << "WRIST_LEFT" << ',' << ',' << ',';
	fout << "HAND_LEFT" << ',' << ',' << ',';
	fout << "SHOULDER_RIGHT" << ',' << ',' << ',';
	fout << "ELBOW_RIGHT" << ',' << ',' << ',';
	fout << "WRIST_RIGHT" << ',' << ',' << ',';
	fout << "HAND_RIGHT" << ',' << ',' << ',';
	fout << "HIP_LEFT" << ',' << ',' << ',';
	fout << "KNEE_LEFT" << ',' << ',' << ',';
	fout << "ANKLE_LEFT" << ',' << ',' << ',';
	fout << "FOOT_LEFT" << ',' << ',' << ',';
	fout << "HIP_RIGHT" << ',' << ',' << ',';
	fout << "KNEE_RIGHT" << ',' << ',' << ',';
	fout << "ANKLE_RIGHT" << ',' << ',' << ',';
	fout << "FOOT_RIGHT" << ',' << ',' << ',';

	fout << "NECK_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "TORSO_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_CENTER_OF_MASS" << ',' << ',' << ',';

	fout << "NECK_ENERGY" << ',' << ',' << ',';
	fout << "TORSO_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_ENERGY" << ',' << ',' << ',';
	fout << "COMBINED_ENERGY" << ',';
	fout << "TOTAL_ENERGY" << ',';

	fout << std::endl;

	for (int p = 0; p < 39; p++){
		fout << 'x' << ',' << 'y' << ',' << 'z' << ',';
	}

	fout << std::endl;

	fout.close();
}

void CSkeletonBasics::COM_output(std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".csv";
	fout.open(outputFile);

	fout << "HIP_CENTER" << ',' << ',' << ',';
	fout << "SPINE" << ',' << ',' << ',';
	fout << "SHOULDER_CENTER" << ',' << ',' << ',';
	fout << "HEAD" << ',' << ',' << ',';
	fout << "SHOULDER_LEFT" << ',' << ',' << ',';
	fout << "ELBOW_LEFT" << ',' << ',' << ',';
	fout << "WRIST_LEFT" << ',' << ',' << ',';
	fout << "HAND_LEFT" << ',' << ',' << ',';
	fout << "SHOULDER_RIGHT" << ',' << ',' << ',';
	fout << "ELBOW_RIGHT" << ',' << ',' << ',';
	fout << "WRIST_RIGHT" << ',' << ',' << ',';
	fout << "HAND_RIGHT" << ',' << ',' << ',';
	fout << "HIP_LEFT" << ',' << ',' << ',';
	fout << "KNEE_LEFT" << ',' << ',' << ',';
	fout << "ANKLE_LEFT" << ',' << ',' << ',';
	fout << "FOOT_LEFT" << ',' << ',' << ',';
	fout << "HIP_RIGHT" << ',' << ',' << ',';
	fout << "KNEE_RIGHT" << ',' << ',' << ',';
	fout << "ANKLE_RIGHT" << ',' << ',' << ',';
	fout << "FOOT_RIGHT" << ',' << ',' << ',';

	fout << "NECK CoM" << ',' << ',' << ',';
	fout << "TORSO_CoM" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_ARM_CoM" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_ARM_CoM" << ',' << ',' << ',';
	fout << "LEFT_UPPER_ARM_CoM" << ',' << ',' << ',';
	fout << "LEFT_LOWER_ARM_CoM" << ',' << ',' << ',';
	fout << "RIGHT_UPPER_LEG_CoM" << ',' << ',' << ',';
	fout << "RIGHT_LOWER_LEG_CoM" << ',' << ',' << ',';
	fout << "LEFT_UPPER_LEG_CoM" << ',' << ',' << ',';
	fout << "LEFT_LOWER_LEG_CoM" << ',' << ',' << ',';

	fout << std::endl;
	for (int a = 0; a < 30; a++){
		fout << 'x' << ',' << 'y' << ',' << 'z' << ',';
	}

	fout << "Neck" << ',';
	fout << "Torso" << ',';
	fout << "Right_Upper_Arm" << ',';
	fout << "Right_Lower_Arm" << ',';
	fout << "Left_Upper_Arm" << ',';
	fout << "Left_Lower_Arm" << ',';
	fout << "Right_Upper_Leg" << ',';
	fout << "Right_Lower_Leg" << ',';
	fout << "Left_Upper_Leg" << ',';
	fout << "Left_Lower_Leg" << ',';

	fout << "Energy Expended This Frame" << ',';
	fout << "Total Energy Expended" << ',';

	fout << std::endl;

	for (int i = 0; i < coords.size(); i++){

		distanceDeviationCheck(i);

		for (int j = 0; j < coords[j].size(); j++){
			fout << coords[i][j].x << ',';
			fout << coords[i][j].y << ',';
			fout << coords[i][j].z << ',';
		}

		fout << COMSES[i].NECK.x << ',';
		fout << COMSES[i].NECK.y << ',';
		fout << COMSES[i].NECK.z << ',';

		fout << COMSES[i].TORSO.x << ',';
		fout << COMSES[i].TORSO.y << ',';
		fout << COMSES[i].TORSO.z << ',';

		fout << COMSES[i].RIGHT_UPPER_ARM.x << ',';
		fout << COMSES[i].RIGHT_UPPER_ARM.y << ',';
		fout << COMSES[i].RIGHT_UPPER_ARM.z << ',';

		fout << COMSES[i].RIGHT_LOWER_ARM.x << ',';
		fout << COMSES[i].RIGHT_LOWER_ARM.y << ',';
		fout << COMSES[i].RIGHT_LOWER_ARM.z << ',';

		fout << COMSES[i].LEFT_UPPER_ARM.x << ',';
		fout << COMSES[i].LEFT_UPPER_ARM.y << ',';
		fout << COMSES[i].LEFT_UPPER_ARM.z << ',';

		fout << COMSES[i].LEFT_LOWER_ARM.x << ',';
		fout << COMSES[i].LEFT_LOWER_ARM.y << ',';
		fout << COMSES[i].LEFT_LOWER_ARM.z << ',';

		fout << COMSES[i].RIGHT_UPPER_LEG.x << ',';
		fout << COMSES[i].RIGHT_UPPER_LEG.y << ',';
		fout << COMSES[i].RIGHT_UPPER_LEG.z << ',';

		fout << COMSES[i].RIGHT_LOWER_LEG.x << ',';
		fout << COMSES[i].RIGHT_LOWER_LEG.y << ',';
		fout << COMSES[i].RIGHT_LOWER_LEG.z << ',';

		fout << COMSES[i].LEFT_UPPER_LEG.x << ',';
		fout << COMSES[i].LEFT_UPPER_LEG.y << ',';
		fout << COMSES[i].LEFT_UPPER_LEG.z << ',';

		fout << COMSES[i].LEFT_LOWER_LEG.x << ',';
		fout << COMSES[i].LEFT_LOWER_LEG.y << ',';
		fout << COMSES[i].LEFT_LOWER_LEG.z << ',';

		fout << energyskels[i].NECK_ENERGY << ',';
		fout << energyskels[i].TORSO_ENERGY << ',';
		fout << energyskels[i].RIGHT_UPPER_ARM_ENERGY << ',';
		fout << energyskels[i].RIGHT_LOWER_ARM_ENERGY << ',';
		fout << energyskels[i].LEFT_UPPER_ARM_ENERGY << ',';
		fout << energyskels[i].LEFT_LOWER_ARM_ENERGY << ',';
		fout << energyskels[i].RIGHT_UPPER_LEG_ENERGY << ',';
		fout << energyskels[i].RIGHT_LOWER_LEG_ENERGY << ',';
		fout << energyskels[i].LEFT_UPPER_LEG_ENERGY << ',';
		fout << energyskels[i].LEFT_LOWER_LEG_ENERGY << ',';

		fout << Energy(energyskels[i]) << ',';
		fout << currentTotalEnergyExpended[i] << ',';

		fout << std::endl;
	}

	fout << std::endl;
}

void CSkeletonBasics::playback_output(std::string filename){
	std::string outputFile;
	time_t currenttime = time(NULL);
	char* timestring = ctime(&currenttime);
	outputFile = filename;
	std::string conv(timestring);
	conv = conv.substr(0, conv.length() - 1);

	for (int i = 0; i < conv.length(); i++){
		if (conv[i] == ':' || conv[i] == ' '){
			conv[i] = '_';
		}
	}

	outputFile += conv;

	outputFile += ".txt";
	CSkeletonBasics::fout.open(outputFile);
	for (int i = 0; i < coords.size(); i++){
		for (int j = 0; j < coords[i].size(); j++){
			fout << coords[i][j].x << std::endl;
			fout << coords[i][j].y << std::endl;
			fout << coords[i][j].z << std::endl;
		}
	}
}
<|endoftext|>


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

#include "AllEvents.h"
#include "ui_AllEvents.h"

#include "../Selectors/SelectInstrument.h"

#include <QInputDialog>
#include <QProgressDialog>
#include <QMessageBox>

void GuiMidiEvent::init(QtMidiEvent *e, SelectInstrument* ins)
{
    setText(0,QString::number(e->tick())); // Tick
    setText(1,QString::number(e->voice())); // Voice
    setText(2,QString::number(e->note())); // Note
    setText(3,QString::number(e->velocity())); // Velocity

    switch(e->type()) {
    case QtMidiEvent::NoteOn:
        setText(4,QObject::tr("note on")); break;
    case QtMidiEvent::NoteOff:
        setText(4,QObject::tr("note off")); break;
    case QtMidiEvent::KeyPressure:
        setText(4,QObject::tr("key press.","key pressure")); break;
    case QtMidiEvent::ChannelPressure:
        setText(4,QObject::tr("chan. press.","channel pressure")); break;
    case QtMidiEvent::ControlChange:
        setText(4,QObject::tr("control")); break;
    case QtMidiEvent::ProgramChange:
        setText(4,QObject::tr("program")); break;
    case QtMidiEvent::PitchWheel:
        setText(4,QObject::tr("pitch wheel")); break;
    case QtMidiEvent::Meta:
        setText(4,QObject::tr("meta")); break;
    case QtMidiEvent::Meta_Lyric:
        setText(4,QObject::tr("meta/lyric")); break;
    case QtMidiEvent::Meta_Tempo:
        setText(4,QObject::tr("tempo")); break;
    case QtMidiEvent::Meta_TimeSignature:
        setText(4,QObject::tr("meta/time sig.","meta/time signature")); break;
    case QtMidiEvent::SysEx:
        setText(4,QObject::tr("sys. ex.","system exclusive")); break;
    default: break;
    }

    if(e->type() == QtMidiEvent::Meta_Tempo) {
        setText(5,QString::number(e->tempo()));
    } else if(e->type() == QtMidiEvent::ControlChange) {
        ins->setInsNum(e->number());
        setText(5,QString("%1 (%2)").arg(e->number()).arg(ins->insName()));
    } else {
        setText(5,QString::fromAscii(e->data()));
    }
}

bool GuiMidiEvent::operator<(const QTreeWidgetItem &other) const
{
    int column = treeWidget()->sortColumn();
    if(column != 0) { return QTreeWidgetItem::operator<(other); }
    return text(column).toInt() < other.text(column).toInt();
}

AllEvents::AllEvents(QWidget *parent, QtMidiFile* f) :
    QDialog(parent), ui(new Ui::AllEvents)
{
    ui->setupUi(this);
    if(!f) { return; }

    SelectInstrument ins;
    QList<QtMidiEvent*> events = f->events();

    QProgressDialog dialog(parent);
    dialog.show();
    dialog.setWindowTitle(tr("Loading..."));
    dialog.setLabelText(tr("Setting up \"All MIDI Events\" dialog..."));
    dialog.setMaximum(events.size());
    dialog.repaint();

    GuiMidiEvent* mI;
    for(int i = 0;i < events.size();i++) {
        dialog.setValue(i);
        mI = new GuiMidiEvent(ui->eventsList);
        mI->init(events.at(i),&ins);
    }

    ui->eventsList->setSortingEnabled(true);
    ui->eventsList->sortItems(0,Qt::AscendingOrder);
    minColSize();

    dialog.hide();
}

AllEvents::~AllEvents()
{
    delete ui;
}

void AllEvents::minColSize()
{
    for(int i = 0; i < ui->eventsList->columnCount(); i++)
    { ui->eventsList->resizeColumnToContents(i); }
}

void AllEvents::on_delCertEvBtn_clicked()
{
    QStringList items;
    items.append(tr("pitch wheel"));
    QString result = QInputDialog::getItem(this,tr("Delete certain events"),
                                           tr("Type of events to delete:"),
                                           items,0,false);
    int res = QMessageBox::warning(this,tr("Warning!"),
                                   tr("Are you SURE you want to delete these events?
This CANNOT be undone!"),
                                   QMessageBox::Ok,QMessageBox::Cancel);
    if(res == QMessageBox::Ok) {
        QMessageBox::information(this,"","TODO: actually DELETE events!!");
    }
}
<commit_msg>More work on all events dialog.<commit_after>/*
 * Raging MIDI (https://github.com/waddlesplash/ragingmidi).
 *
 * Copyright (c) 2012-2013 WaddleSplash & contributors (see AUTHORS.txt).
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall
 * be included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "AllEvents.h"
#include "ui_AllEvents.h"

#include "../Selectors/SelectInstrument.h"

#include <QInputDialog>
#include <QProgressDialog>
#include <QMessageBox>

void GuiMidiEvent::init(QtMidiEvent *e, SelectInstrument* ins)
{
    setText(0,QString::number(e->tick())); // Tick
    setText(1,QString::number(e->voice())); // Voice
    setText(2,QString::number(e->note())); // Note
    setText(3,QString::number(e->velocity())); // Velocity

    switch(e->type()) {
    case QtMidiEvent::NoteOn:
        setText(4,QObject::tr("note on")); break;
    case QtMidiEvent::NoteOff:
        setText(4,QObject::tr("note off")); break;
    case QtMidiEvent::KeyPressure:
        setText(4,QObject::tr("key press.","key pressure")); break;
    case QtMidiEvent::ChannelPressure:
        setText(4,QObject::tr("chan. press.","channel pressure")); break;
    case QtMidiEvent::ControlChange:
        setText(4,QObject::tr("control")); break;
    case QtMidiEvent::ProgramChange:
        setText(4,QObject::tr("program")); break;
    case QtMidiEvent::PitchWheel:
        setText(4,QObject::tr("pitch wheel")); break;
    case QtMidiEvent::Meta:
        setText(4,QObject::tr("meta")); break;
    case QtMidiEvent::Meta_Lyric:
        setText(4,QObject::tr("meta/lyric")); break;
    case QtMidiEvent::Meta_Tempo:
        setText(4,QObject::tr("tempo")); break;
    case QtMidiEvent::Meta_TimeSignature:
        setText(4,QObject::tr("meta/time sig.","meta/time signature")); break;
    case QtMidiEvent::SysEx:
        setText(4,QObject::tr("sys. ex.","system exclusive")); break;
    default: break;
    }

    if(e->type() == QtMidiEvent::Meta_Tempo) {
        setText(5,QString::number(e->tempo()));
    } else if(e->type() == QtMidiEvent::ControlChange) {
        ins->setInsNum(e->number());
        setText(5,QString("%1 (%2)").arg(e->number()).arg(ins->insName()));
    } else {
        setText(5,QString::fromAscii(e->data()));
    }
}

bool GuiMidiEvent::operator<(const QTreeWidgetItem &other) const
{
    int column = treeWidget()->sortColumn();
    if(column != 0) { return QTreeWidgetItem::operator<(other); }
    return text(column).toInt() < other.text(column).toInt();
}

AllEvents::AllEvents(QWidget *parent, QtMidiFile* f) :
    QDialog(parent), ui(new Ui::AllEvents)
{
    ui->setupUi(this);
    if(!f) { return; }

    SelectInstrument ins;
    QList<QtMidiEvent*> events = f->events();

    QProgressDialog dialog(parent);
    dialog.show();
    dialog.setWindowTitle(tr("Loading..."));
    dialog.setLabelText(tr("Creating list items..."));
    dialog.setMaximum(events.size());
    dialog.repaint();

    GuiMidiEvent* mI;
    for(int i = 0;i < events.size();i++) {
        if(i % 100) { dialog.setValue(i); }
        if(i % 1000) { QApplication::processEvents(); }
        mI = new GuiMidiEvent(ui->eventsList);
        mI->init(events.at(i),&ins);
    }

    dialog.setLabelText(tr("Sorting items..."));
    QApplication::processEvents();
    ui->eventsList->sortItems(0,Qt::AscendingOrder);
    ui->eventsList->setSortingEnabled(true);
    minColSize();

    dialog.hide();
}

AllEvents::~AllEvents()
{
    delete ui;
}

void AllEvents::minColSize()
{
    for(int i = 0; i < ui->eventsList->columnCount(); i++)
    { ui->eventsList->resizeColumnToContents(i); }
}

void AllEvents::on_delCertEvBtn_clicked()
{
    QStringList items;
    items.append(tr("pitch wheel"));
    QString result = QInputDialog::getItem(this,tr("Delete certain events"),
                                           tr("Type of events to delete:"),
                                           items,0,false);
    int res = QMessageBox::warning(this,tr("Warning!"),
                                   tr("Are you SURE you want to delete these events?
This CANNOT be undone!"),
                                   QMessageBox::Ok,QMessageBox::Cancel);
    if(res == QMessageBox::Ok) {
        QMessageBox::information(this,"","TODO: actually DELETE events!!");
    }
}
<|endoftext|>


<commit_before>#ifndef GPIO_HPP
#define GPIO_HPP

#include <cstdlib>
#include <vector>
#include <iostream>
#include <fstream>

#include <stdio.h>
#include <string.h>
#include <unistd.h>

class GPIO
{
public:
	/**
	 * PWM pins.
	 * Assigned int values are path indices in the _pwmPinPaths list.
	 */
	enum PwmPin {
		P8_13 = 0,
		P8_19 = 1,
		P9_14 = 2,
		P9_16 = 3
	};

	/**
	 * Plain GPIOs.
	 * Assigned int values are pin indices in sysfs.
	 */
	enum Pin {
		P8_10 = 68,
		P8_12 = 44,
		P8_15 = 47,
		P8_17 = 27,
		P9_17 = 4,
		P9_18 = 5,
		P9_21 = 3,
		P9_23 = 49,
		P9_24 = 15,
		P9_26 = 14,
		P9_41 = 20,
		P9_42 = 7
	};

	GPIO();
	~GPIO();

	/**
	 * @brief Sets a GPIO pin to the specified value.
	 *
	 * @param pin The GPIO to set.
	 * @param value Desired pin value.
	 */
	void setPin(const Pin pin, const bool value);

	/**
	 * @brief Sets a PWM pin's duty cycle.
	 *
	 * @param pin The PWM pin to set.
	 * @param duty Duty cycle percentage, 0 < duty < 1.
	 */
	void setPwm(const PwmPin pin, const float duty);

private:
	bool containsPin(const Pin pin);
	void exportPin(const Pin pin);
	int echo(const std::string target, const int value);
	int echo(const std::string target, const char *value);
	std::string matchPath(std::string pattern);
	inline std::string append(const std::string base, const std::string suffix)
	{
		std::string tmp(base);
		tmp.append(suffix);
		return tmp;
	}

	const unsigned int PWM_PERIOD;
	std::vector<int> _exportedPins;
	std::vector<std::string> _pwmPinPaths;
};

#endif
<commit_msg>pin changes for new mainboard<commit_after>#ifndef GPIO_HPP
#define GPIO_HPP

#include <cstdlib>
#include <vector>
#include <iostream>
#include <fstream>

#include <stdio.h>
#include <string.h>
#include <unistd.h>

class GPIO
{
public:
	/**
	 * PWM pins.
	 * Assigned int values are path indices in the _pwmPinPaths list.
	 */
	enum PwmPin {
		P8_13 = 0,
		P8_19 = 1,
		P9_14 = 2,
		P9_16 = 3
	};

	/**
	 * Plain GPIOs.
	 * Assigned int values are pin indices in sysfs.
	 */
	enum Pin {
		P8_10 = 68,
		P8_12 = 44,
		P8_15 = 47,
		P8_17 = 27,
		P9_17 = 4,
		P9_18 = 5,
		P9_21 = 3,
		P9_23 = 49,
		P9_24 = 15,
		P9_26 = 14,
		P9_31 = 120,
		P9_41 = 20,
		P9_42 = 7
	};

	GPIO();
	~GPIO();

	/**
	 * @brief Sets a GPIO pin to the specified value.
	 *
	 * @param pin The GPIO to set.
	 * @param value Desired pin value.
	 */
	void setPin(const Pin pin, const bool value);

	/**
	 * @brief Sets a PWM pin's duty cycle.
	 *
	 * @param pin The PWM pin to set.
	 * @param duty Duty cycle percentage, 0 < duty < 1.
	 */
	void setPwm(const PwmPin pin, const float duty);

private:
	bool containsPin(const Pin pin);
	void exportPin(const Pin pin);
	int echo(const std::string target, const int value);
	int echo(const std::string target, const char *value);
	std::string matchPath(std::string pattern);
	inline std::string append(const std::string base, const std::string suffix)
	{
		std::string tmp(base);
		tmp.append(suffix);
		return tmp;
	}

	const unsigned int PWM_PERIOD;
	std::vector<int> _exportedPins;
	std::vector<std::string> _pwmPinPaths;
};

#endif
<|endoftext|>


<commit_before>#include <math.h>
#include <memory.h>
#include <random>
#include <stdlib.h>

#include "Neural_Networks.h"

Connection::Connection(Layer *layer, Layer *parent_layer, double scale) {
	this->layer = layer;
	this->parent_layer = parent_layer;
	this->number_weights = layer->number_nodes * parent_layer->number_nodes;

	weight = new float[number_weights];

	for (int i = 0; i < number_weights; i++) {
		weight[i] = scale * (2.0 * rand() / RAND_MAX - 1);
	}
}
Connection::~Connection() {
	delete[] weight;
}

Layer::Layer(int number_nodes, int activation) {
	this->activation = activation;
	this->batch_size = 1;
	this->number_nodes = number_nodes;

	memset(bias = new float[number_nodes], 0, sizeof(float) * number_nodes);
	error = new float[number_nodes];
	neuron = new float[number_nodes];
}
Layer::~Layer() {
	for (int i = 0; i < connection.size(); i++) {
		delete connection[i];
	}
	delete[] bias;
	delete[] error;
	delete[] neuron;
}

void Layer::Activation() {
	for (int h = 0; h < batch_size; h++) {
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			neuron[j] += bias[j];
		}

		if (activation == Activation::softmax) {
			double max;
			double sum = 0;

			for (int j = 0; j < number_nodes; j++) {
				if (j == 0 || max < neuron[j]) {
					max = neuron[j];
				}
			}
			for (int j = 0; j < number_nodes; j++) {
				sum += (neuron[j] = exp(neuron[j] - max));
			}
			for (int j = 0; j < number_nodes; j++) {
				neuron[j] /= sum;
			}
		}
		else {
			if (activation == Activation::linear) {
				// neuron[j] = neuron[j];
			}
			else if (activation == Activation::sigmoid) {
				for (int j = 0; j < number_nodes; j++) {
					neuron[j] = 1 / (1 + exp(-neuron[j]));
				}
			}
		}
	}
}
void Layer::Backward() {
	for (int h = 0; h < batch_size; h++) {
		float *error = &this->error[h * number_nodes];
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			for (int k = 0; k < connection.size(); k++) {
				Connection *connection = this->connection[k];

				Layer *parent_layer = connection->parent_layer;

				float *next_error = &parent_layer->error[h * parent_layer->number_nodes];
				float *weight = &connection->weight[j * parent_layer->number_nodes];

				for (int l = 0; l < parent_layer->number_nodes; l++) {
					next_error[l] += error[j] * weight[l];
				}
			}
		}
	}
}
void Layer::Derivative(int loss, float **y_batch) {
	if (y_batch) {
		for (int h = 0; h < batch_size; h++) {
			float *error = &this->error[h * number_nodes];
			float *neuron = &this->neuron[h * number_nodes];

			if (loss == Loss::cross_entropy) {
				if (activation == Activation::sigmoid) {
					for (int j = 0; j < number_nodes; j++) {
						error[j] = (neuron[j] - y_batch[h][j]) / (number_nodes * batch_size);
					}
				}
				else if (activation == Activation::softmax) {
					for (int j = 0; j < number_nodes; j++) {
						error[j] = (neuron[j] - y_batch[h][j]) / batch_size;
					}
				}
			}
			else if (loss == Loss::mean_squared_error) {
				for (int j = 0; j < number_nodes; j++) {
					error[j] = 2 * (neuron[j] - y_batch[h][j]) / (number_nodes * batch_size);
				}
			}
		}
		Derivative(loss);
	}
	else {
		for (int h = 0; h < batch_size; h++) {
			float *error = &this->error[h * number_nodes];
			float *neuron = &this->neuron[h * number_nodes];

			if (activation == Activation::linear) {
				// error[j] *= 1;
			}
			else if (activation == Activation::sigmoid && loss != Loss::cross_entropy){
				for (int j = 0; j < number_nodes; j++) {
					error[j] *= (1 - neuron[j]) * neuron[j];
				}
			}
		}
	}
}
void Layer::Forward() {
	for (int h = 0; h < batch_size; h++) {
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			double sum = 0;

			for (int k = 0; k < connection.size(); k++) {
				Connection *connection = this->connection[k];

				Layer *parent_layer = connection->parent_layer;

				float *prev_neuron = &parent_layer->neuron[h * parent_layer->number_nodes];
				float *weight = &connection->weight[j * parent_layer->number_nodes];

				for (int l = 0; l < parent_layer->number_nodes; l++) {
					sum += prev_neuron[l] * weight[l];
				}
			}
			neuron[j] = sum;
		}
	}
}
void Layer::Resize_Memory(int batch_size) {
	this->batch_size = batch_size;

	error = (float*)realloc(error, sizeof(float) * batch_size * number_nodes);
	neuron = (float*)realloc(neuron, sizeof(float) * batch_size * number_nodes);
}

void Neural_Networks::Resize_Memory(int batch_size) {
	if (this->batch_size != batch_size) {
		for (int i = 0; i < layer.size(); i++) {
			layer[i]->Resize_Memory(batch_size);
		}
		this->batch_size = batch_size;
	}
}

double Neural_Networks::Calculate_Loss(Layer *layer, float **y_batch) {
	double sum = 0;

	for (int h = 0; h < batch_size; h++) {
		float *neuron = &layer->neuron[h * layer->number_nodes];

		if (loss == Loss::cross_entropy) {
			if (layer->activation == Activation::sigmoid) {
				for (int j = 0; j < layer->number_nodes; j++) {
					sum -= (y_batch[h][j] * log(static_cast<double>(neuron[j])) + (1 - y_batch[h][j]) * log(1.0 - neuron[j])) / layer->number_nodes;
				}
			}
			else if (layer->activation == Activation::softmax) {
				for (int j = 0; j < layer->number_nodes; j++) {
					sum -= y_batch[h][j] * log(static_cast<double>(neuron[j]));
				}
			}
		}
		else if (loss == Loss::mean_squared_error) {
			for (int j = 0; j < layer->number_nodes; j++) {
				sum += (neuron[j] - y_batch[h][j]) * (neuron[j] - y_batch[h][j]) / layer->number_nodes;
			}
		}
	}
	return sum;
}

Neural_Networks::Neural_Networks() {
	batch_size = 1;
}
Neural_Networks::~Neural_Networks() {
	for (int i = 0; i < layer.size(); i++) {
		delete layer[i];
	}
}

void Neural_Networks::Add(int number_nodes, int activation) {
	this->layer.push_back(new Layer(number_nodes, activation));
}
void Neural_Networks::Compile(int loss, double learning_rate) {
	this->loss = loss;
	this->learning_rate = learning_rate;
}
void Neural_Networks::Connect(int from, int to, double scale) {
	Connection *connection = new Connection(layer[from], layer[to], scale);

	this->connection.push_back(connection);
	layer[from]->connection.push_back(connection);
}
void Neural_Networks::Predict(float input[], float output[]) {
	Predict(&input, &output);
}
void Neural_Networks::Predict(float **input, float **output, int batch_size) {
	Resize_Memory(batch_size);

	for (int h = 0, i = 0; h < batch_size; h++) {
		memcpy(&layer[i]->neuron[h * layer[i]->number_nodes], input[h], sizeof(float) * layer[i]->number_nodes);
	}
	for (int i = 1; i < layer.size(); i++) {
		layer[i]->Forward();
		layer[i]->Activation();
	}
	for (int h = 0, i = layer.size() - 1; h < batch_size; h++) {
		memcpy(output[h], &layer[i]->neuron[h * layer[i]->number_nodes], sizeof(float) * layer[i]->number_nodes);
	}
}

double Neural_Networks::Evaluate(float **x_test, float **y_test, int test_size, int batch_size) {
	float **x_batch = new float*[batch_size];
	float **y_batch = new float*[batch_size];

	double loss = 0;

	for (int g = 0, h = 0; g < test_size; g++) {
		x_batch[h] = x_test[g];
		y_batch[h] = y_test[g];

		if (++h == batch_size || g == test_size - 1) {
			Resize_Memory(h);

			// copy x_test to neuron
			while (--h >= 0) {
				memcpy(&layer[0]->neuron[h * layer[0]->number_nodes], x_batch[h], sizeof(float) * layer[0]->number_nodes);
			}
			h = 0;

			// forward propagation
			for (int i = 1; i < layer.size(); i++) {
				layer[i]->Forward();
				layer[i]->Activation();
			}

			// calculate loss
			loss += Calculate_Loss(layer.back(), y_batch);
		}
	}
	delete[] x_batch;
	delete[] y_batch;

	return loss / test_size;
}
double Neural_Networks::Fit(float **x_train, float **y_train, int train_size, int batch_size) {
	float **x_batch = new float*[batch_size];
	float **y_batch = new float*[batch_size];

	double loss = 0;

	for (int g = 0, h = 0; g < train_size; g++) {
		x_batch[h] = x_train[g];
		y_batch[h] = y_train[g];

		if (++h == batch_size || g == train_size - 1) {
			Resize_Memory(h);

			// copy x_train to neuron
			while (--h >= 0) {
				memcpy(&layer[0]->neuron[h * layer[0]->number_nodes], x_batch[h], sizeof(float) * layer[0]->number_nodes);
			}
			h = 0;

			// initialize error to zero
			for (int i = 0; i < layer.size(); i++) {
				memset(layer[i]->error, 0, sizeof(float) * this->batch_size * layer[i]->number_nodes);
			}

			// forward propagation
			for (int i = 1; i < layer.size(); i++) {
				layer[i]->Forward();
				layer[i]->Activation();
			}

			// calculate loss
			loss += Calculate_Loss(layer.back(), y_batch);

			// calculate error
			layer.back()->Derivative(this->loss, y_batch);

			// error backpropagation
			layer.back()->Backward();

			for (int i = layer.size() - 2; i > 0; i--) {
				layer[i]->Derivative();
				layer[i]->Backward();
			}

			// adjust bias
			for (int i = 0; i < layer.size(); i++) {
				Layer *layer = this->layer[i];

				for (int j = 0; j < layer->number_nodes; j++) {
					double sum = 0;

					for (int h = 0; h < this->batch_size; h++) {
						sum += layer->error[h * layer->number_nodes + j];
					}
					layer->bias[j] -= learning_rate * sum;
				}
			}

			// adjust weight
			for (int i = 0; i < connection.size(); i++) {
				Connection *connection = this->connection[i];

				Layer *layer = connection->layer;
				Layer *parent_layer = connection->parent_layer;

				for (int j = 0; j < connection->number_weights; j++) {
					int k = j / parent_layer->number_nodes;
					int l = j % parent_layer->number_nodes;

					double sum = 0;

					for (int h = 0; h < this->batch_size; h++) {
						sum += layer->error[h * layer->number_nodes + k] * parent_layer->neuron[h * parent_layer->number_nodes + l];
					}
					connection->weight[j] -= learning_rate * sum;
				}
			}
		}
	}
	delete[] x_batch;
	delete[] y_batch;

	return loss / train_size;
}<commit_msg>Update Neural_Networks.cpp<commit_after>#include <math.h>
#include <memory.h>
#include <random>
#include <stdlib.h>

#include "Neural_Networks.h"

Connection::Connection(Layer *layer, Layer *parent_layer, double scale) {
	this->layer = layer;
	this->parent_layer = parent_layer;
	this->number_weights = layer->number_nodes * parent_layer->number_nodes;

	weight = new float[number_weights];

	for (int i = 0; i < number_weights; i++) {
		weight[i] = scale * (2.0 * rand() / RAND_MAX - 1);
	}
}
Connection::~Connection() {
	delete[] weight;
}

Layer::Layer(int number_nodes, int activation) {
	this->activation = activation;
	this->batch_size = 1;
	this->number_nodes = number_nodes;

	memset(bias = new float[number_nodes], 0, sizeof(float) * number_nodes);
	error = new float[number_nodes];
	neuron = new float[number_nodes];
}
Layer::~Layer() {
	for (int i = 0; i < connection.size(); i++) {
		delete connection[i];
	}
	delete[] bias;
	delete[] error;
	delete[] neuron;
}

void Layer::Activation() {
	for (int h = 0; h < batch_size; h++) {
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			neuron[j] += bias[j];
		}

		if (activation == Activation::softmax) {
			double max;
			double sum = 0;

			for (int j = 0; j < number_nodes; j++) {
				if (j == 0 || max < neuron[j]) {
					max = neuron[j];
				}
			}
			for (int j = 0; j < number_nodes; j++) {
				sum += (neuron[j] = exp(neuron[j] - max));
			}
			for (int j = 0; j < number_nodes; j++) {
				neuron[j] /= sum;
			}
		}
		else {
			if (activation == Activation::linear) {
				// neuron[j] = neuron[j];
			}
			else if (activation == Activation::sigmoid) {
				for (int j = 0; j < number_nodes; j++) {
					neuron[j] = 1 / (1 + exp(-neuron[j]));
				}
			}
		}
	}
}
void Layer::Backward() {
	for (int h = 0; h < batch_size; h++) {
		float *error = &this->error[h * number_nodes];
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			for (int k = 0; k < connection.size(); k++) {
				Connection *connection = this->connection[k];

				Layer *parent_layer = connection->parent_layer;

				float *prev_error = &parent_layer->error[h * parent_layer->number_nodes];
				float *weight = &connection->weight[j * parent_layer->number_nodes];

				for (int l = 0; l < parent_layer->number_nodes; l++) {
					prev_error[l] += error[j] * weight[l];
				}
			}
		}
	}
}
void Layer::Derivative(int loss, float **y_batch) {
	if (y_batch) {
		for (int h = 0; h < batch_size; h++) {
			float *error = &this->error[h * number_nodes];
			float *neuron = &this->neuron[h * number_nodes];

			if (loss == Loss::cross_entropy) {
				if (activation == Activation::sigmoid) {
					for (int j = 0; j < number_nodes; j++) {
						error[j] = (neuron[j] - y_batch[h][j]) / (number_nodes * batch_size);
					}
				}
				else if (activation == Activation::softmax) {
					for (int j = 0; j < number_nodes; j++) {
						error[j] = (neuron[j] - y_batch[h][j]) / batch_size;
					}
				}
			}
			else if (loss == Loss::mean_squared_error) {
				for (int j = 0; j < number_nodes; j++) {
					error[j] = 2 * (neuron[j] - y_batch[h][j]) / (number_nodes * batch_size);
				}
			}
		}
		Derivative(loss);
	}
	else {
		for (int h = 0; h < batch_size; h++) {
			float *error = &this->error[h * number_nodes];
			float *neuron = &this->neuron[h * number_nodes];

			if (activation == Activation::linear) {
				// error[j] *= 1;
			}
			else if (activation == Activation::sigmoid && loss != Loss::cross_entropy){
				for (int j = 0; j < number_nodes; j++) {
					error[j] *= (1 - neuron[j]) * neuron[j];
				}
			}
		}
	}
}
void Layer::Forward() {
	for (int h = 0; h < batch_size; h++) {
		float *neuron = &this->neuron[h * number_nodes];

		for (int j = 0; j < number_nodes; j++) {
			double sum = 0;

			for (int k = 0; k < connection.size(); k++) {
				Connection *connection = this->connection[k];

				Layer *parent_layer = connection->parent_layer;

				float *prev_neuron = &parent_layer->neuron[h * parent_layer->number_nodes];
				float *weight = &connection->weight[j * parent_layer->number_nodes];

				for (int l = 0; l < parent_layer->number_nodes; l++) {
					sum += prev_neuron[l] * weight[l];
				}
			}
			neuron[j] = sum;
		}
	}
}
void Layer::Resize_Memory(int batch_size) {
	this->batch_size = batch_size;

	error = (float*)realloc(error, sizeof(float) * batch_size * number_nodes);
	neuron = (float*)realloc(neuron, sizeof(float) * batch_size * number_nodes);
}

void Neural_Networks::Resize_Memory(int batch_size) {
	if (this->batch_size != batch_size) {
		for (int i = 0; i < layer.size(); i++) {
			layer[i]->Resize_Memory(batch_size);
		}
		this->batch_size = batch_size;
	}
}

double Neural_Networks::Calculate_Loss(Layer *layer, float **y_batch) {
	double sum = 0;

	for (int h = 0; h < batch_size; h++) {
		float *neuron = &layer->neuron[h * layer->number_nodes];

		if (loss == Loss::cross_entropy) {
			if (layer->activation == Activation::sigmoid) {
				for (int j = 0; j < layer->number_nodes; j++) {
					sum -= (y_batch[h][j] * log(static_cast<double>(neuron[j])) + (1 - y_batch[h][j]) * log(1.0 - neuron[j])) / layer->number_nodes;
				}
			}
			else if (layer->activation == Activation::softmax) {
				for (int j = 0; j < layer->number_nodes; j++) {
					sum -= y_batch[h][j] * log(static_cast<double>(neuron[j]));
				}
			}
		}
		else if (loss == Loss::mean_squared_error) {
			for (int j = 0; j < layer->number_nodes; j++) {
				sum += (neuron[j] - y_batch[h][j]) * (neuron[j] - y_batch[h][j]) / layer->number_nodes;
			}
		}
	}
	return sum;
}

Neural_Networks::Neural_Networks() {
	batch_size = 1;
}
Neural_Networks::~Neural_Networks() {
	for (int i = 0; i < layer.size(); i++) {
		delete layer[i];
	}
}

void Neural_Networks::Add(int number_nodes, int activation) {
	this->layer.push_back(new Layer(number_nodes, activation));
}
void Neural_Networks::Compile(int loss, double learning_rate) {
	this->loss = loss;
	this->learning_rate = learning_rate;
}
void Neural_Networks::Connect(int from, int to, double scale) {
	Connection *connection = new Connection(layer[from], layer[to], scale);

	this->connection.push_back(connection);
	layer[from]->connection.push_back(connection);
}
void Neural_Networks::Predict(float input[], float output[]) {
	Predict(&input, &output);
}
void Neural_Networks::Predict(float **input, float **output, int batch_size) {
	Resize_Memory(batch_size);

	for (int h = 0, i = 0; h < batch_size; h++) {
		memcpy(&layer[i]->neuron[h * layer[i]->number_nodes], input[h], sizeof(float) * layer[i]->number_nodes);
	}
	for (int i = 1; i < layer.size(); i++) {
		layer[i]->Forward();
		layer[i]->Activation();
	}
	for (int h = 0, i = layer.size() - 1; h < batch_size; h++) {
		memcpy(output[h], &layer[i]->neuron[h * layer[i]->number_nodes], sizeof(float) * layer[i]->number_nodes);
	}
}

double Neural_Networks::Evaluate(float **x_test, float **y_test, int test_size, int batch_size) {
	float **x_batch = new float*[batch_size];
	float **y_batch = new float*[batch_size];

	double loss = 0;

	for (int g = 0, h = 0; g < test_size; g++) {
		x_batch[h] = x_test[g];
		y_batch[h] = y_test[g];

		if (++h == batch_size || g == test_size - 1) {
			Resize_Memory(h);

			// copy x_test to neuron
			while (--h >= 0) {
				memcpy(&layer[0]->neuron[h * layer[0]->number_nodes], x_batch[h], sizeof(float) * layer[0]->number_nodes);
			}
			h = 0;

			// forward propagation
			for (int i = 1; i < layer.size(); i++) {
				layer[i]->Forward();
				layer[i]->Activation();
			}

			// calculate loss
			loss += Calculate_Loss(layer.back(), y_batch);
		}
	}
	delete[] x_batch;
	delete[] y_batch;

	return loss / test_size;
}
double Neural_Networks::Fit(float **x_train, float **y_train, int train_size, int batch_size) {
	float **x_batch = new float*[batch_size];
	float **y_batch = new float*[batch_size];

	double loss = 0;

	for (int g = 0, h = 0; g < train_size; g++) {
		x_batch[h] = x_train[g];
		y_batch[h] = y_train[g];

		if (++h == batch_size || g == train_size - 1) {
			Resize_Memory(h);

			// copy x_train to neuron
			while (--h >= 0) {
				memcpy(&layer[0]->neuron[h * layer[0]->number_nodes], x_batch[h], sizeof(float) * layer[0]->number_nodes);
			}
			h = 0;

			// initialize error to zero
			for (int i = 0; i < layer.size(); i++) {
				memset(layer[i]->error, 0, sizeof(float) * this->batch_size * layer[i]->number_nodes);
			}

			// forward propagation
			for (int i = 1; i < layer.size(); i++) {
				layer[i]->Forward();
				layer[i]->Activation();
			}

			// calculate loss
			loss += Calculate_Loss(layer.back(), y_batch);

			// calculate error
			layer.back()->Derivative(this->loss, y_batch);

			// error backpropagation
			layer.back()->Backward();

			for (int i = layer.size() - 2; i > 0; i--) {
				layer[i]->Derivative();
				layer[i]->Backward();
			}

			// adjust bias
			for (int i = 0; i < layer.size(); i++) {
				Layer *layer = this->layer[i];

				for (int j = 0; j < layer->number_nodes; j++) {
					double sum = 0;

					for (int h = 0; h < this->batch_size; h++) {
						sum += layer->error[h * layer->number_nodes + j];
					}
					layer->bias[j] -= learning_rate * sum;
				}
			}

			// adjust weight
			for (int i = 0; i < connection.size(); i++) {
				Connection *connection = this->connection[i];

				Layer *layer = connection->layer;
				Layer *parent_layer = connection->parent_layer;

				for (int j = 0; j < connection->number_weights; j++) {
					int k = j / parent_layer->number_nodes;
					int l = j % parent_layer->number_nodes;

					double sum = 0;

					for (int h = 0; h < this->batch_size; h++) {
						sum += layer->error[h * layer->number_nodes + k] * parent_layer->neuron[h * parent_layer->number_nodes + l];
					}
					connection->weight[j] -= learning_rate * sum;
				}
			}
		}
	}
	delete[] x_batch;
	delete[] y_batch;

	return loss / train_size;
}
<|endoftext|>


<commit_before>#include "HearthstoneLogTracker.h"

#include <QRegExp>
#include <QStringList>

const int NUM_HERO_POWER_CARDS = 43;
const char HERO_POWER_CARD_IDS[NUM_HERO_POWER_CARDS][32] = {
"CS1h_001" /* Lesser Heal */, "CS2_017" /* Shapeshift */, "CS2_034" /* Fireblast */, "CS2_049" /* Totemic Call */, "CS2_056" /* Life Tap */, "CS2_083b" /* Dagger Mastery */, "CS2_101" /* Reinforce */, "CS2_102" /* Armor Up! */, "DS1h_292" /* Steady Shot */, "EX1_625t" /* Mind Spike */, "EX1_625t2" /* Mind Shatter */, "EX1_tk33" /* INFERNO! */, "NAX10_03" /* Hateful Strike */, "NAX10_03H" /* Hateful Strike */, "NAX11_02" /* Poison Cloud */, "NAX11_02H" /* Poison Cloud */, "NAX12_02" /* Decimate */, "NAX12_02H" /* Decimate */, "NAX13_02" /* Polarity Shift */, "NAX14_02" /* Frost Breath */, "NAX15_02" /* Frost Blast */, "NAX15_02H" /* Frost Blast */, "NAX15_04" /* Chains */, "NAX15_04H" /* Chains */, "NAX1_04" /* Skitter */, "NAX1h_04" /* Skitter */, "NAX2_03" /* Rain of Fire */, "NAX2_03H" /* Rain of Fire */, "NAX3_02" /* Web Wrap */, "NAX3_02H" /* Web Wrap */, "NAX4_04" /* Raise Dead */, "NAX4_04H" /* Raise Dead */, "NAX5_02" /* Eruption */, "NAX5_02H" /* Eruption */, "NAX6_02" /* Necrotic Aura */, "NAX6_02H" /* Necrotic Aura */, "NAX7_03" /* Unbalancing Strike */, "NAX7_03H" /* Unbalancing Strike */, "NAX8_02" /* Harvest */, "NAX8_02H" /* Harvest */, "NAX9_06" /* Unholy Shadow */, "TU4d_003" /* Shotgun Blast */, "TU4e_002" /* Flames of Azzinoth */
};

HearthstoneLogTracker::HearthstoneLogTracker()
  : mTurnCounter( 0 ), mHeroPowerUsed( false ), mHeroPlayerId( 0 )
{
  connect( &mLogWatcher, SIGNAL( LineAdded(QString) ), this, SLOT( HandleLogLine(QString) ) );
  Reset();
}

void HearthstoneLogTracker::Reset() {
  mTurnCounter = 0;
  mHeroPowerUsed = false;
  mCardHistoryList.clear();
}

void HearthstoneLogTracker::HandleLogLine( const QString& line ) {
  if( line.trimmed().isEmpty() )
    return;

  // CardPlayed / CardReturned / PlayerDied
  QRegExp regex( "ProcessChanges.*cardId=(\\w+).*zone from (.*) -> (.*)" );
  if( regex.indexIn(line) != -1 ) {
    QStringList captures = regex.capturedTexts();
    QString cardId = captures[1];
    QString from = captures[2];
    QString to = captures[3];

    bool draw = from.contains( "DECK" ) && to.contains( "HAND" );
    bool mulligan = from.contains( "HAND" ) && to.contains( "DECK" );

    // Discarded cards by playing Soulfire, Doomguard etc.
    bool discard = from.contains( "HAND" ) && to.contains( "GRAVEYARD" );

    if( !draw && !mulligan && !discard ) {
      if( from.contains( "FRIENDLY HAND" ) ) {
        CardPlayed( PLAYER_SELF, cardId.toStdString() );
      } else if( from.contains( "OPPOSING HAND" ) ) {
        CardPlayed( PLAYER_OPPONENT, cardId.toStdString() );
      }
    }

    if( from.contains( "FRIENDLY PLAY" ) && to.contains( "FRIENDLY HAND" ) ) {
      CardReturned( PLAYER_SELF, cardId.toStdString() );
    }

    DEBUG( "Card %s from %s -> %s. (draw: %d, mulligan %d, discard %d)", cardId.toStdString().c_str(), from.toStdString().c_str(), to.toStdString().c_str(), draw, mulligan, discard );
  }

  // Outcome
  QRegExp regexOutcome( "\\[Asset\\].*name=(\\w+)_screen_start" );
  if( regexOutcome.indexIn(line) != -1 ) {
    QStringList captures = regexOutcome.capturedTexts();
    QString outcome = captures[1];
    if( outcome == "victory" ) {
      emit HandleOutcome( OUTCOME_VICTORY );
    } else if( outcome == "defeat" ) {
      emit HandleOutcome( OUTCOME_DEFEAT );
    }
  }

  // Coin
  QRegExp regexCoin( "ProcessChanges.*zonePos=5.*zone from  -> (.*)" );  // unique because from is nothing -> " "
  if( regexCoin.indexIn(line) != -1 ) {
    QStringList captures = regexCoin.capturedTexts();
    QString to = captures[1];

    if( to.contains( "FRIENDLY HAND" ) ) {
      // I go second because I get the coin
      emit HandleOrder( ORDER_SECOND );
    } else if( to.contains( "OPPOSING HAND" ) ) {
      // Opponent got coin, so I go first
      emit HandleOrder( ORDER_FIRST );
    }
  }

  // Turn Info
  QRegExp regexTurn( "change=powerTask.*value=MAIN_ACTION" );
  if( regexTurn.indexIn(line) != -1 ) {
    mTurnCounter++;

    // reset hero power usage on turn change
    mHeroPowerUsed = false;
  }

  // Hero Power
  QRegExp regexHeroPowerEquip( "\\[Zone\\].*player=(\\d+).*-> FRIENDLY PLAY \\(Hero Power\\)" );
  if( regexHeroPowerEquip.indexIn(line) != -1 ) {
    QStringList captures = regexHeroPowerEquip.capturedTexts();
    QString playerId = captures[1];

    mHeroPlayerId = playerId.toInt();
    DEBUG( "Hero Power Equip -> My Player Id: %d", mHeroPlayerId );
  }

  QRegExp regexHeroPower( "\\[Power\\].*cardId=(\\w+).*player=(\\d+)" );
  if( regexHeroPower.indexIn(line) != -1 ) {
    QStringList captures = regexHeroPower.capturedTexts();
    QString cardId = captures[1];
    int playerId = captures[2].toInt();
    Player player = ( playerId == mHeroPlayerId ) ? PLAYER_SELF : PLAYER_OPPONENT;

    bool isHeroPower = false;
    for( int i = 0; i < NUM_HERO_POWER_CARDS; i++ ) {
      if( cardId == HERO_POWER_CARD_IDS[ i ] ) {
        isHeroPower = true;
        break;
      }
    }

    // Power log line is emitted twice
    // Make sure we only account for first occurrence
    // Plus line is emitted when match starts, so ignore turn 0
    if( isHeroPower && !mHeroPowerUsed && CurrentTurn() > 0 ) {
      CardPlayed( player, cardId.toStdString() );
      mHeroPowerUsed = true;
    }
  }
}

void HearthstoneLogTracker::CardPlayed( Player player, const string& cardId ) {
  DEBUG( "Card played %s on turn %d: %s", PLAYER_NAMES[ player ], CurrentTurn(), cardId.c_str() );
  mCardHistoryList.push_back( CardHistoryItem( CurrentTurn(), player, cardId ) );
}

void HearthstoneLogTracker::CardReturned( Player player, const string& cardId ) {
  DEBUG( "Card returned %s on turn %d: %s", PLAYER_NAMES[ player ], CurrentTurn(), cardId.c_str() );
  // Make sure we remove the "Choose One"-cards from the history
  // if we decide to withdraw them after a second of thought
  if( !mCardHistoryList.empty() &&
      mCardHistoryList.back().turn == CurrentTurn() &&
      mCardHistoryList.back().player == player &&
      mCardHistoryList.back().cardId == cardId )
  {
    mCardHistoryList.pop_back();
  }
}

int HearthstoneLogTracker::CurrentTurn() const {
  return ( mTurnCounter + 1 ) / 2;
}
<commit_msg>fix turn count<commit_after>#include "HearthstoneLogTracker.h"

#include <QRegExp>
#include <QStringList>

const int NUM_HERO_POWER_CARDS = 43;
const char HERO_POWER_CARD_IDS[NUM_HERO_POWER_CARDS][32] = {
"CS1h_001" /* Lesser Heal */, "CS2_017" /* Shapeshift */, "CS2_034" /* Fireblast */, "CS2_049" /* Totemic Call */, "CS2_056" /* Life Tap */, "CS2_083b" /* Dagger Mastery */, "CS2_101" /* Reinforce */, "CS2_102" /* Armor Up! */, "DS1h_292" /* Steady Shot */, "EX1_625t" /* Mind Spike */, "EX1_625t2" /* Mind Shatter */, "EX1_tk33" /* INFERNO! */, "NAX10_03" /* Hateful Strike */, "NAX10_03H" /* Hateful Strike */, "NAX11_02" /* Poison Cloud */, "NAX11_02H" /* Poison Cloud */, "NAX12_02" /* Decimate */, "NAX12_02H" /* Decimate */, "NAX13_02" /* Polarity Shift */, "NAX14_02" /* Frost Breath */, "NAX15_02" /* Frost Blast */, "NAX15_02H" /* Frost Blast */, "NAX15_04" /* Chains */, "NAX15_04H" /* Chains */, "NAX1_04" /* Skitter */, "NAX1h_04" /* Skitter */, "NAX2_03" /* Rain of Fire */, "NAX2_03H" /* Rain of Fire */, "NAX3_02" /* Web Wrap */, "NAX3_02H" /* Web Wrap */, "NAX4_04" /* Raise Dead */, "NAX4_04H" /* Raise Dead */, "NAX5_02" /* Eruption */, "NAX5_02H" /* Eruption */, "NAX6_02" /* Necrotic Aura */, "NAX6_02H" /* Necrotic Aura */, "NAX7_03" /* Unbalancing Strike */, "NAX7_03H" /* Unbalancing Strike */, "NAX8_02" /* Harvest */, "NAX8_02H" /* Harvest */, "NAX9_06" /* Unholy Shadow */, "TU4d_003" /* Shotgun Blast */, "TU4e_002" /* Flames of Azzinoth */
};

HearthstoneLogTracker::HearthstoneLogTracker()
  : mTurnCounter( 0 ), mHeroPowerUsed( false ), mHeroPlayerId( 0 )
{
  connect( &mLogWatcher, SIGNAL( LineAdded(QString) ), this, SLOT( HandleLogLine(QString) ) );
  Reset();
}

void HearthstoneLogTracker::Reset() {
  mTurnCounter = 0;
  mHeroPowerUsed = false;
  mCardHistoryList.clear();
}

void HearthstoneLogTracker::HandleLogLine( const QString& line ) {
  if( line.trimmed().isEmpty() )
    return;

  // CardPlayed / CardReturned / PlayerDied
  QRegExp regex( "ProcessChanges.*cardId=(\\w+).*zone from (.*) -> (.*)" );
  if( regex.indexIn(line) != -1 ) {
    QStringList captures = regex.capturedTexts();
    QString cardId = captures[1];
    QString from = captures[2];
    QString to = captures[3];

    bool draw = from.contains( "DECK" ) && to.contains( "HAND" );
    bool mulligan = from.contains( "HAND" ) && to.contains( "DECK" );

    // Discarded cards by playing Soulfire, Doomguard etc.
    bool discard = from.contains( "HAND" ) && to.contains( "GRAVEYARD" );

    if( !draw && !mulligan && !discard ) {
      if( from.contains( "FRIENDLY HAND" ) ) {
        CardPlayed( PLAYER_SELF, cardId.toStdString() );
      } else if( from.contains( "OPPOSING HAND" ) ) {
        CardPlayed( PLAYER_OPPONENT, cardId.toStdString() );
      }
    }

    if( from.contains( "FRIENDLY PLAY" ) && to.contains( "FRIENDLY HAND" ) ) {
      CardReturned( PLAYER_SELF, cardId.toStdString() );
    }

    DEBUG( "Card %s from %s -> %s. (draw: %d, mulligan %d, discard %d)", cardId.toStdString().c_str(), from.toStdString().c_str(), to.toStdString().c_str(), draw, mulligan, discard );
  }

  // Outcome
  QRegExp regexOutcome( "\\[Asset\\].*name=(\\w+)_screen_start" );
  if( regexOutcome.indexIn(line) != -1 ) {
    QStringList captures = regexOutcome.capturedTexts();
    QString outcome = captures[1];
    if( outcome == "victory" ) {
      emit HandleOutcome( OUTCOME_VICTORY );
    } else if( outcome == "defeat" ) {
      emit HandleOutcome( OUTCOME_DEFEAT );
    }
  }

  // Coin
  QRegExp regexCoin( "ProcessChanges.*zonePos=5.*zone from  -> (.*)" );  // unique because from is nothing -> " "
  if( regexCoin.indexIn(line) != -1 ) {
    QStringList captures = regexCoin.capturedTexts();
    QString to = captures[1];

    if( to.contains( "FRIENDLY HAND" ) ) {
      // I go second because I get the coin
      emit HandleOrder( ORDER_SECOND );
    } else if( to.contains( "OPPOSING HAND" ) ) {
      // Opponent got coin, so I go first
      emit HandleOrder( ORDER_FIRST );
    }
  }

  // Turn Info
  QRegExp regexTurn( "change=powerTask.*tag=NEXT_STEP value=MAIN_ACTION" );
  if( regexTurn.indexIn(line) != -1 ) {
    mTurnCounter++;

    // reset hero power usage on turn change
    mHeroPowerUsed = false;
  }

  // Hero Power
  QRegExp regexHeroPowerEquip( "\\[Zone\\].*player=(\\d+).*-> FRIENDLY PLAY \\(Hero Power\\)" );
  if( regexHeroPowerEquip.indexIn(line) != -1 ) {
    QStringList captures = regexHeroPowerEquip.capturedTexts();
    QString playerId = captures[1];

    mHeroPlayerId = playerId.toInt();
    DEBUG( "Hero Power Equip -> My Player Id: %d", mHeroPlayerId );
  }

  QRegExp regexHeroPower( "\\[Power\\].*cardId=(\\w+).*player=(\\d+)" );
  if( regexHeroPower.indexIn(line) != -1 ) {
    QStringList captures = regexHeroPower.capturedTexts();
    QString cardId = captures[1];
    int playerId = captures[2].toInt();
    Player player = ( playerId == mHeroPlayerId ) ? PLAYER_SELF : PLAYER_OPPONENT;

    bool isHeroPower = false;
    for( int i = 0; i < NUM_HERO_POWER_CARDS; i++ ) {
      if( cardId == HERO_POWER_CARD_IDS[ i ] ) {
        isHeroPower = true;
        break;
      }
    }

    // Power log line is emitted twice
    // Make sure we only account for first occurrence
    // Plus line is emitted when match starts, so ignore turn 0
    if( isHeroPower && !mHeroPowerUsed && CurrentTurn() > 0 ) {
      CardPlayed( player, cardId.toStdString() );
      mHeroPowerUsed = true;
    }
  }
}

void HearthstoneLogTracker::CardPlayed( Player player, const string& cardId ) {
  DEBUG( "Card played %s on turn %d: %s", PLAYER_NAMES[ player ], CurrentTurn(), cardId.c_str() );
  mCardHistoryList.push_back( CardHistoryItem( CurrentTurn(), player, cardId ) );
}

void HearthstoneLogTracker::CardReturned( Player player, const string& cardId ) {
  DEBUG( "Card returned %s on turn %d: %s", PLAYER_NAMES[ player ], CurrentTurn(), cardId.c_str() );
  // Make sure we remove the "Choose One"-cards from the history
  // if we decide to withdraw them after a second of thought
  if( !mCardHistoryList.empty() &&
      mCardHistoryList.back().turn == CurrentTurn() &&
      mCardHistoryList.back().player == player &&
      mCardHistoryList.back().cardId == cardId )
  {
    mCardHistoryList.pop_back();
  }
}

int HearthstoneLogTracker::CurrentTurn() const {
  return ( mTurnCounter + 1 ) / 2;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip>
#include <string>
#include <memory>

#include <windows.h>
#include <psapi.h> //GetModuleFileNameEx
#include <TlHelp32.h>

// Setting DLL access controls
#include <AccCtrl.h>
#include <Aclapi.h>
#include <Sddl.h>

// UWP
#include <atlbase.h>
#include <appmodel.h>

#include "MinConsole.hpp"

namespace Console = MinConsole;

const wchar_t* DLLFile = L"UWPDumper.dll";

void SetAccessControl(const std::wstring &ExecutableName);

bool DLLInjectRemote(uint32_t ProcessID, const std::wstring &DLLpath);

std::wstring GetRunningDirectory();

int main()
{
	SetConsoleOutputCP(437);

	Console::SetTextColor(Console::Color::Info);
	std::wcout << "UWPInjector Build date (" << __DATE__ << " : " << __TIME__ << ")" << std::endl;
	Console::SetTextColor(Console::Color::Input);
	std::wcout << "\t-https://github.com/Wunkolo/UWPDumper\n";
	Console::SetTextColor(Console::Color::Magenta);
	std::wcout << std::wstring(Console::GetWidth() - 1, '-') << std::endl;
	Console::SetTextColor(Console::Color::Info);

	uint32_t ProcessID = 0;

	std::cout << "Currently running UWP Apps:" << std::endl;
	void* ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32 ProcessEntry;
	ProcessEntry.dwSize = sizeof(PROCESSENTRY32);

	if( Process32First(ProcessSnapshot, &ProcessEntry) )
	{
		while( Process32Next(ProcessSnapshot, &ProcessEntry) )
		{
			void* ProcessHandle = OpenProcess(
				PROCESS_QUERY_LIMITED_INFORMATION,
				false,
				ProcessEntry.th32ProcessID
			);
			if( ProcessHandle )
			{
				uint32_t NameLength = 0;
				int32_t ProcessCode = GetPackageFullName(
					ProcessHandle,
					&NameLength,
					nullptr
				);
				if( NameLength )
				{
					std::wcout
						<< std::setw(12)
						<< ProcessEntry.th32ProcessID << " | "
						<< ProcessEntry.szExeFile << " : ";
					std::unique_ptr<wchar_t[]> PackageName(new wchar_t[NameLength]());

					ProcessCode = GetPackageFullName(
						ProcessHandle,
						&NameLength,
						PackageName.get()
					);

					if( ProcessCode != ERROR_SUCCESS )
					{
						std::wcout << "GetPackageFamilyName Error: " << ProcessCode;
					}

					std::wcout << PackageName.get() << std::endl;

					PackageName.reset();
				}
			}
			CloseHandle(ProcessHandle);
		}
	}
	else
	{
		// Error iterating processes
	}
	std::cout << "Enter ProcessID: ";
	std::cin >> ProcessID;

	SetAccessControl(GetRunningDirectory() + L"\\" + DLLFile);

	if( DLLInjectRemote(ProcessID, GetRunningDirectory() + L"\\" + DLLFile) )
	{
		Console::SetTextColor(Console::Color::Green | Console::Color::Bright);
		std::cout << "Success!" << std::endl;
	}
	else
	{
		Console::SetTextColor(Console::Color::Red | Console::Color::Bright);
		std::cout << "Failed" << std::endl;
		system("pause");
	}

	return 0;
}

void SetAccessControl(const std::wstring &ExecutableName)
{
	PSECURITY_DESCRIPTOR SecurityDescriptor = nullptr;
	EXPLICIT_ACCESSW ExplicitAccess = { 0 };

	ACL *AccessControlCurrent = nullptr;
	ACL *AccessControlNew = nullptr;

	SECURITY_INFORMATION SecurityInfo = DACL_SECURITY_INFORMATION;
	PSID SecurityIdentifier = nullptr;

	if( GetNamedSecurityInfoW(
		ExecutableName.c_str(),
		SE_FILE_OBJECT,
		DACL_SECURITY_INFORMATION,
		nullptr,
		nullptr,
		&AccessControlCurrent,
		nullptr,
		&SecurityDescriptor) == ERROR_SUCCESS
		)
	{
		ConvertStringSidToSidW(L"S-1-15-2-1", &SecurityIdentifier);
		if( SecurityIdentifier != nullptr )
		{
			ExplicitAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
			ExplicitAccess.grfAccessMode = SET_ACCESS;
			ExplicitAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
			ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
			ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
			ExplicitAccess.Trustee.ptstrName = reinterpret_cast<wchar_t*>(SecurityIdentifier);

			if( SetEntriesInAclW(
				1,
				&ExplicitAccess,
				AccessControlCurrent,
				&AccessControlNew) == ERROR_SUCCESS )
			{
				SetNamedSecurityInfoW(
					const_cast<wchar_t*>(ExecutableName.c_str()),
					SE_FILE_OBJECT,
					SecurityInfo,
					nullptr,
					nullptr,
					AccessControlNew,
					nullptr
				);
			};
		}
	}
	if( SecurityDescriptor )
	{
		LocalFree(
			reinterpret_cast<HLOCAL>(SecurityDescriptor)
		);
	}
	if( AccessControlNew )
	{
		LocalFree(
			reinterpret_cast<HLOCAL>(AccessControlNew)
		);
	}
}

bool DLLInjectRemote(uint32_t ProcessID, const std::wstring& DLLpath)
{
	const size_t DLLPathSize = ((DLLpath.size() + 1) * sizeof(wchar_t));
	uint32_t Result = 0;
	if( !ProcessID )
	{
		return false;
	}

	if( GetFileAttributesW(DLLpath.c_str()) == INVALID_FILE_ATTRIBUTES )
	{
		std::wcout << "DLL file: " << DLLpath << " does not exists" << std::endl;
		return false;
	}

	SetAccessControl(DLLpath);

	void* ProcLoadLibrary = reinterpret_cast<void*>(
		GetProcAddress(
			GetModuleHandleW(L"kernel32.dll"),
			"LoadLibraryW")
		);

	if( !ProcLoadLibrary )
	{
		std::wcout << "Unable to find LoadLibraryW procedure" << std::endl;
		return false;
	}

	void* Process = OpenProcess(
		PROCESS_ALL_ACCESS,
		false,
		ProcessID);
	if( Process == nullptr )
	{
		std::wcout << "Unable to open process for writing" << std::endl;
		return false;
	}
	void* VirtualAlloc = reinterpret_cast<void*>(
		VirtualAllocEx(
			Process,
			nullptr,
			DLLPathSize,
			MEM_RESERVE | MEM_COMMIT,
			PAGE_READWRITE
		)
		);

	if( VirtualAlloc == nullptr )
	{
		std::wcout << "Unable to remotely allocate memory" << std::endl;
		CloseHandle(Process);
		return false;
	}

	SIZE_T BytesWritten = 0;
	Result = WriteProcessMemory(
		Process,
		VirtualAlloc,
		DLLpath.data(),
		DLLPathSize,
		&BytesWritten
	);

	if( Result == 0 )
	{
		std::wcout << "Unable to write process memory" << std::endl;
		CloseHandle(Process);
		return false;
	}

	if( BytesWritten != DLLPathSize )
	{
		std::wcout << "Failed to write remote DLL path name" << std::endl;
		CloseHandle(Process);
		return false;
	}

	void* RemoteThread =
		CreateRemoteThread(
			Process,
			nullptr,
			0,
			reinterpret_cast<LPTHREAD_START_ROUTINE>(ProcLoadLibrary),
			VirtualAlloc,
			0,
			0
		);

	// Wait for remote thread to finish
	if( RemoteThread )
	{
		// Explicitly wait for LoadLibraryW to complete before releasing memory
		// avoids causing a remote memory leak
		WaitForSingleObject(RemoteThread, INFINITE);
		CloseHandle(RemoteThread);
	}
	else
	{
		// Failed to create thread
		std::wcout << "Unable to create remote thread" << std::endl;
	}

	VirtualFreeEx(Process, VirtualAlloc, 0, MEM_RELEASE);
	CloseHandle(Process);
	return true;
}

std::wstring GetRunningDirectory()
{
	wchar_t RunPath[MAX_PATH];
	GetModuleFileNameW(GetModuleHandleW(nullptr), RunPath, MAX_PATH);
	PathRemoveFileSpecW(RunPath);
	return std::wstring(RunPath);
}<commit_msg>Add verbosity and formatting<commit_after>#include <iostream>
#include <iomanip>
#include <string>
#include <memory>

#include <windows.h>
#include <psapi.h> //GetModuleFileNameEx
#include <TlHelp32.h>

// Setting DLL access controls
#include <AccCtrl.h>
#include <Aclapi.h>
#include <Sddl.h>

// UWP
#include <atlbase.h>
#include <appmodel.h>

#include "MinConsole.hpp"

namespace Console = MinConsole;

const wchar_t* DLLFile = L"UWPDumper.dll";

void SetAccessControl(const std::wstring &ExecutableName);

bool DLLInjectRemote(uint32_t ProcessID, const std::wstring &DLLpath);

std::wstring GetRunningDirectory();

int main()
{
	SetConsoleOutputCP(437);

	Console::SetTextColor(Console::Color::Green | Console::Color::Bright);
	std::wcout << "UWPInjector Build date (" << __DATE__ << " : " << __TIME__ << ")" << std::endl;
	Console::SetTextColor(Console::Color::Input);
	std::wcout << "\t-https://github.com/Wunkolo/UWPDumper\n";
	Console::SetTextColor(Console::Color::Magenta);
	std::wcout << std::wstring(Console::GetWidth() - 1, '-') << std::endl;
	Console::SetTextColor(Console::Color::Info);

	uint32_t ProcessID = 0;

	std::cout << "Currently running UWP Apps:" << std::endl;
	void* ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	PROCESSENTRY32 ProcessEntry;
	ProcessEntry.dwSize = sizeof(PROCESSENTRY32);

	if( Process32First(ProcessSnapshot, &ProcessEntry) )
	{
		while( Process32Next(ProcessSnapshot, &ProcessEntry) )
		{
			void* ProcessHandle = OpenProcess(
				PROCESS_QUERY_LIMITED_INFORMATION,
				false,
				ProcessEntry.th32ProcessID
			);
			if( ProcessHandle )
			{
				uint32_t NameLength = 0;
				int32_t ProcessCode = GetPackageFullName(
					ProcessHandle,
					&NameLength,
					nullptr
				);
				if( NameLength )
				{
					Console::SetTextColor(Console::Color::Green | Console::Color::Bright);
					std::wcout
						<< std::setw(12)
						<< ProcessEntry.th32ProcessID;

					Console::SetTextColor(Console::Color::Info);
					std::wcout
						<< " | "
						<< ProcessEntry.szExeFile << " :\n\t\t-";
					std::unique_ptr<wchar_t[]> PackageName(new wchar_t[NameLength]());

					ProcessCode = GetPackageFullName(
						ProcessHandle,
						&NameLength,
						PackageName.get()
					);

					if( ProcessCode != ERROR_SUCCESS )
					{
						std::wcout << "GetPackageFamilyName Error: " << ProcessCode;
					}

					std::wcout << PackageName.get() << std::endl;

					PackageName.reset();
				}
			}
			CloseHandle(ProcessHandle);
		}
	}
	else
	{
		// Error iterating processes
	}
	std::cout << "Enter ProcessID: ";
	Console::SetTextColor(Console::Color::Green | Console::Color::Bright);
	std::cin >> ProcessID;
	Console::SetTextColor(Console::Color::Info);

	SetAccessControl(GetRunningDirectory() + L"\\" + DLLFile);

	if( DLLInjectRemote(ProcessID, GetRunningDirectory() + L"\\" + DLLFile) )
	{
		Console::SetTextColor(Console::Color::Green | Console::Color::Bright);
		std::cout << "Success!" << std::endl;
	}
	else
	{
		Console::SetTextColor(Console::Color::Red | Console::Color::Bright);
		std::cout << "Failed" << std::endl;
		system("pause");
	}

	return 0;
}

void SetAccessControl(const std::wstring &ExecutableName)
{
	PSECURITY_DESCRIPTOR SecurityDescriptor = nullptr;
	EXPLICIT_ACCESSW ExplicitAccess = { 0 };

	ACL *AccessControlCurrent = nullptr;
	ACL *AccessControlNew = nullptr;

	SECURITY_INFORMATION SecurityInfo = DACL_SECURITY_INFORMATION;
	PSID SecurityIdentifier = nullptr;

	if( GetNamedSecurityInfoW(
		ExecutableName.c_str(),
		SE_FILE_OBJECT,
		DACL_SECURITY_INFORMATION,
		nullptr,
		nullptr,
		&AccessControlCurrent,
		nullptr,
		&SecurityDescriptor) == ERROR_SUCCESS
		)
	{
		ConvertStringSidToSidW(L"S-1-15-2-1", &SecurityIdentifier);
		if( SecurityIdentifier != nullptr )
		{
			ExplicitAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
			ExplicitAccess.grfAccessMode = SET_ACCESS;
			ExplicitAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
			ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
			ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
			ExplicitAccess.Trustee.ptstrName = reinterpret_cast<wchar_t*>(SecurityIdentifier);

			if( SetEntriesInAclW(
				1,
				&ExplicitAccess,
				AccessControlCurrent,
				&AccessControlNew) == ERROR_SUCCESS )
			{
				SetNamedSecurityInfoW(
					const_cast<wchar_t*>(ExecutableName.c_str()),
					SE_FILE_OBJECT,
					SecurityInfo,
					nullptr,
					nullptr,
					AccessControlNew,
					nullptr
				);
			};
		}
	}
	if( SecurityDescriptor )
	{
		LocalFree(
			reinterpret_cast<HLOCAL>(SecurityDescriptor)
		);
	}
	if( AccessControlNew )
	{
		LocalFree(
			reinterpret_cast<HLOCAL>(AccessControlNew)
		);
	}
}

bool DLLInjectRemote(uint32_t ProcessID, const std::wstring& DLLpath)
{
	const size_t DLLPathSize = ((DLLpath.size() + 1) * sizeof(wchar_t));
	uint32_t Result = 0;
	if( !ProcessID )
	{
		std::wcout << "Invalid Process ID: " << ProcessID << std::endl;
		return false;
	}

	if( GetFileAttributesW(DLLpath.c_str()) == INVALID_FILE_ATTRIBUTES )
	{
		std::wcout << "DLL file: " << DLLpath << " does not exists" << std::endl;
		return false;
	}

	SetAccessControl(DLLpath);

	void* ProcLoadLibrary = reinterpret_cast<void*>(
		GetProcAddress(
			GetModuleHandleW(L"kernel32.dll"),
			"LoadLibraryW")
		);

	if( !ProcLoadLibrary )
	{
		std::wcout << "Unable to find LoadLibraryW procedure" << std::endl;
		return false;
	}

	void* Process = OpenProcess(
		PROCESS_ALL_ACCESS,
		false,
		ProcessID);
	if( Process == nullptr )
	{
		std::wcout << "Unable to open process ID" << ProcessID << " for writing" << std::endl;
		return false;
	}
	void* VirtualAlloc = reinterpret_cast<void*>(
		VirtualAllocEx(
			Process,
			nullptr,
			DLLPathSize,
			MEM_RESERVE | MEM_COMMIT,
			PAGE_READWRITE
		)
		);

	if( VirtualAlloc == nullptr )
	{
		std::wcout << "Unable to remotely allocate memory" << std::endl;
		CloseHandle(Process);
		return false;
	}

	SIZE_T BytesWritten = 0;
	Result = WriteProcessMemory(
		Process,
		VirtualAlloc,
		DLLpath.data(),
		DLLPathSize,
		&BytesWritten
	);

	if( Result == 0 )
	{
		std::wcout << "Unable to write process memory" << std::endl;
		CloseHandle(Process);
		return false;
	}

	if( BytesWritten != DLLPathSize )
	{
		std::wcout << "Failed to write remote DLL path name" << std::endl;
		CloseHandle(Process);
		return false;
	}

	void* RemoteThread =
		CreateRemoteThread(
			Process,
			nullptr,
			0,
			reinterpret_cast<LPTHREAD_START_ROUTINE>(ProcLoadLibrary),
			VirtualAlloc,
			0,
			0
		);

	// Wait for remote thread to finish
	if( RemoteThread )
	{
		// Explicitly wait for LoadLibraryW to complete before releasing memory
		// avoids causing a remote memory leak
		WaitForSingleObject(RemoteThread, INFINITE);
		CloseHandle(RemoteThread);
	}
	else
	{
		// Failed to create thread
		std::wcout << "Unable to create remote thread" << std::endl;
	}

	VirtualFreeEx(Process, VirtualAlloc, 0, MEM_RELEASE);
	CloseHandle(Process);
	return true;
}

std::wstring GetRunningDirectory()
{
	wchar_t RunPath[MAX_PATH];
	GetModuleFileNameW(GetModuleHandleW(nullptr), RunPath, MAX_PATH);
	PathRemoveFileSpecW(RunPath);
	return std::wstring(RunPath);
}<|endoftext|>