<commit_before>/* Copyright 2017 R. Thomas
 * Copyright 2017 Quarkslab
 *
 * 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 <stdexcept>
#include <string.h>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <numeric>
#include <iterator>

#include "LIEF/PE/hash.hpp"
#include "LIEF/exception.hpp"

#include "LIEF/Abstract/Section.hpp"

#include "LIEF/PE/Section.hpp"
#include "LIEF/PE/EnumToString.hpp"

namespace LIEF {
namespace PE {

Section::~Section(void) = default;

Section::Section(void) :
  LIEF::Section{},
  virtualSize_{0},
  content_{},
  pointerToRelocations_{0},
  pointerToLineNumbers_{0},
  numberOfRelocations_{0},
  numberOfLineNumbers_{0},
  characteristics_{0},
  types_{PE_SECTION_TYPES::UNKNOWN}
{}

Section& Section::operator=(const Section&) = default;
Section::Section(const Section&) = default;

Section::Section(const pe_section* header) :
  virtualSize_{header->VirtualSize},
  pointerToRelocations_{header->PointerToRelocations},
  pointerToLineNumbers_{header->PointerToLineNumbers},
  numberOfRelocations_{header->NumberOfRelocations},
  numberOfLineNumbers_{header->NumberOfLineNumbers},
  characteristics_{header->Characteristics},
  types_{PE_SECTION_TYPES::UNKNOWN}
{
  this->name_            = std::string(header->Name, sizeof(header->Name)).c_str();
  this->virtual_address_ = header->VirtualAddress;
  this->size_            = header->SizeOfRawData;
  this->offset_          = header->PointerToRawData;

}

Section::Section(const std::vector<uint8_t>& data, const std::string& name, uint32_t characteristics) :
  Section::Section{}
{
  this->characteristics_ = characteristics;
  this->name_            = name;
  this->size_            = data.size();
  this->content_         = data;
}

Section::Section(const std::string& name) :
  Section::Section{}
{
  this->name_ = name;
}

uint32_t Section::virtual_size(void) const {
  return this->virtualSize_;
}

uint32_t Section::sizeof_raw_data(void) const {
  return this->size();
}

std::vector<uint8_t> Section::content(void) const {
  return this->content_;
}

std::vector<uint8_t>& Section::content_ref(void) {
  return this->content_;
}

uint32_t Section::pointerto_raw_data(void) const {
  return this->offset();
}

uint32_t Section::pointerto_relocation(void) const {
  return this->pointerToRelocations_;
}

uint32_t Section::pointerto_line_numbers(void) const {
  return this->pointerToLineNumbers_;
}

uint16_t Section::numberof_relocations(void) const {
  return this->numberOfRelocations_;
}

uint16_t Section::numberof_line_numbers(void) const {
  return this->numberOfLineNumbers_;
}

uint32_t Section::characteristics(void) const {
  return this->characteristics_;
}

const std::set<PE_SECTION_TYPES>& Section::types(void) const {
  return this->types_;
}

bool Section::is_type(PE_SECTION_TYPES type) const {
  return this->types_.count(type) != 0;
}

void Section::name(const std::string& name) {
  if (name.size() > STRUCT_SIZES::NameSize - 1) {
    throw LIEF::pe_bad_section_name("Name is too big");
  }
  this->name_  = name;
}

bool Section::has_characteristic(SECTION_CHARACTERISTICS c) const {
  return (this->characteristics_ & static_cast<uint32_t>(c)) > 0;
}

std::set<SECTION_CHARACTERISTICS> Section::characteristics_list(void) const {
  std::set<SECTION_CHARACTERISTICS> charac;
  std::copy_if(
      std::begin(section_characteristics_array),
      std::end(section_characteristics_array),
      std::inserter(charac, std::begin(charac)),
      std::bind(&Section::has_characteristic, this, std::placeholders::_1));

  return charac;
}

void Section::content(const std::vector<uint8_t>& data) {
  this->content_ = data;
}

void Section::virtual_size(uint32_t virtualSize) {
  this->virtualSize_ = virtualSize;
}

void Section::pointerto_raw_data(uint32_t pointerToRawData) {
  this->offset(pointerToRawData);
}

void Section::pointerto_relocation(uint32_t pointerToRelocation) {
  this->pointerToRelocations_ = pointerToRelocation;
}

void Section::pointerto_line_numbers(uint32_t pointerToLineNumbers) {
  this->pointerToLineNumbers_ = pointerToLineNumbers;
}

void Section::numberof_relocations(uint16_t numberOfRelocations) {
  this->numberOfRelocations_ = numberOfRelocations;
}

void Section::numberof_line_numbers(uint16_t numberOfLineNumbers) {
  this->numberOfLineNumbers_ = numberOfLineNumbers;
}

void Section::sizeof_raw_data(uint32_t sizeOfRawData) {
  this->size(sizeOfRawData);
}

void Section::type(PE_SECTION_TYPES type) {
  this->types_ = {type};
}

void Section::remove_type(PE_SECTION_TYPES type) {
  this->types_.erase(type);
}

void Section::add_type(PE_SECTION_TYPES type) {
  this->types_.insert(type);
}

void Section::characteristics(uint32_t characteristics) {
  this->characteristics_ = characteristics;
}

void Section::remove_characteristic(SECTION_CHARACTERISTICS characteristic) {
  this->characteristics_ &= ~ static_cast<uint32_t>(characteristic);
}

void Section::add_characteristic(SECTION_CHARACTERISTICS characteristic) {
  this->characteristics_ |= static_cast<uint32_t>(characteristic);
}

void Section::accept(LIEF::Visitor& visitor) const {
  visitor.visit(*this);
}

void Section::clear(uint8_t c) {
  std::fill(
      std::begin(this->content_),
      std::end(this->content_),
      c);
}

bool Section::operator==(const Section& rhs) const {
  size_t hash_lhs = Hash::hash(*this);
  size_t hash_rhs = Hash::hash(rhs);
  return hash_lhs == hash_rhs;
}

bool Section::operator!=(const Section& rhs) const {
  return not (*this == rhs);
}

std::ostream& operator<<(std::ostream& os, const Section& section) {
  const auto& chara = section.characteristics_list();

  std::string chara_str = std::accumulate(
     std::begin(chara),
     std::end(chara), std::string{},
     [] (const std::string& a, SECTION_CHARACTERISTICS b) {
         return a.empty() ?
         to_string(b) :
         a + " - " + to_string(b);
     });
  os << std::hex;
  os << std::left
     << std::setw(10) << section.name()
     << std::setw(10) << section.virtual_size()
     << std::setw(10) << section.virtual_address()
     << std::setw(10) << section.size()
     << std::setw(10) << section.offset()
     << std::setw(10) << section.pointerto_relocation()
     << std::setw(10) << section.entropy()
     << std::setw(10) << chara_str;

  return os;
}

}
}
<commit_msg>Fix (bad) bound checking<commit_after>/* Copyright 2017 R. Thomas
 * Copyright 2017 Quarkslab
 *
 * 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 <stdexcept>
#include <string.h>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <numeric>
#include <iterator>

#include "LIEF/PE/hash.hpp"
#include "LIEF/exception.hpp"

#include "LIEF/Abstract/Section.hpp"

#include "LIEF/PE/Section.hpp"
#include "LIEF/PE/EnumToString.hpp"

namespace LIEF {
namespace PE {

Section::~Section(void) = default;

Section::Section(void) :
  LIEF::Section{},
  virtualSize_{0},
  content_{},
  pointerToRelocations_{0},
  pointerToLineNumbers_{0},
  numberOfRelocations_{0},
  numberOfLineNumbers_{0},
  characteristics_{0},
  types_{PE_SECTION_TYPES::UNKNOWN}
{}

Section& Section::operator=(const Section&) = default;
Section::Section(const Section&) = default;

Section::Section(const pe_section* header) :
  virtualSize_{header->VirtualSize},
  pointerToRelocations_{header->PointerToRelocations},
  pointerToLineNumbers_{header->PointerToLineNumbers},
  numberOfRelocations_{header->NumberOfRelocations},
  numberOfLineNumbers_{header->NumberOfLineNumbers},
  characteristics_{header->Characteristics},
  types_{PE_SECTION_TYPES::UNKNOWN}
{
  this->name_            = std::string(header->Name, sizeof(header->Name)).c_str();
  this->virtual_address_ = header->VirtualAddress;
  this->size_            = header->SizeOfRawData;
  this->offset_          = header->PointerToRawData;

}

Section::Section(const std::vector<uint8_t>& data, const std::string& name, uint32_t characteristics) :
  Section::Section{}
{
  this->characteristics_ = characteristics;
  this->name_            = name;
  this->size_            = data.size();
  this->content_         = data;
}

Section::Section(const std::string& name) :
  Section::Section{}
{
  this->name_ = name;
}

uint32_t Section::virtual_size(void) const {
  return this->virtualSize_;
}

uint32_t Section::sizeof_raw_data(void) const {
  return this->size();
}

std::vector<uint8_t> Section::content(void) const {
  return this->content_;
}

std::vector<uint8_t>& Section::content_ref(void) {
  return this->content_;
}

uint32_t Section::pointerto_raw_data(void) const {
  return this->offset();
}

uint32_t Section::pointerto_relocation(void) const {
  return this->pointerToRelocations_;
}

uint32_t Section::pointerto_line_numbers(void) const {
  return this->pointerToLineNumbers_;
}

uint16_t Section::numberof_relocations(void) const {
  return this->numberOfRelocations_;
}

uint16_t Section::numberof_line_numbers(void) const {
  return this->numberOfLineNumbers_;
}

uint32_t Section::characteristics(void) const {
  return this->characteristics_;
}

const std::set<PE_SECTION_TYPES>& Section::types(void) const {
  return this->types_;
}

bool Section::is_type(PE_SECTION_TYPES type) const {
  return this->types_.count(type) != 0;
}

void Section::name(const std::string& name) {
  if (name.size() > STRUCT_SIZES::NameSize) {
    throw LIEF::pe_bad_section_name("Name is too big");
  }
  this->name_  = name;
}

bool Section::has_characteristic(SECTION_CHARACTERISTICS c) const {
  return (this->characteristics_ & static_cast<uint32_t>(c)) > 0;
}

std::set<SECTION_CHARACTERISTICS> Section::characteristics_list(void) const {
  std::set<SECTION_CHARACTERISTICS> charac;
  std::copy_if(
      std::begin(section_characteristics_array),
      std::end(section_characteristics_array),
      std::inserter(charac, std::begin(charac)),
      std::bind(&Section::has_characteristic, this, std::placeholders::_1));

  return charac;
}

void Section::content(const std::vector<uint8_t>& data) {
  this->content_ = data;
}

void Section::virtual_size(uint32_t virtualSize) {
  this->virtualSize_ = virtualSize;
}

void Section::pointerto_raw_data(uint32_t pointerToRawData) {
  this->offset(pointerToRawData);
}

void Section::pointerto_relocation(uint32_t pointerToRelocation) {
  this->pointerToRelocations_ = pointerToRelocation;
}

void Section::pointerto_line_numbers(uint32_t pointerToLineNumbers) {
  this->pointerToLineNumbers_ = pointerToLineNumbers;
}

void Section::numberof_relocations(uint16_t numberOfRelocations) {
  this->numberOfRelocations_ = numberOfRelocations;
}

void Section::numberof_line_numbers(uint16_t numberOfLineNumbers) {
  this->numberOfLineNumbers_ = numberOfLineNumbers;
}

void Section::sizeof_raw_data(uint32_t sizeOfRawData) {
  this->size(sizeOfRawData);
}

void Section::type(PE_SECTION_TYPES type) {
  this->types_ = {type};
}

void Section::remove_type(PE_SECTION_TYPES type) {
  this->types_.erase(type);
}

void Section::add_type(PE_SECTION_TYPES type) {
  this->types_.insert(type);
}

void Section::characteristics(uint32_t characteristics) {
  this->characteristics_ = characteristics;
}

void Section::remove_characteristic(SECTION_CHARACTERISTICS characteristic) {
  this->characteristics_ &= ~ static_cast<uint32_t>(characteristic);
}

void Section::add_characteristic(SECTION_CHARACTERISTICS characteristic) {
  this->characteristics_ |= static_cast<uint32_t>(characteristic);
}

void Section::accept(LIEF::Visitor& visitor) const {
  visitor.visit(*this);
}

void Section::clear(uint8_t c) {
  std::fill(
      std::begin(this->content_),
      std::end(this->content_),
      c);
}

bool Section::operator==(const Section& rhs) const {
  size_t hash_lhs = Hash::hash(*this);
  size_t hash_rhs = Hash::hash(rhs);
  return hash_lhs == hash_rhs;
}

bool Section::operator!=(const Section& rhs) const {
  return not (*this == rhs);
}

std::ostream& operator<<(std::ostream& os, const Section& section) {
  const auto& chara = section.characteristics_list();

  std::string chara_str = std::accumulate(
     std::begin(chara),
     std::end(chara), std::string{},
     [] (const std::string& a, SECTION_CHARACTERISTICS b) {
         return a.empty() ?
         to_string(b) :
         a + " - " + to_string(b);
     });
  os << std::hex;
  os << std::left
     << std::setw(10) << section.name()
     << std::setw(10) << section.virtual_size()
     << std::setw(10) << section.virtual_address()
     << std::setw(10) << section.size()
     << std::setw(10) << section.offset()
     << std::setw(10) << section.pointerto_relocation()
     << std::setw(10) << section.entropy()
     << std::setw(10) << chara_str;

  return os;
}

}
}
<|endoftext|>


<commit_before>//============================================================================
// Name        : PinballBot.cpp
// Author      : Nico Hauser, David Schmid
// Version     : 0.1
// Description : A reinforcement learning agent that learns to play pinball
//============================================================================

#include <stdlib.h>     /* atexit */
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <numeric>
#include <ctime>

#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>

#include "PinballBot.h"

#include "action/ActionsSim.cpp"

#include "sim/Simulation.h"
#include "sim/Renderer.h"

#include "agent/Agent.h"
#include "agent/State.h"

#include "stats/StatsLogger.h"

const bool						PinballBot::SIMULATION					= true;

const bool						PinballBot::RENDER						= false;
const float						PinballBot::FPS							= 60.0f;
const float						PinballBot::TIME_STEP					= 1.0f / FPS;
const float						PinballBot::TICK_INTERVAL				= 1000.0f / FPS;

const unsigned long long		PinballBot::SAVE_INTERVAL				= 100000;
const unsigned long long		PinballBot::STATS_INTERVAL				= 50000;
const unsigned long long		PinballBot::LOG_INTERVAL				= 10000;
const unsigned long long		PinballBot::OUTSIDE_CF_UNTIL_RESPAWN	= 1800;//1 step ≈ 1/60 sec in-game, 1800 steps ≈ 30 secs in-game

const std::string				PinballBot::STATS_FILE					= "stats.csv";
const std::string				PinballBot::POLICIES_FILE				= "policies.csv";

PinballBot::PinballBot() : statsLogger(), rewardsCollected(0, 0.0f){

	KEYS							= SDL_GetKeyboardState(NULL);

	pause							= false;
	quit							= false;

	nextTime						= 0;

	steps							= 0;
	statsRewardsCollected			= 0;
	timeLastLog						= std::time(nullptr);
	gameOvers						= 0;

	stepStartedBeingOutsideCF		= 0;

	rlAgent							= nullptr;
	renderer						= nullptr;

	statsLogger.registerLoggingColumn("STEPS",					std::bind(&PinballBot::logSteps, this));
	statsLogger.registerLoggingColumn("TIME",					std::bind(&PinballBot::logTime, this));
	statsLogger.registerLoggingColumn("AMOUNT_OF_STATES",		std::bind(&PinballBot::logAmountOfStates, this));
	statsLogger.registerLoggingColumn("AVERAGE_TIME_PER_LOOP",	std::bind(&PinballBot::logAverageTimePerLoop, this));
	statsLogger.registerLoggingColumn("REWARDS_COLLECTED",		std::bind(&PinballBot::logRewardsCollected, this));
	statsLogger.registerLoggingColumn("GAMEOVERS",				std::bind(&PinballBot::logGameOvers, this));

	statsLogger.initLog(STATS_FILE);
}

Uint32 PinballBot::timeLeft() {
    Uint32 now = SDL_GetTicks();

    if(nextTime <= now){
    	return 0;
    }else{
    	return nextTime - now;
    }
}

void PinballBot::capFramerate() {
	SDL_Delay(timeLeft());
	nextTime += TICK_INTERVAL;
}

void PinballBot::handleKeys(Simulation &sim, SDL_Event &e){
	while( SDL_PollEvent( &e ) != 0 ){
		if( e.type == SDL_QUIT ){
			quit = true;
		}

		if (KEYS[SDL_SCANCODE_LEFT]){
			sim.enableLeftFlipper();
		}else{
			sim.disableLeftFlipper();
		}

		if (KEYS[SDL_SCANCODE_RIGHT]){
			sim.enableRightFlipper();
		}else{
			sim.disableRightFlipper();
		}

		if (KEYS[SDL_SCANCODE_SPACE]){
			pause = true;
		}else{
			pause = false;
		}

		if (KEYS[SDL_SCANCODE_P]){
			sim.generateRandomPinField();
		}

		if (KEYS[SDL_SCANCODE_S]){
			rlAgent->savePoliciesToFile();
		}

	}
}

bool PinballBot::preventStablePositionsOutsideCF(Simulation &sim){
	if(sim.isPlayingBallInsideCaptureFrame()){

		stepStartedBeingOutsideCF = 0;
		return true;
	}else{
		if(stepStartedBeingOutsideCF == 0){
			//when does the ball leave the CF
			stepStartedBeingOutsideCF		= steps;
		}else{
			//if it stays out of it for too long, respawn it
			if((steps - stepStartedBeingOutsideCF) > OUTSIDE_CF_UNTIL_RESPAWN){
				printf("The ball was outside the capture frame for too long, respawn!\n");
				sim.debugPlayingBall();
				sim.respawnBall();

				stepStartedBeingOutsideCF = 0;
			}
		}

		return false;
	}
}

void PinballBot::runSimulation(){

	Simulation 										sim;
	SDL_Event										e;

	std::vector<Action*> availableActions			= ActionsSim::actionsAvailable(sim);

	Agent											agent(availableActions);
	rlAgent											= &agent;

	if(RENDER){
		renderer			= new Renderer(320, 640, sim.getWorld());
	}

	while(!quit){

		if(RENDER){
			handleKeys(sim, e);
		}

		if(!pause){

			sim.step(TIME_STEP);

			//Ignore default rewards
			if(sim.reward != Action::DEFAULT_REWARD){
				rewardsCollected.push_back(sim.reward);
			}

			if(sim.reward == 0.0f){
				gameOvers++;
			}

			if(preventStablePositionsOutsideCF(sim)){
				rlAgent->think(sim.getCurrentState(availableActions), rewardsCollected);
				statsRewardsCollected += std::accumulate(rewardsCollected.begin(), rewardsCollected.end(), 0.0f);
				rewardsCollected.clear();
			}

			if(RENDER){
				renderer->render();
				capFramerate();
			}

		}else{
			nextTime = SDL_GetTicks() + TICK_INTERVAL;
		}

		if(steps != 0){
			if(steps % LOG_INTERVAL  == 0){
				printf("step #%lld | amount of states: %ld\n", steps, rlAgent->states.size());

				if(steps % STATS_INTERVAL == 0){
					statsLogger.log(STATS_FILE);

					statsRewardsCollected = 0;
					gameOvers = 0;

					if(steps % SAVE_INTERVAL == 0){
						rlAgent->savePoliciesToFile();
					}
				}

			}
		}
		steps++;
	}
}

void PinballBot::shutdownHook(){
	rlAgent->savePoliciesToFile(); //doesn't work yet, vector empty :/

	//archive previous log file
	statsLogger.archiveLog(STATS_FILE);
}

std::string PinballBot::logSteps(){
	return std::to_string(steps);
}

std::string PinballBot::logTime(){
	return std::to_string(std::time(nullptr));
}

std::string PinballBot::logAmountOfStates(){
	return std::to_string(rlAgent->states.size());
}

std::string PinballBot::logAverageTimePerLoop(){
	return std::to_string(( ((double)(std::time(nullptr) - timeLastLog)) / ( (double)SAVE_INTERVAL) ));
}

std::string PinballBot::logRewardsCollected(){
	return std::to_string(statsRewardsCollected);
}

std::string PinballBot::logGameOvers(){
	return std::to_string(gameOvers);
}

void initLogFile(){
	std::ofstream statsFile;
	statsFile.open(PinballBot::STATS_FILE);
	statsFile << "STEPS;TIME;AMOUNT_OF_STATES;AVERAGE_TIME_PER_LOOP;REWARDS_COLLECTED;GAMEOVERS" << std::endl;
}

int main(int argc, char** argv) {

	PinballBot bot;

	//atexit(shutdownHook);

	if(PinballBot::SIMULATION){
		bot.runSimulation();
	}

	return 0;
}
<commit_msg>Fixed stats error<commit_after>//============================================================================
// Name        : PinballBot.cpp
// Author      : Nico Hauser, David Schmid
// Version     : 0.1
// Description : A reinforcement learning agent that learns to play pinball
//============================================================================

#include <stdlib.h>     /* atexit */
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <numeric>
#include <ctime>

#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>

#include "PinballBot.h"

#include "action/ActionsSim.cpp"

#include "sim/Simulation.h"
#include "sim/Renderer.h"

#include "agent/Agent.h"
#include "agent/State.h"

#include "stats/StatsLogger.h"

const bool						PinballBot::SIMULATION					= true;

const bool						PinballBot::RENDER						= false;
const float						PinballBot::FPS							= 60.0f;
const float						PinballBot::TIME_STEP					= 1.0f / FPS;
const float						PinballBot::TICK_INTERVAL				= 1000.0f / FPS;

const unsigned long long		PinballBot::SAVE_INTERVAL				= 100000;
const unsigned long long		PinballBot::STATS_INTERVAL				= 50000;
const unsigned long long		PinballBot::LOG_INTERVAL				= 10000;
const unsigned long long		PinballBot::OUTSIDE_CF_UNTIL_RESPAWN	= 1800;//1 step ≈ 1/60 sec in-game, 1800 steps ≈ 30 secs in-game

const std::string				PinballBot::STATS_FILE					= "stats.csv";
const std::string				PinballBot::POLICIES_FILE				= "policies.csv";

PinballBot::PinballBot() : statsLogger(), rewardsCollected(0, 0.0f){

	KEYS							= SDL_GetKeyboardState(NULL);

	pause							= false;
	quit							= false;

	nextTime						= 0;

	steps							= 0;
	statsRewardsCollected			= 0;
	timeLastLog						= std::time(nullptr);
	gameOvers						= 0;

	stepStartedBeingOutsideCF		= 0;

	rlAgent							= nullptr;
	renderer						= nullptr;

	statsLogger.registerLoggingColumn("STEPS",					std::bind(&PinballBot::logSteps, this));
	statsLogger.registerLoggingColumn("TIME",					std::bind(&PinballBot::logTime, this));
	statsLogger.registerLoggingColumn("AMOUNT_OF_STATES",		std::bind(&PinballBot::logAmountOfStates, this));
	statsLogger.registerLoggingColumn("AVERAGE_TIME_PER_LOOP",	std::bind(&PinballBot::logAverageTimePerLoop, this));
	statsLogger.registerLoggingColumn("REWARDS_COLLECTED",		std::bind(&PinballBot::logRewardsCollected, this));
	statsLogger.registerLoggingColumn("GAMEOVERS",				std::bind(&PinballBot::logGameOvers, this));

	statsLogger.initLog(STATS_FILE);
}

Uint32 PinballBot::timeLeft() {
    Uint32 now = SDL_GetTicks();

    if(nextTime <= now){
    	return 0;
    }else{
    	return nextTime - now;
    }
}

void PinballBot::capFramerate() {
	SDL_Delay(timeLeft());
	nextTime += TICK_INTERVAL;
}

void PinballBot::handleKeys(Simulation &sim, SDL_Event &e){
	while( SDL_PollEvent( &e ) != 0 ){
		if( e.type == SDL_QUIT ){
			quit = true;
		}

		if (KEYS[SDL_SCANCODE_LEFT]){
			sim.enableLeftFlipper();
		}else{
			sim.disableLeftFlipper();
		}

		if (KEYS[SDL_SCANCODE_RIGHT]){
			sim.enableRightFlipper();
		}else{
			sim.disableRightFlipper();
		}

		if (KEYS[SDL_SCANCODE_SPACE]){
			pause = true;
		}else{
			pause = false;
		}

		if (KEYS[SDL_SCANCODE_P]){
			sim.generateRandomPinField();
		}

		if (KEYS[SDL_SCANCODE_S]){
			rlAgent->savePoliciesToFile();
		}

	}
}

bool PinballBot::preventStablePositionsOutsideCF(Simulation &sim){
	if(sim.isPlayingBallInsideCaptureFrame()){

		stepStartedBeingOutsideCF = 0;
		return true;
	}else{
		if(stepStartedBeingOutsideCF == 0){
			//when does the ball leave the CF
			stepStartedBeingOutsideCF		= steps;
		}else{
			//if it stays out of it for too long, respawn it
			if((steps - stepStartedBeingOutsideCF) > OUTSIDE_CF_UNTIL_RESPAWN){
				printf("The ball was outside the capture frame for too long, respawn!\n");
				sim.debugPlayingBall();
				sim.respawnBall();

				stepStartedBeingOutsideCF = 0;
			}
		}

		return false;
	}
}

void PinballBot::runSimulation(){

	Simulation 										sim;
	SDL_Event										e;

	std::vector<Action*> availableActions			= ActionsSim::actionsAvailable(sim);

	Agent											agent(availableActions);
	rlAgent											= &agent;

	if(RENDER){
		renderer			= new Renderer(320, 640, sim.getWorld());
	}

	while(!quit){

		if(RENDER){
			handleKeys(sim, e);
		}

		if(!pause){

			sim.step(TIME_STEP);

			//Ignore default rewards
			if(sim.reward != Action::DEFAULT_REWARD){
				rewardsCollected.push_back(sim.reward);
			}

			if(sim.reward == 0.0f){
				gameOvers++;
			}

			if(preventStablePositionsOutsideCF(sim)){
				rlAgent->think(sim.getCurrentState(availableActions), rewardsCollected);
				statsRewardsCollected += std::accumulate(rewardsCollected.begin(), rewardsCollected.end(), 0.0f);
				rewardsCollected.clear();
			}

			if(RENDER){
				renderer->render();
				capFramerate();
			}

		}else{
			nextTime = SDL_GetTicks() + TICK_INTERVAL;
		}

		if(steps != 0){
			if(steps % LOG_INTERVAL  == 0){
				printf("step #%lld | amount of states: %ld\n", steps, rlAgent->states.size());

				if(steps % STATS_INTERVAL == 0){
					statsLogger.log(STATS_FILE);

					statsRewardsCollected = 0;
					gameOvers = 0;

					if(steps % SAVE_INTERVAL == 0){
						rlAgent->savePoliciesToFile();
					}
				}

			}
		}
		steps++;
	}
}

void PinballBot::shutdownHook(){
	rlAgent->savePoliciesToFile(); //doesn't work yet, vector empty :/

	//archive previous log file
	statsLogger.archiveLog(STATS_FILE);
}

std::string PinballBot::logSteps(){
	return std::to_string(steps);
}

std::string PinballBot::logTime(){
	timeLastLog = std::time(nullptr);
	return std::to_string(timeLastLog);
}

std::string PinballBot::logAmountOfStates(){
	return std::to_string(rlAgent->states.size());
}

std::string PinballBot::logAverageTimePerLoop(){
	return std::to_string(( ((double)(std::time(nullptr) - timeLastLog)) / ( (double)SAVE_INTERVAL) ));
}

std::string PinballBot::logRewardsCollected(){
	return std::to_string(statsRewardsCollected);
}

std::string PinballBot::logGameOvers(){
	return std::to_string(gameOvers);
}

void initLogFile(){
	std::ofstream statsFile;
	statsFile.open(PinballBot::STATS_FILE);
	statsFile << "STEPS;TIME;AMOUNT_OF_STATES;AVERAGE_TIME_PER_LOOP;REWARDS_COLLECTED;GAMEOVERS" << std::endl;
}

int main(int argc, char** argv) {

	PinballBot bot;

	//atexit(shutdownHook);

	if(PinballBot::SIMULATION){
		bot.runSimulation();
	}

	return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include <TextReport.h>
#include <iostream>
#include <sstream>
#include <Report.h>
#include <Result.h>
#include <Test.h>

using namespace std;
using namespace oout;

class TextReportStream final : public Report {
public:
	void preamble()
	{
		// @todo #57:15min Test counts show in preample
		text << "[==========] Running" << endl;
	}

	void begin(const string &tag, const map<string, string> &attributes) override
	{
		if (tag == "testcase") {
			text << "[ RUN      ] " << attributes.at("name") << endl;
			if (attributes.at("failures") == "0") {
				text << "[       OK ] ";
			} else {
				text << "[  FAILED  ] ";
			}
			text << attributes.at("name") << endl;
		} else {
			// @todo #53:15min gtest text format for "cases"
			text << tag << ": ";
			for (const auto &ap : attributes) {
				text << ap.first << "='" << ap.second << "' ";
			}
			text << endl;
		}
	}
	void end(const string &) override
	{
	}

	// @todo #57:15min format portscrips and status
	string asString() const
	{
		return text.str();
	}

private:
	ostringstream text;
};

TextReport::TextReport(const std::shared_ptr<const Result> &result)
	: result(result)
{
}

string TextReport::asString() const
{
	TextReportStream rep;
	rep.preamble();
	result->print(&rep);
	return rep.asString();
}
<commit_msg>#57: Default ctor for TextReportStream<commit_after>// Copyright (c) 2017 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include <TextReport.h>
#include <iostream>
#include <sstream>
#include <Report.h>
#include <Result.h>
#include <Test.h>

using namespace std;
using namespace oout;

// @todo #57:15min TextReportStream is a bad name
class TextReportStream final : public Report {
public:
	TextReportStream()
		: text()
	{
	}

	void preamble()
	{
		// @todo #57:15min Test counts show in preample
		text << "[==========] Running" << endl;
	}

	void begin(const string &tag, const map<string, string> &attributes) override
	{
		if (tag == "testcase") {
			text << "[ RUN      ] " << attributes.at("name") << endl;
			if (attributes.at("failures") == "0") {
				text << "[       OK ] ";
			} else {
				text << "[  FAILED  ] ";
			}
			text << attributes.at("name") << endl;
		} else {
			// @todo #53:15min gtest text format for "cases"
			text << tag << ": ";
			for (const auto &ap : attributes) {
				text << ap.first << "='" << ap.second << "' ";
			}
			text << endl;
		}
	}
	void end(const string &) override
	{
	}

	// @todo #57:15min format portscrips and status
	string asString() const
	{
		return text.str();
	}

private:
	ostringstream text;
};

TextReport::TextReport(const std::shared_ptr<const Result> &result)
	: result(result)
{
}

string TextReport::asString() const
{
	TextReportStream rep;
	rep.preamble();
	result->print(&rep);
	return rep.asString();
}
<|endoftext|>


<commit_before>#include "TpObserver.h"

TpObserver::TpObserver (const ChannelClassList &channelFilter,
                              QObject          *parent       )
: AbstractClientObserver(channelFilter)
, IObserver (parent)
, id(1) // Always ignore
{
}//TpObserver::TpObserver

void
TpObserver::setId (int i)
{
    id = i;
}//TpObserver::setId

void
TpObserver::startMonitoring (const QString &strC)
{
    strContact = strC;
}//TpObserver::startMonitoring

void
TpObserver::stopMonitoring ()
{
    strContact.clear ();
}//TpObserver::stopMonitoring

void
TpObserver::observeChannels(
        const MethodInvocationContextPtr<> & context,
        const AccountPtr                   & account,
        const ConnectionPtr                & connection,
        const QList <ChannelPtr>           & channels,
        const ChannelDispatchOperationPtr  & dispatchOperation,
        const QList <ChannelRequestPtr>    & requestsSatisfied,
        const QVariantMap                  & observerInfo)
{
    bool bOk;
    QString msg;
    emit log ("Observer got something!");

    if (strContact.isEmpty ())
    {
        context->setFinished ();
        emit log ("But we weren't asked to notify anything, so go away");
        return;
    }

    msg = QString("There are %1 channels in channels list")
          .arg (channels.size ());
    log (msg);

    foreach (ChannelPtr channel, channels)
    {
        if (!channel->isReady ())
        {
            emit log ("Channel is not ready");

            ChannelAccepter *closer = new ChannelAccepter(context,
                                                          account,
                                                          connection,
                                                          channels,
                                                          dispatchOperation,
                                                          requestsSatisfied,
                                                          observerInfo,
                                                          channel,
                                                          strContact,
                                                          this);
            bOk =
            QObject::connect (
                closer, SIGNAL (log(const QString &, int)),
                this  , SIGNAL (log(const QString &, int)));
            bOk =
            QObject::connect (
                closer, SIGNAL (callStarted ()),
                this  , SIGNAL (callStarted ()));
            closer->init ();
            break;
        }
    }
}//TpObserver::addDispatchOperation

ChannelAccepter::ChannelAccepter (
    const MethodInvocationContextPtr<> & ctx,
    const AccountPtr                   & act,
    const ConnectionPtr                & conn,
    const QList <ChannelPtr>           & chnls,
    const ChannelDispatchOperationPtr  & dispatchOp,
    const QList <ChannelRequestPtr>    & requestsSat,
    const QVariantMap                  & obsInfo,
    const ChannelPtr                     channel,
    const QString                      & strNum,
          QObject                      * parent)
: QObject(parent)
, context (ctx)
, account (act)
, connection (conn)
, channels (chnls)
, dispatchOperation (dispatchOp)
, requestsSatisfied (requestsSat)
, observerInfo (obsInfo)
, currentChannel (channel)
, strCheckNumber (strNum)
, mutex (QMutex::Recursive)
, nRefCount (0)
, bFailure (false)
{
}//ChannelAccepter::ChannelAccepter

bool
ChannelAccepter::init ()
{
    bool bOk;

    PendingReady *pendingReady;
    QMutexLocker locker(&mutex);

    nRefCount ++;   // One for protection

    nRefCount ++;
    pendingReady = connection->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onConnectionReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for connection to become ready");
    }

    nRefCount ++;
    pendingReady = account->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onAccountReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for account to become ready");
    }

    nRefCount ++;
    pendingReady = currentChannel->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onChannelReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for channel to become ready");
    }

    emit log ("All become ready's sent");
    decrefCleanup ();

    return (bOk);
}//ChannelAccepter::init

void
ChannelAccepter::decrefCleanup ()
{
    QMutexLocker locker(&mutex);
    nRefCount--;
    if (0 != nRefCount)
    {
        return;
    }

    emit log ("Everything ready. Cleaning up");

    bool bCleanupLater = false;
    do { // Not a loop
        if (bFailure)
        {
            emit log ("Failed while waiting for something");
            break;
        }

        QString msg;
        msg = QString("Channel type = %1. isRequested = %2")
                .arg (currentChannel->channelType ())
                .arg (currentChannel->isRequested ());
        emit log (msg);

        ContactPtr contact = currentChannel->initiatorContact ();
        msg = QString("Contact id = %1. alias = %2")
               .arg (contact->id ())
               .arg (contact->alias ());
        emit log (msg);

        int interested = 0;
        if (0 == currentChannel->channelType().compare (
                TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA))
        {
            interested++;
        }
        if (!currentChannel->isRequested ())
        {
            interested++;
        }
        if (contact->id ().contains (strCheckNumber))
        {
            interested++;
        }

        if (3 != interested)
        {
            emit log ("Channel that we're not interested in");
            break;
        }

        emit log ("Incoming call from our number!");
        emit callStarted ();
    } while (0); // Not a loop

    if (!bCleanupLater)
    {
        context->setFinished ();
        this->deleteLater ();
    }
}//ChannelAccepter::decrefCleanup

void
ChannelAccepter::onCallAccepted (Tp::PendingOperation *operation)
{
    if (operation->isError ())
    {
        emit log ("Failed to accept call");
    }
    else
    {
        emit log ("Call accepted");
    }
    context->setFinished ();
    this->deleteLater ();
}//ChannelAccepter::onCallAccepted

void
ChannelAccepter::onChannelReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Channel could not become ready");
            bFailure = true;
        }

        if (!currentChannel->isReady ())
        {
            emit log ("Dammit the channel is still not ready");
        }
        else
        {
            emit log ("Channel is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onChannelReady

void
ChannelAccepter::onConnectionReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Connection could not become ready");
            bFailure = true;
        }

        if (!connection->isReady ())
        {
            emit log ("Dammit the connection is still not ready");
        }
        else
        {
            emit log ("Connection is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onConnectionReady

void
ChannelAccepter::onAccountReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Account could not become ready");
            bFailure = true;
        }

        if (!account->isReady ())
        {
            emit log ("Dammit the account is still not ready");
        }
        else
        {
            emit log ("Account is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onAccountReady
<commit_msg>fix one warning<commit_after>#include "TpObserver.h"

TpObserver::TpObserver (const ChannelClassList &channelFilter,
                              QObject          *parent       )
: IObserver (parent)
, AbstractClientObserver(channelFilter)
, id(1) // Always ignore
{
}//TpObserver::TpObserver

void
TpObserver::setId (int i)
{
    id = i;
}//TpObserver::setId

void
TpObserver::startMonitoring (const QString &strC)
{
    strContact = strC;
}//TpObserver::startMonitoring

void
TpObserver::stopMonitoring ()
{
    strContact.clear ();
}//TpObserver::stopMonitoring

void
TpObserver::observeChannels(
        const MethodInvocationContextPtr<> & context,
        const AccountPtr                   & account,
        const ConnectionPtr                & connection,
        const QList <ChannelPtr>           & channels,
        const ChannelDispatchOperationPtr  & dispatchOperation,
        const QList <ChannelRequestPtr>    & requestsSatisfied,
        const QVariantMap                  & observerInfo)
{
    bool bOk;
    QString msg;
    emit log ("Observer got something!");

    if (strContact.isEmpty ())
    {
        context->setFinished ();
        emit log ("But we weren't asked to notify anything, so go away");
        return;
    }

    msg = QString("There are %1 channels in channels list")
          .arg (channels.size ());
    log (msg);

    foreach (ChannelPtr channel, channels)
    {
        if (!channel->isReady ())
        {
            emit log ("Channel is not ready");

            ChannelAccepter *closer = new ChannelAccepter(context,
                                                          account,
                                                          connection,
                                                          channels,
                                                          dispatchOperation,
                                                          requestsSatisfied,
                                                          observerInfo,
                                                          channel,
                                                          strContact,
                                                          this);
            bOk =
            QObject::connect (
                closer, SIGNAL (log(const QString &, int)),
                this  , SIGNAL (log(const QString &, int)));
            bOk =
            QObject::connect (
                closer, SIGNAL (callStarted ()),
                this  , SIGNAL (callStarted ()));
            closer->init ();
            break;
        }
    }
}//TpObserver::addDispatchOperation

ChannelAccepter::ChannelAccepter (
    const MethodInvocationContextPtr<> & ctx,
    const AccountPtr                   & act,
    const ConnectionPtr                & conn,
    const QList <ChannelPtr>           & chnls,
    const ChannelDispatchOperationPtr  & dispatchOp,
    const QList <ChannelRequestPtr>    & requestsSat,
    const QVariantMap                  & obsInfo,
    const ChannelPtr                     channel,
    const QString                      & strNum,
          QObject                      * parent)
: QObject(parent)
, context (ctx)
, account (act)
, connection (conn)
, channels (chnls)
, dispatchOperation (dispatchOp)
, requestsSatisfied (requestsSat)
, observerInfo (obsInfo)
, currentChannel (channel)
, strCheckNumber (strNum)
, mutex (QMutex::Recursive)
, nRefCount (0)
, bFailure (false)
{
}//ChannelAccepter::ChannelAccepter

bool
ChannelAccepter::init ()
{
    bool bOk;

    PendingReady *pendingReady;
    QMutexLocker locker(&mutex);

    nRefCount ++;   // One for protection

    nRefCount ++;
    pendingReady = connection->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onConnectionReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for connection to become ready");
    }

    nRefCount ++;
    pendingReady = account->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onAccountReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for account to become ready");
    }

    nRefCount ++;
    pendingReady = currentChannel->becomeReady ();
    bOk =
    QObject::connect (
        pendingReady, SIGNAL (finished (Tp::PendingOperation *)),
        this        , SLOT   (onChannelReady (Tp::PendingOperation *)));
    if (bOk)
    {
        emit log ("Waiting for channel to become ready");
    }

    emit log ("All become ready's sent");
    decrefCleanup ();

    return (bOk);
}//ChannelAccepter::init

void
ChannelAccepter::decrefCleanup ()
{
    QMutexLocker locker(&mutex);
    nRefCount--;
    if (0 != nRefCount)
    {
        return;
    }

    emit log ("Everything ready. Cleaning up");

    bool bCleanupLater = false;
    do { // Not a loop
        if (bFailure)
        {
            emit log ("Failed while waiting for something");
            break;
        }

        QString msg;
        msg = QString("Channel type = %1. isRequested = %2")
                .arg (currentChannel->channelType ())
                .arg (currentChannel->isRequested ());
        emit log (msg);

        ContactPtr contact = currentChannel->initiatorContact ();
        msg = QString("Contact id = %1. alias = %2")
               .arg (contact->id ())
               .arg (contact->alias ());
        emit log (msg);

        int interested = 0;
        if (0 == currentChannel->channelType().compare (
                TELEPATHY_INTERFACE_CHANNEL_TYPE_STREAMED_MEDIA))
        {
            interested++;
        }
        if (!currentChannel->isRequested ())
        {
            interested++;
        }
        if (contact->id ().contains (strCheckNumber))
        {
            interested++;
        }

        if (3 != interested)
        {
            emit log ("Channel that we're not interested in");
            break;
        }

        emit log ("Incoming call from our number!");
        emit callStarted ();
    } while (0); // Not a loop

    if (!bCleanupLater)
    {
        context->setFinished ();
        this->deleteLater ();
    }
}//ChannelAccepter::decrefCleanup

void
ChannelAccepter::onCallAccepted (Tp::PendingOperation *operation)
{
    if (operation->isError ())
    {
        emit log ("Failed to accept call");
    }
    else
    {
        emit log ("Call accepted");
    }
    context->setFinished ();
    this->deleteLater ();
}//ChannelAccepter::onCallAccepted

void
ChannelAccepter::onChannelReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Channel could not become ready");
            bFailure = true;
        }

        if (!currentChannel->isReady ())
        {
            emit log ("Dammit the channel is still not ready");
        }
        else
        {
            emit log ("Channel is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onChannelReady

void
ChannelAccepter::onConnectionReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Connection could not become ready");
            bFailure = true;
        }

        if (!connection->isReady ())
        {
            emit log ("Dammit the connection is still not ready");
        }
        else
        {
            emit log ("Connection is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onConnectionReady

void
ChannelAccepter::onAccountReady (Tp::PendingOperation *operation)
{
    do { // Not a loop
        if (operation->isError ())
        {
            emit log ("Account could not become ready");
            bFailure = true;
        }

        if (!account->isReady ())
        {
            emit log ("Dammit the account is still not ready");
        }
        else
        {
            emit log ("Account is ready");
        }

        decrefCleanup ();
    } while (0); // Not a loop
    operation->deleteLater ();
}//ChannelAccepter::onAccountReady
<|endoftext|>


<commit_before>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
 *
 * This library 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 library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "accessible.h"

#include <QDBusPendingReply>
#include <QDebug>
#include <QtGui/QWidget>

#include <QAccessibleValueInterface>

#include "adaptor.h"
#include "bridge.h"
#include "cache.h"
#include "constant_mappings.h"

#include "generated/accessible_adaptor.h"
#include "generated/action_adaptor.h"
#include "generated/component_adaptor.h"
#include "generated/editable_text_adaptor.h"
#include "generated/event_adaptor.h"
#include "generated/socket_proxy.h"
#include "generated/table_adaptor.h"
#include "generated/text_adaptor.h"
#include "generated/value_adaptor.h"

#define ACCESSIBLE_CREATION_DEBUG

#define QSPI_REGISTRY_NAME "org.a11y.atspi.Registry"

QString QSpiAccessible::pathForObject(QObject *object)
{
    Q_ASSERT(object);
    return QSPI_OBJECT_PATH_PREFIX + QString::number(reinterpret_cast<size_t>(object));
}

QString QSpiAccessible::pathForInterface(QAccessibleInterface *interface, int childIndex)
{
    QString path;
    QAccessibleInterface* interfaceWithObject = interface;
    while(!interfaceWithObject->object()) {
        QAccessibleInterface* parentInterface;
        interfaceWithObject->navigate(QAccessible::Ancestor, 1, &parentInterface);
        Q_ASSERT(parentInterface->isValid());
        int index = parentInterface->indexOfChild(interfaceWithObject);
        //Q_ASSERT(index >= 0);
        // FIXME: This should never happen!
        if (index < 0) {

            index = 999;
            path.prepend("/BROKEN_OBJECT_HIERARCHY");
            qWarning() << "Object claims to have child that we cannot navigate to. FIX IT!" << parentInterface->object();

            qDebug() << "Original interface: " << interface->object() << index;
            qDebug() << "Parent interface: " << parentInterface->object() << " childcount:" << parentInterface->childCount();
            QObject* p = parentInterface->object();
            qDebug() << p->children();

            QAccessibleInterface* tttt;
            int id = parentInterface->navigate(QAccessible::Child, 1, &tttt);
            qDebug() << "Nav child: " << id << tttt->object();
        }
        path.prepend('/' + QString::number(index));
        interfaceWithObject = parentInterface;
    }
    path.prepend(QSPI_OBJECT_PATH_PREFIX + QString::number(reinterpret_cast<quintptr>(interfaceWithObject->object())));

    if (childIndex > 0) {
        path.append('/' + QString::number(childIndex));
    }
    return path;
}

QPair<QAccessibleInterface*, int> QSpiAccessible::interfaceFromPath(const QString& dbusPath)
{
    QStringList parts = dbusPath.split('/');

    Q_ASSERT(parts.size() > 5);

    // ignore the first /org/a11y/atspi/accessible/
    QString objectString = parts.at(5);

    quintptr uintptr = objectString.toULongLong();

    if (!uintptr)
        return QPair<QAccessibleInterface*, int>(0, 0);

    QObject* object = reinterpret_cast<QObject*>(uintptr);

    qDebug() << object;
    QAccessibleInterface* inter = QAccessible::queryAccessibleInterface(object);
    QAccessibleInterface* childInter;

    int index = 0;

    for (int i = 6; i < parts.size(); ++i) {
        index = inter->navigate(QAccessible::Child, parts.at(i).toInt(), &childInter);
        if (index == 0) {
            delete inter;
            inter = childInter;
        }
    }

    return QPair<QAccessibleInterface*, int>(inter, index);
}

QSpiAccessible::QSpiAccessible(QAccessibleInterface *interface, int index)
    : QSpiAdaptor(interface, index)
{
    QString path = pathForInterface(interface, index);
    QDBusObjectPath dbusPath = QDBusObjectPath(path);

    reference = QSpiObjectReference(spiBridge->dBusConnection(),
                                               dbusPath);
#ifdef ACCESSIBLE_CREATION_DEBUG
    qDebug() << "ACCESSIBLE: " << interface->object() << reference.path.path() << interface->text(QAccessible::Name, index) << qSpiRoleMapping[interface->role(index)].name();
#endif

    new AccessibleAdaptor(this);
    supportedInterfaces << QSPI_INTERFACE_ACCESSIBLE;

    if (    (!interface->rect(index).isEmpty()) ||
            (interface->object() && interface->object()->isWidgetType()) ||
            (interface->role(index) == QAccessible::ListItem) ||
            (interface->role(index) == QAccessible::Cell) ||
            (interface->role(index) == QAccessible::TreeItem) ||
            (interface->role(index) == QAccessible::Row) ||
            (interface->object() && interface->object()->inherits("QSGItem"))
            ) {
        new ComponentAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_COMPONENT;

        if (interface->object() && interface->object()->isWidgetType()) {
            QWidget *w = qobject_cast<QWidget*>(interface->object());
            if (w->isWindow()) {
                new WindowAdaptor(this);
#ifdef ACCESSIBLE_CREATION_DEBUG
                qDebug() << " IS a window";
#endif
            }
        }
    }
#ifdef ACCESSIBLE_CREATION_DEBUG
    else {
        qDebug() << " IS NOT a component";
    }
#endif

    new ObjectAdaptor(this);
    new FocusAdaptor(this);

    if (interface->actionInterface())
    {
        new ActionAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_ACTION;
    }
    if (interface->textInterface())
    {
        new TextAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_TEXT;
        oldText = interface->textInterface()->text(0, interface->textInterface()->characterCount());
    }
    if (interface->editableTextInterface())
    {
        new EditableTextAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_EDITABLE_TEXT;
    }
    if (interface->valueInterface())
    {
        new ValueAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_VALUE;
    }
    if (interface->table2Interface())
    {
        new TableAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_TABLE;
    }

    spiBridge->dBusConnection().registerObject(reference.path.path(),
                                  this, QDBusConnection::ExportAdaptors);
    state = interface->state(childIndex());
}

QSpiObjectReference QSpiAccessible::getParentReference() const
{
    Q_ASSERT(interface);

    if (interface->isValid()) {
        QAccessibleInterface *parentInterface = 0;
        interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
        if (parentInterface) {
            QSpiAdaptor *parent = spiBridge->objectToAccessible(parentInterface->object());
            delete parentInterface;
            if (parent)
                return parent->getReference();
        }
    }
    qWarning() << "Invalid parent: " << interface << interface->object();
    return QSpiObjectReference();
}

void QSpiAccessible::accessibleEvent(QAccessible::Event event)
{
    Q_ASSERT(interface);
    if (!interface->isValid()) {
        spiBridge->removeAdaptor(this);
        return;
    }

    switch (event) {
    case QAccessible::NameChanged: {
        QSpiObjectReference r = getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        emit PropertyChange("accessible-name", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::DescriptionChanged: {
        QSpiObjectReference r = getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        emit PropertyChange("accessible-description", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::Focus: {

        qDebug() << "Focus: " << getReference().path.path() << interface->object() << interface->text(QAccessible::Name, 0);

        QDBusVariant data;
        data.setVariant(QVariant::fromValue(getReference()));
        emit StateChanged("focused", 1, 0, data, spiBridge->getRootReference());
        emit Focus("", 0, 0, data, spiBridge->getRootReference());
        break;
    }
#if (QT_VERSION >= QT_VERSION_CHECK(4, 8, 0))
    case QAccessible::TextUpdated: {
        Q_ASSERT(interface->textInterface());

        // at-spi doesn't have a proper text updated/changed, so remove all and re-add the new text
        qDebug() << "Text changed: " << interface->object();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(oldText));
        emit TextChanged("delete", 0, oldText.length(), data, spiBridge->getRootReference());

        QString text = interface->textInterface()->text(0, interface->textInterface()->characterCount());
        data.setVariant(QVariant::fromValue(text));
        emit TextChanged("insert", 0, text.length(), data, spiBridge->getRootReference());
        oldText = text;

        QDBusVariant cursorData;
        int pos = interface->textInterface()->cursorPosition();
        cursorData.setVariant(QVariant::fromValue(pos));
        emit TextCaretMoved(QString(), pos ,0, cursorData, spiBridge->getRootReference());
        break;
    }
    case QAccessible::TextCaretMoved: {
        Q_ASSERT(interface->textInterface());
        qDebug() << "Text caret moved: " << interface->object();
        QDBusVariant data;
        int pos = interface->textInterface()->cursorPosition();
        data.setVariant(QVariant::fromValue(pos));
        emit TextCaretMoved(QString(), pos ,0, data, spiBridge->getRootReference());
        break;
    }
#endif
    case QAccessible::ValueChanged: {
        Q_ASSERT(interface->valueInterface());
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(getReference()));
        emit PropertyChange("accessible-value", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::ObjectShow:
        break;
    case QAccessible::ObjectHide:
        // TODO - send status changed
//        qWarning() << "Object hide";
        break;
    case QAccessible::ObjectDestroyed:
        // TODO - maybe send children-changed and cache Removed
//        qWarning() << "Object destroyed";
        break;
    case QAccessible::StateChanged: {
        QAccessible::State newState = interface->state(childIndex());
//        qDebug() << "StateChanged: old: " << state << " new: " << newState << " xor: " << (state^newState);
        if ((state^newState) & QAccessible::Checked) {
            int checked = (newState & QAccessible::Checked) ? 1 : 0;
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(getReference()));
            emit StateChanged("checked", checked, 0, data, spiBridge->getRootReference());
        }
        state = newState;
        break;
    }
    case QAccessible::TableModelChanged: {
        // This is rather evil. We don't send data and hope that at-spi fetches the right child.
        // This hack fails when a row gets removed and a different one added in its place.
        QDBusVariant data;
        emit ChildrenChanged("add", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::ParentChanged:
        // TODO - send parent changed
    default:
//        qWarning() << "QSpiAccessible::accessibleEvent not handled: " << QString::number(event, 16)
//                   << " obj: " << interface->object()
//                   << (interface->isValid() ? interface->object()->objectName() : " invalid interface!");
        break;
    }
}

void QSpiAccessible::windowActivated()
{
    QDBusVariant data;
    data.setVariant(QString());
    emit Create("", 0, 0, data, spiBridge->getRootReference());
    emit Restore("", 0, 0, data, spiBridge->getRootReference());
    emit Activate("", 0, 0, data, spiBridge->getRootReference());
}
<commit_msg>Row/column headers are components.<commit_after>/*
 * D-Bus AT-SPI, Qt Adaptor
 *
 * Copyright 2009-2011 Nokia Corporation and/or its subsidiary(-ies).
 *
 * This library 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 library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "accessible.h"

#include <QDBusPendingReply>
#include <QDebug>
#include <QtGui/QWidget>

#include <QAccessibleValueInterface>

#include "adaptor.h"
#include "bridge.h"
#include "cache.h"
#include "constant_mappings.h"

#include "generated/accessible_adaptor.h"
#include "generated/action_adaptor.h"
#include "generated/component_adaptor.h"
#include "generated/editable_text_adaptor.h"
#include "generated/event_adaptor.h"
#include "generated/socket_proxy.h"
#include "generated/table_adaptor.h"
#include "generated/text_adaptor.h"
#include "generated/value_adaptor.h"

#define ACCESSIBLE_CREATION_DEBUG

#define QSPI_REGISTRY_NAME "org.a11y.atspi.Registry"

QString QSpiAccessible::pathForObject(QObject *object)
{
    Q_ASSERT(object);
    return QSPI_OBJECT_PATH_PREFIX + QString::number(reinterpret_cast<size_t>(object));
}

QString QSpiAccessible::pathForInterface(QAccessibleInterface *interface, int childIndex)
{
    QString path;
    QAccessibleInterface* interfaceWithObject = interface;
    while(!interfaceWithObject->object()) {
        QAccessibleInterface* parentInterface;
        interfaceWithObject->navigate(QAccessible::Ancestor, 1, &parentInterface);
        Q_ASSERT(parentInterface->isValid());
        int index = parentInterface->indexOfChild(interfaceWithObject);
        //Q_ASSERT(index >= 0);
        // FIXME: This should never happen!
        if (index < 0) {

            index = 999;
            path.prepend("/BROKEN_OBJECT_HIERARCHY");
            qWarning() << "Object claims to have child that we cannot navigate to. FIX IT!" << parentInterface->object();

            qDebug() << "Original interface: " << interface->object() << index;
            qDebug() << "Parent interface: " << parentInterface->object() << " childcount:" << parentInterface->childCount();
            QObject* p = parentInterface->object();
            qDebug() << p->children();

            QAccessibleInterface* tttt;
            int id = parentInterface->navigate(QAccessible::Child, 1, &tttt);
            qDebug() << "Nav child: " << id << tttt->object();
        }
        path.prepend('/' + QString::number(index));
        interfaceWithObject = parentInterface;
    }
    path.prepend(QSPI_OBJECT_PATH_PREFIX + QString::number(reinterpret_cast<quintptr>(interfaceWithObject->object())));

    if (childIndex > 0) {
        path.append('/' + QString::number(childIndex));
    }
    return path;
}

QPair<QAccessibleInterface*, int> QSpiAccessible::interfaceFromPath(const QString& dbusPath)
{
    QStringList parts = dbusPath.split('/');

    Q_ASSERT(parts.size() > 5);

    // ignore the first /org/a11y/atspi/accessible/
    QString objectString = parts.at(5);

    quintptr uintptr = objectString.toULongLong();

    if (!uintptr)
        return QPair<QAccessibleInterface*, int>(0, 0);

    QObject* object = reinterpret_cast<QObject*>(uintptr);

    qDebug() << object;
    QAccessibleInterface* inter = QAccessible::queryAccessibleInterface(object);
    QAccessibleInterface* childInter;

    int index = 0;

    for (int i = 6; i < parts.size(); ++i) {
        index = inter->navigate(QAccessible::Child, parts.at(i).toInt(), &childInter);
        if (index == 0) {
            delete inter;
            inter = childInter;
        }
    }

    return QPair<QAccessibleInterface*, int>(inter, index);
}

QSpiAccessible::QSpiAccessible(QAccessibleInterface *interface, int index)
    : QSpiAdaptor(interface, index)
{
    QString path = pathForInterface(interface, index);
    QDBusObjectPath dbusPath = QDBusObjectPath(path);

    reference = QSpiObjectReference(spiBridge->dBusConnection(),
                                               dbusPath);
#ifdef ACCESSIBLE_CREATION_DEBUG
    qDebug() << "ACCESSIBLE: " << interface->object() << reference.path.path() << interface->text(QAccessible::Name, index) << qSpiRoleMapping[interface->role(index)].name();
#endif

    new AccessibleAdaptor(this);
    supportedInterfaces << QSPI_INTERFACE_ACCESSIBLE;

    if (    (!interface->rect(index).isEmpty()) ||
            (interface->object() && interface->object()->isWidgetType()) ||
            (interface->role(index) == QAccessible::ListItem) ||
            (interface->role(index) == QAccessible::Cell) ||
            (interface->role(index) == QAccessible::TreeItem) ||
            (interface->role(index) == QAccessible::Row) ||
            (interface->role(index) == QAccessible::RowHeader) ||
            (interface->role(index) == QAccessible::ColumnHeader) ||
            (interface->object() && interface->object()->inherits("QSGItem"))
            ) {
        new ComponentAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_COMPONENT;

        if (interface->object() && interface->object()->isWidgetType()) {
            QWidget *w = qobject_cast<QWidget*>(interface->object());
            if (w->isWindow()) {
                new WindowAdaptor(this);
#ifdef ACCESSIBLE_CREATION_DEBUG
                qDebug() << " IS a window";
#endif
            }
        }
    }
#ifdef ACCESSIBLE_CREATION_DEBUG
    else {
        qDebug() << " IS NOT a component";
    }
#endif

    new ObjectAdaptor(this);
    new FocusAdaptor(this);

    if (interface->actionInterface())
    {
        new ActionAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_ACTION;
    }
    if (interface->textInterface())
    {
        new TextAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_TEXT;
        oldText = interface->textInterface()->text(0, interface->textInterface()->characterCount());
    }
    if (interface->editableTextInterface())
    {
        new EditableTextAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_EDITABLE_TEXT;
    }
    if (interface->valueInterface())
    {
        new ValueAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_VALUE;
    }
    if (interface->table2Interface())
    {
        new TableAdaptor(this);
        supportedInterfaces << QSPI_INTERFACE_TABLE;
    }

    spiBridge->dBusConnection().registerObject(reference.path.path(),
                                  this, QDBusConnection::ExportAdaptors);
    state = interface->state(childIndex());
}

QSpiObjectReference QSpiAccessible::getParentReference() const
{
    Q_ASSERT(interface);

    if (interface->isValid()) {
        QAccessibleInterface *parentInterface = 0;
        interface->navigate(QAccessible::Ancestor, 1, &parentInterface);
        if (parentInterface) {
            QSpiAdaptor *parent = spiBridge->objectToAccessible(parentInterface->object());
            delete parentInterface;
            if (parent)
                return parent->getReference();
        }
    }
    qWarning() << "Invalid parent: " << interface << interface->object();
    return QSpiObjectReference();
}

void QSpiAccessible::accessibleEvent(QAccessible::Event event)
{
    Q_ASSERT(interface);
    if (!interface->isValid()) {
        spiBridge->removeAdaptor(this);
        return;
    }

    switch (event) {
    case QAccessible::NameChanged: {
        QSpiObjectReference r = getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        emit PropertyChange("accessible-name", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::DescriptionChanged: {
        QSpiObjectReference r = getReference();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(r));
        emit PropertyChange("accessible-description", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::Focus: {

        qDebug() << "Focus: " << getReference().path.path() << interface->object() << interface->text(QAccessible::Name, 0);

        QDBusVariant data;
        data.setVariant(QVariant::fromValue(getReference()));
        emit StateChanged("focused", 1, 0, data, spiBridge->getRootReference());
        emit Focus("", 0, 0, data, spiBridge->getRootReference());
        break;
    }
#if (QT_VERSION >= QT_VERSION_CHECK(4, 8, 0))
    case QAccessible::TextUpdated: {
        Q_ASSERT(interface->textInterface());

        // at-spi doesn't have a proper text updated/changed, so remove all and re-add the new text
        qDebug() << "Text changed: " << interface->object();
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(oldText));
        emit TextChanged("delete", 0, oldText.length(), data, spiBridge->getRootReference());

        QString text = interface->textInterface()->text(0, interface->textInterface()->characterCount());
        data.setVariant(QVariant::fromValue(text));
        emit TextChanged("insert", 0, text.length(), data, spiBridge->getRootReference());
        oldText = text;

        QDBusVariant cursorData;
        int pos = interface->textInterface()->cursorPosition();
        cursorData.setVariant(QVariant::fromValue(pos));
        emit TextCaretMoved(QString(), pos ,0, cursorData, spiBridge->getRootReference());
        break;
    }
    case QAccessible::TextCaretMoved: {
        Q_ASSERT(interface->textInterface());
        qDebug() << "Text caret moved: " << interface->object();
        QDBusVariant data;
        int pos = interface->textInterface()->cursorPosition();
        data.setVariant(QVariant::fromValue(pos));
        emit TextCaretMoved(QString(), pos ,0, data, spiBridge->getRootReference());
        break;
    }
#endif
    case QAccessible::ValueChanged: {
        Q_ASSERT(interface->valueInterface());
        QDBusVariant data;
        data.setVariant(QVariant::fromValue(getReference()));
        emit PropertyChange("accessible-value", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::ObjectShow:
        break;
    case QAccessible::ObjectHide:
        // TODO - send status changed
//        qWarning() << "Object hide";
        break;
    case QAccessible::ObjectDestroyed:
        // TODO - maybe send children-changed and cache Removed
//        qWarning() << "Object destroyed";
        break;
    case QAccessible::StateChanged: {
        QAccessible::State newState = interface->state(childIndex());
//        qDebug() << "StateChanged: old: " << state << " new: " << newState << " xor: " << (state^newState);
        if ((state^newState) & QAccessible::Checked) {
            int checked = (newState & QAccessible::Checked) ? 1 : 0;
            QDBusVariant data;
            data.setVariant(QVariant::fromValue(getReference()));
            emit StateChanged("checked", checked, 0, data, spiBridge->getRootReference());
        }
        state = newState;
        break;
    }
    case QAccessible::TableModelChanged: {
        // This is rather evil. We don't send data and hope that at-spi fetches the right child.
        // This hack fails when a row gets removed and a different one added in its place.
        QDBusVariant data;
        emit ChildrenChanged("add", 0, 0, data, spiBridge->getRootReference());
        break;
    }
    case QAccessible::ParentChanged:
        // TODO - send parent changed
    default:
//        qWarning() << "QSpiAccessible::accessibleEvent not handled: " << QString::number(event, 16)
//                   << " obj: " << interface->object()
//                   << (interface->isValid() ? interface->object()->objectName() : " invalid interface!");
        break;
    }
}

void QSpiAccessible::windowActivated()
{
    QDBusVariant data;
    data.setVariant(QString());
    emit Create("", 0, 0, data, spiBridge->getRootReference());
    emit Restore("", 0, 0, data, spiBridge->getRootReference());
    emit Activate("", 0, 0, data, spiBridge->getRootReference());
}
<|endoftext|>


<commit_before>
#include "VM.h"

#include <libevm/VMFace.h>

#include "ExecutionEngine.h"
#include "Compiler.h"

namespace dev
{
namespace eth
{
namespace jit
{

bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
	auto module = Compiler().compile(_ext.code);

	ExecutionEngine engine;
	auto exitCode = engine.run(std::move(module), m_gas, &_ext);

	switch (exitCode)
	{
	case 101:
		BOOST_THROW_EXCEPTION(BadJumpDestination());
	case 102:
		BOOST_THROW_EXCEPTION(OutOfGas());
	case 103:
		BOOST_THROW_EXCEPTION(StackTooSmall(1,0));
	}

	m_output = std::move(engine.returnData);
	return {m_output.data(), m_output.size()};	// TODO: This all bytesConstRef stuff sucks
}

}
}
}
<commit_msg>Try not to use JIT in any interactive mode<commit_after>
#include "VM.h"

#include <libevm/VMFace.h>

#include "ExecutionEngine.h"
#include "Compiler.h"

namespace dev
{
namespace eth
{
namespace jit
{

bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
{
	assert(_onOp == nullptr); // Parameter ignored
	assert(_steps == (uint64_t)-1); // Parameter ignored

	auto module = Compiler().compile(_ext.code);

	ExecutionEngine engine;
	auto exitCode = engine.run(std::move(module), m_gas, &_ext);

	switch (exitCode)
	{
	case 101:
		BOOST_THROW_EXCEPTION(BadJumpDestination());
	case 102:
		BOOST_THROW_EXCEPTION(OutOfGas());
	case 103:
		BOOST_THROW_EXCEPTION(StackTooSmall(1,0));
	}

	m_output = std::move(engine.returnData);
	return {m_output.data(), m_output.size()};	// TODO: This all bytesConstRef stuff sucks
}

}
}
}
<|endoftext|>


<commit_before>#ifndef __CONSOLE_HPP_INCLUDED
#define __CONSOLE_HPP_INCLUDED

#include "code/ylikuutio/callback_system/key_and_callback_struct.hpp"
#include "code/ylikuutio/callback_system/callback_parameter.hpp"
#include "code/ylikuutio/callback_system/callback_object.hpp"
#include "code/ylikuutio/callback_system/callback_engine.hpp"
#include "code/ylikuutio/common/any_value.hpp"
#include "code/ylikuutio/ontology/font2D.hpp"

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <list>     // std::list
#include <stdint.h> // uint32_t etc.
#include <vector>   // std::vector

namespace console
{
    class Console
    {
        public:
            // constructor.
            Console(std::vector<KeyAndCallbackStruct>** current_keypress_callback_engine_vector_pointer_pointer,
                    std::vector<KeyAndCallbackStruct>** current_keyrelease_callback_engine_vector_pointer_pointer,
                    ontology::Font2D* text2D_pointer);

            // destructor.
            ~Console();

            void set_my_keypress_callback_engine_vector_pointer(std::vector<KeyAndCallbackStruct>* my_keypress_callback_engine_vector_pointer);
            void set_my_keyrelease_callback_engine_vector_pointer(std::vector<KeyAndCallbackStruct>* my_keyrelease_callback_engine_vector_pointer);
            void draw_console();

            // callbacks.

            static void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods);

            static datatypes::AnyValue* enable_enter_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_exit_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_move_to_previous_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_move_to_next_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_backspace(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_enter_key(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_ctrl_c(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enter_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* exit_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* move_to_previous_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* move_to_next_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* backspace(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* ctrl_c(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enter_key(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

        private:
            void copy_historical_input_into_current_input();
            bool exit_console();
            void delete_character();
            void move_cursor_left();
            void move_cursor_right();
            void move_cursor_to_start_of_line();
            void move_cursor_to_end_of_line();
            void page_up();
            void page_down();
            void home();
            void end();

            std::list<char> current_input; // This is used for actual inputs.
            std::list<char>::iterator cursor_it;
            uint32_t cursor_index;
            bool in_console;
            bool can_enter_console;
            bool can_exit_console;
            bool can_move_to_previous_input;
            bool can_move_to_next_input;
            bool can_backspace;
            bool can_enter_key;
            bool can_ctrl_c;
            bool is_left_control_pressed;
            bool is_right_control_pressed;
            bool is_left_alt_pressed;
            bool is_right_alt_pressed;
            bool is_left_shift_pressed;
            bool is_right_shift_pressed;

            std::vector<std::list<char>> command_history;
            bool in_historical_input;
            uint32_t historical_input_i;
            std::list<char> temp_input;    // This is used for temporary storage of new input while modifying historical inputs.

            // These are related to keypress callbacks.
            std::vector<KeyAndCallbackStruct>** current_keypress_callback_engine_vector_pointer_pointer;
            std::vector<KeyAndCallbackStruct>* previous_keypress_callback_engine_vector_pointer;
            std::vector<KeyAndCallbackStruct>* my_keypress_callback_engine_vector_pointer;

            // These are related to keyrelease callbacks.
            std::vector<KeyAndCallbackStruct>** current_keyrelease_callback_engine_vector_pointer_pointer;
            std::vector<KeyAndCallbackStruct>* previous_keyrelease_callback_engine_vector_pointer;
            std::vector<KeyAndCallbackStruct>* my_keyrelease_callback_engine_vector_pointer;

            // This is a pointer to `font2D::Font2D` instance that is used for printing.
            ontology::Font2D* text2D_pointer;
    };
}

#endif
<commit_msg>Reordered code lines and added comments.<commit_after>#ifndef __CONSOLE_HPP_INCLUDED
#define __CONSOLE_HPP_INCLUDED

#include "code/ylikuutio/callback_system/key_and_callback_struct.hpp"
#include "code/ylikuutio/callback_system/callback_parameter.hpp"
#include "code/ylikuutio/callback_system/callback_object.hpp"
#include "code/ylikuutio/callback_system/callback_engine.hpp"
#include "code/ylikuutio/common/any_value.hpp"
#include "code/ylikuutio/ontology/font2D.hpp"

// Include GLFW
#ifndef __GLFW3_H_INCLUDED
#define __GLFW3_H_INCLUDED
#include <glfw3.h>
#endif

// Include standard headers
#include <list>     // std::list
#include <stdint.h> // uint32_t etc.
#include <vector>   // std::vector

namespace console
{
    class Console
    {
        public:
            // constructor.
            Console(std::vector<KeyAndCallbackStruct>** current_keypress_callback_engine_vector_pointer_pointer,
                    std::vector<KeyAndCallbackStruct>** current_keyrelease_callback_engine_vector_pointer_pointer,
                    ontology::Font2D* text2D_pointer);

            // destructor.
            ~Console();

            void set_my_keypress_callback_engine_vector_pointer(std::vector<KeyAndCallbackStruct>* my_keypress_callback_engine_vector_pointer);
            void set_my_keyrelease_callback_engine_vector_pointer(std::vector<KeyAndCallbackStruct>* my_keyrelease_callback_engine_vector_pointer);
            void draw_console();

            // Callbacks.

            static void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods);

            // Action mode keyrelease callbacks begin here.

            static datatypes::AnyValue* enable_enter_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            // Action mode keypress callbacks begin here.

            static datatypes::AnyValue* enter_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            // Console mode keyrelease callbacks begin here.

            static datatypes::AnyValue* enable_exit_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_left_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* release_right_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_move_to_previous_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_move_to_next_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_backspace(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_enter_key(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enable_ctrl_c(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            // Console mode keypress callbacks begin here.

            static datatypes::AnyValue* exit_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_control_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_alt_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_left_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* press_right_shift_in_console(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* move_to_previous_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* move_to_next_input(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* backspace(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* enter_key(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            static datatypes::AnyValue* ctrl_c(
                    callback_system::CallbackEngine*,
                    callback_system::CallbackObject*,
                    std::vector<callback_system::CallbackParameter*>&,
                    console::Console* console);

            // Callbacks end here.

        private:
            void copy_historical_input_into_current_input();
            bool exit_console();
            void delete_character();
            void move_cursor_left();
            void move_cursor_right();
            void move_cursor_to_start_of_line();
            void move_cursor_to_end_of_line();
            void page_up();
            void page_down();
            void home();
            void end();

            std::list<char> current_input; // This is used for actual inputs.
            std::list<char>::iterator cursor_it;
            uint32_t cursor_index;
            bool in_console;
            bool can_enter_console;
            bool can_exit_console;
            bool can_move_to_previous_input;
            bool can_move_to_next_input;
            bool can_backspace;
            bool can_enter_key;
            bool can_ctrl_c;
            bool is_left_control_pressed;
            bool is_right_control_pressed;
            bool is_left_alt_pressed;
            bool is_right_alt_pressed;
            bool is_left_shift_pressed;
            bool is_right_shift_pressed;

            std::vector<std::list<char>> command_history;
            bool in_historical_input;
            uint32_t historical_input_i;
            std::list<char> temp_input;    // This is used for temporary storage of new input while modifying historical inputs.

            // These are related to keypress callbacks.
            std::vector<KeyAndCallbackStruct>** current_keypress_callback_engine_vector_pointer_pointer;
            std::vector<KeyAndCallbackStruct>* previous_keypress_callback_engine_vector_pointer;
            std::vector<KeyAndCallbackStruct>* my_keypress_callback_engine_vector_pointer;

            // These are related to keyrelease callbacks.
            std::vector<KeyAndCallbackStruct>** current_keyrelease_callback_engine_vector_pointer_pointer;
            std::vector<KeyAndCallbackStruct>* previous_keyrelease_callback_engine_vector_pointer;
            std::vector<KeyAndCallbackStruct>* my_keyrelease_callback_engine_vector_pointer;

            // This is a pointer to `font2D::Font2D` instance that is used for printing.
            ontology::Font2D* text2D_pointer;
    };
}

#endif
<|endoftext|>


<commit_before><commit_msg>Bugfix: `Shader::get_number_of_apprentices`.<commit_after><|endoftext|>