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

#include "process_timestamps.hpp"
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stdexcept>

namespace {
using rko_lio::core::Secondsd;
using rko_lio::core::TimestampVector;

// Returns the number of integer digits in a value.
inline int number_of_digits_integer_part(const double value) {
  const double abs_val = std::abs(value);
  const auto int_part = static_cast<uint64_t>(std::round(abs_val));
  return int_part > 0 ? static_cast<int>(std::floor(std::log10(int_part) + 1)) : 1;
}

// The timestamps are either in seconds or in nanoseconds, we handle no other case for now
std::tuple<Secondsd, Secondsd, TimestampVector> timestamps_in_sec_from_raw(const std::vector<double>& raw_timestamps) {
  const auto& [min_it, max_it] = std::minmax_element(raw_timestamps.begin(), raw_timestamps.end());
  const double min_stamp = *min_it;
  const double max_stamp = *max_it;
  const double scan_duration = std::abs(max_stamp - min_stamp);

  const bool is_nanoseconds = (scan_duration > 100.0);
  // 100 seconds is far more than the duration of any normal scan
  // but note that this was necessary because a hesai sensor spit out a 20 sec difference in a real scan
  // I'll welcome improvements to logic here to handle edge cases like this

  TimestampVector timestamps_in_seconds(raw_timestamps.size());
  std::transform(raw_timestamps.cbegin(), raw_timestamps.cend(), timestamps_in_seconds.begin(),
                 [is_nanoseconds](const double ts) { return Secondsd(is_nanoseconds ? ts * 1e-9 : ts); });
  if (is_nanoseconds) {
    return {Secondsd(min_stamp * 1e-9), Secondsd(max_stamp * 1e-9), timestamps_in_seconds};
  } else {
    return {Secondsd(min_stamp), Secondsd(max_stamp), timestamps_in_seconds};
  }
}
} // namespace

namespace rko_lio::core {
std::tuple<Secondsd, Secondsd, TimestampVector> process_timestamps(const std::vector<double>& raw_timestamps,
                                                                   const Secondsd& header_stamp) {
  constexpr auto EPSILON_TIME = std::chrono::nanoseconds(10);

  const auto& [min_ts, max_ts, raw_timestamps_in_sec] = timestamps_in_sec_from_raw(raw_timestamps);
  TimestampVector timestamps = raw_timestamps_in_sec;
  const Secondsd scan_duration = std::chrono::abs(max_ts - min_ts);

  Secondsd begin_stamp;
  Secondsd end_stamp;

  // Case: absolute timestamps
  // min or max is within 1ms to stamp time. If the timestamps are not absolute, I don't know what they are.
  if (std::chrono::abs(header_stamp - min_ts) < std::chrono::milliseconds(1) ||
      std::chrono::abs(header_stamp - max_ts) < std::chrono::milliseconds(1)) {
    begin_stamp = min_ts;
    end_stamp = max_ts;
    return {begin_stamp, end_stamp, std::move(timestamps)};
  }

  // - Case 1: timestamps are relative to scan start
  // - Case 2: timestamps are relative to scan end
  //   the limits i've set empirically based on all the cases encountered till now and what felt reasonable
  bool relative_stamps = (min_ts >= Secondsd(0) && std::chrono::abs(min_ts) < std::chrono::milliseconds(4)) ||
                         (max_ts <= Secondsd(0) && std::chrono::abs(max_ts) < std::chrono::milliseconds(4));

  // here are weirdo cases i've seen which i think should be kept separate so its always in mind in case they cause
  // problems in the future
  // - Avia Livox on HeLiPR - min timestamps are oten greater than the header stamp by a significant amount
  // - VLP-16 on Leg-KILO: relative to the end, but some points are ahead of the header stamp
  relative_stamps = relative_stamps ||
                    (min_ts >= Secondsd(0) && std::chrono::abs(min_ts) < std::chrono::milliseconds(20)) ||
                    (min_ts < Secondsd(0) && max_ts > Secondsd(0) && max_ts < std::chrono::milliseconds(10));

  if (relative_stamps) {
    std::transform(timestamps.begin(), ti


/*
Copyright 2017 Google Inc. All Rights Reserved.
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 "Patch.h"

ofJson Patch::toJson(){
	ofJson node;
	node["position"] = position;
	node["attack"] = attack;
	node["decay"] = decay;
	node["sustain"] = sustain;
	node["release"] = release;

	ofJson instsNode;
	for(auto& instrument : instruments){
		instsNode.push_back(instrument);
	}
	node["instruments"] = instsNode;

	node["grid"] = {grid[0], grid[1]};
	return node;
}

bool Patch::fromJson(const ofJson &node){
	bool result = true;
	auto readFloat = [&result](const ofJson &node, float &value){
		if(node.is_number()){
			value = std::min(std::max(node.get<float>(), 0.0f), 1.0f);
		}else{
			result = false;
		}
	};

	readFloat(node["position"], position);
	readFloat(node["attack"], attack);
	readFloat(node["decay"], decay);
	readFloat(node["sustain"], sustain);
	readFloat(node["release"], release);

	const ofJson &instsNode = node["instruments"];
	if(instsNode.is_array() && instsNode.size() == instruments.size()){
		for(size_t i=0; i<instruments.size(); ++i){
			instruments[i] = instsNode[i];
		}
	}else{
		result = false;
	}

	const ofJson &gridNode = node["grid"];
	if(gridNode.is_array() && gridNode.size() == grid.size()){
		for(size_t i=0; i<grid.size(); ++i){
			readFloat(gridNode[i], grid[i]);
		}
	}else{
		result = false;
	}

	return result;
}

bool Patches::load(){
	ofJson doc = ofLoadJson(filename);
	if(doc.is_null()){
		return false;
	}

	size_t idx = 0;
	bool result = true;
	for(auto& patchNode : doc["patches"]){
		if(idx>=size()){
			break;
		}
		result = (*this)[idx].fromJson(patchNode) && result;
		++idx;
	}

	return result;
}

bool Patches::save(){
	ofJson doc;
	ofJson patchesNode;
	for(auto& patch : *this){
		patchesNode.push_back(patch.toJson());
	}
	doc["patches"] = patchesNode;
	return ofSaveJson(filename, doc);
}


//-----> C++ Basics 02

//-> Type - Casting
/*
#include<iostream>
using namespace std;

int main(){
    int a=89;
    float b=23.78;

    cout<<"The value of a is "<<(float)a<<"."<<endl;
    cout<<"The value of a is "<<float(a)<<"."<<endl;
    cout<<"The value of b is "<<(int)b<<"."<<endl;
    cout<<"The value of b is "<<int(b)<<"."<<endl;

    cout<<"--------------------------------------------------"<<endl;

    cout<<"The Expression is "<<a+b<<endl;;
    cout<<"The Expression is "<<a+int(b)<<endl;;
    cout<<"The Expression is "<<a+(int)b<<endl;;

    return 0;
}
*/

//---> Operators
/*
Operators in C++ :-
    1) Arithmetic Operators :- '+' , '-' , '*' , '/' , '%' , '++' , '--'.
    2) Assignment Opertaors :- used to assign the values to variables.
    3) Comparison Operators :- '==' , '>=' , '<=' , '>' , '<' , '!='.
    4) Logical Operators    :- '&&' , '||' , '!'.
*/

/*
1) Arithmetic Operators :-

#include<iostream>
using namespace std;

int main(){
    int a=10,b=5;

    cout<<"Operators in C++"<<endl;
    cout<<"1. Arithmetic Operators :- "<<endl;

    cout<<"The value of (a+b) is "<<a+b<<"."<<endl;
    cout<<"The value of (a-b) is "<<a-b<<"."<<endl;
    cout<<"The value of (a*b) is "<<a*b<<"."<<endl;
    cout<<"The value of (a/b) is "<<a/b<<"."<<endl;
    cout<<"The value of (a%b) is "<<a%b<<"."<<endl;
    cout<<"The value of (a++) is "<<a++<<"."<<endl;
    cout<<"The value of (++a) is "<<++a<<"."<<endl;
    cout<<"The value of (a--) is "<<a--<<"."<<endl;
    cout<<"The value of (--a) is "<<--a<<"."<<endl;

    return 0;
}
*/

/*
2) Assignment Opertaors :-

#include<iostream>
using namespace std;

int main(){
    int a=3;
    float b=9.8;
    char c='w';

    return 0;
}
*/

/*
3) Comparison Operators :-

#include<iostream>
using namespace std;

int main(){
    int a=17,b=10;
    cout<<"3. Comparison Operators :-"<<endl;

    cout<<"The value of (a==b) is "<<(a==b)<<"."<<endl;
    cout<<"The value of (a>=b) is "<<(a>=b)<<"."<<endl;
    cout<<"The value of (a<=b) is "<<(a<=b)<<"."<<endl;
    cout<<"The value of (a>b) is "<<(a>b)<<"."<<endl;
    cout<<"The value of (a<b) is "<<(a<b)<<"."<<endl;
    cout<<"The value of (a!=b) is "<<(a!=b)<<"."<<endl;

    return 0;
}
*/

/*
4) Logical Operators :-

#include<iostream>
using namespace std;

int main(){
    int a=17,b=10;
    cout<<"3. Comparison Operators :-"<<endl;

    cout<<"The value of (a==b) is "<<(a==b)<<"."<<endl;
    cout<<"The value of (a>=b) is "<<(a>=b)<<"."<<endl;
    cout<<"The value of (a<=b) is "<<(a<=b)<<"."<<endl;
    cout<<"The value of (a>b) is "<<(a>b)<<"."<<endl;
    cout<<"The value of (a<b) is "<<(a<b)<<"."<<endl;
    cout<<"The value of (a!=b) is "<<(a!=b)<<"."<<endl;
    cout<<"------------------------------------------------------------------------------------------------"<<endl;

    cout<<"4. Logical Operators :- "<<endl;

    cout<<"The value of this logical AND operator ((a==b) && (a<b)) is "<<((a==b) && (a<b))<<"."<<endl;
    cout<<"The value of this logical OR operator ((a==b) || (a<b)) is "<<((a==b) || (a<b))<<"."<<endl;
    cout<<"The value of this logical NOT operator (!(a==b)) is "<<(!(a==b))<<"."<<endl;

    return 0;
}
*/

/*
5) Bitwise Operators :-

#include<iostream>
using namespace std;

int main(){
    int a=10;
    int b=17;

    cout<<(a&b)<<endl;    //-> AND
    cout<<(a|b)<<endl;    //-> OR
    cout<<~b<<endl;       //-> NOT
    cout<<(a^b)<<endl;    //-> XOR
    cout<<"------------------------------------"<<endl;

    cout<<(++a)<<endl;      //-> pre-increment
    cout<<(--a)<<endl;      //-> pre-decrement
    cout<<(a++)<<endl;      //-> post-increment
    cout<<(a--)<<endl;      //-> post-decrement
    cout<<(++b)<<endl;
    cout<<(--b)<<endl;
    cout<<(b++)<<endl;
    cout<<(b--)<<endl;
    cout<<"------------------------------------"<<endl;

    //-> Left-shift operator
    cout<<(19<<1)<<endl;
    cout<<(17<<2)<<endl;
    //-> Right-shift operator
    cout<<(19>>1)<<endl;
    cout<<(17>>2)<<endl;

    return 0;
}
*/

//-> Operator Precedence

/*
#include<iostream>
using namespace std;

int main(){
    int a=3,b=9;
    int c= (a*9)+b-90;
    cout<<c<<endl;

    return 0;
}
*/

// Reference Variable

/*
#include<iostream>
using namespace std;

int c=29;

int main(){
    int a,b,c;

    cout<<"Enter the value of a : "<<endl;
    cin>>a;

    cout<<"Enter the value of b : "<<endl;
    cin>>b;

    c=a+b;

    cout<<"The sum is "<<c<<"."<<endl;
    cout<<"The Global c is "<<::c<<"."<<endl;      // '::' -> scope resolution operator.

    return 0;
}
*/

//-> Reference Variables  :- To give another name for a same value.

/*
#include<iostream>
using namespace std;

int main(){
    int a=17;
    int &b = a;   //-> reference variable

    cout<<a<<endl;
    cout<<b<<endl;

    return 0;
}
*/

//-> Manipulators
/*
1) endl
2) setw(can use when we include iomanip)
*/

/*
#include<iostream>
#include<iomanip>
using namespace std;

int main(){
    int a=10,b=100,c=1000;
    cout<<"The use of endl:-"<


#include <iostream>
#include <iomanip> //input / output manipulator
using namespace std;

int main() {
    // item names
    string items[9] = {"Water", "Coca-Cola", "Fuzetea", "Mars", "Snickers", "Kinder", "Crisps", "Popcorn", "Biscuits"};
    // item prices
    double prices[9] = {1.00, 2.00, 2.00, 1.30, 1.30, 1.50, 0.85, 1.15, 1.00};
    // item codes
    string codes[9] = {"A1", "A2", "A3", "B1", "B2", "B3", "C1", "C2", "C3"};
    // item stock
    int stock[9] = {5, 5, 5, 5, 5, 5, 5 ,5 ,5};

    string inputCode;
    double money;
    char another;
    char pound = 156; // used ASCII caracters to display the pound symbol

    do {
        // display the menu
        cout << "\n--- Vending Machine Menu ---\n";
        for (int i = 0; i < 9; i++) {
            cout << codes[i] << " - " << items[i] << " - " << pound << fixed << setprecision(2) << prices[i];
            if (stock[i] == 0) cout << " [Out of Stock]";
            cout << endl;
        }

        // ask for item code
        cout << "\nEnter item code: ";
        cin >> inputCode;

        // find the item
        int index = -1;
        for (int i = 0; i < 9; i++) {
            if (inputCode == codes[i]) {
                index = i;
                break;
            }
        }
        //simple error handleing
        if (index == -1) {
            cout << "Invalid code. Try again.\n";
            continue;
        }
        //display message when item is out of stock
        if (stock[index] == 0) {
            cout << "Sorry, " << items[index] << " is out of stock.\n";
            continue;
        }

        // input the money value
        cout << "Insert money ("<< pound<< "): ";
        cin >> money;
        //for when you have introduced less money than the item cost, you get error message and how much the item costs
        if (money < prices[index]) {
            cout << "Not enough money. " << items[index] << " costs "<< pound << prices[index] << ".\n";
            continue;
        }

        // dispense item and calculate change
        stock[index]--;
        double change = money - prices[index];
        cout << "Dispensing " << items[index] << "...\n";
        cout << "Here's your change: "<<pound<< fixed << setprecision(2) << change << "\n";

        // ask to buy something else
        cout << "\nWant to buy something else? (y/n): ";
        cin >> another;

    } while (another == 'y' || another == 'Y');

    cout << "Thank you for your purchase. Please come again.\n";
    return 0;
}


#include "console_ui.hpp"
#include "game.hpp"
#include <random>

void TicTacToe::play() {
    populateBoard();
    ConsoleUI::GameMenu(state, running);

    while(running) {
        displayBoard();
        makeMove();
        if(!isTie())
            AIMove();
        victory();
    }
}

inline void TicTacToe::setPlayed(int move) {
    alreadyPlayed.at(move) = 1;
}

void TicTacToe::displayBoard()
{
    //TODO: Make the board bigger and  center it
    ConsoleUI::clearConsole();
    std::cout << TicTacToeTexts::tictactoeText << "\n";

    for(std::size_t i = 0 ; i < board.size() ; i += 3)
    {
        std::cout << "          ██          ██     " << '\n';
        std::cout << "          ██          ██     " << '\n';

        std::cout << "    ";
        printColoredCell(board.at(i));
        std::cout << "     ██    ";
        printColoredCell(board.at(i + 1));
        std::cout << "     ██    ";
        printColoredCell(board.at(i + 2));
        std::cout << "  " << '\n';

        std::cout << "          ██          ██     " << '\n';
        std::cout << "          ██          ██     " << '\n';

        std::cout << ((i < 6) ? "▇▇▇▇▇▇▇▇▇▇██▇▇▇▇▇▇▇▇▇▇██▇▇▇▇▇▇▇▇▇▇" : "" ) << '\n';
    }
}

void TicTacToe::printColoredCell(char &cell)
{
    if(isInWinningLine(&cell)) {
        ConsoleUI::setColor(ConsoleColor::YELLOW);
    }else if (cell == player) {
        ConsoleUI::setColor(ConsoleColor::BLUE);
    } else if (cell == ai) {
        ConsoleUI::setColor(ConsoleColor::RED);
    }

    std::cout << cell;
    ConsoleUI::resetColor();
}

inline void TicTacToe::populateBoard() {
    for(std::size_t i = 0 ; i < board.size() ; i++) {
        board.at(i) = ' ';
    }
}

inline bool TicTacToe::isWinningLine(const char &a, const char &b, const char &c, const char &who)
{
    return a == who && b == who && c == who;
}

bool TicTacToe::isInWinningLine(const char* ptr) const {
    for (auto* winPtr : winningLine) {
        if (winPtr == ptr)
            return true;
    }
    return false;
}

bool TicTacToe::isTie() const{
    for(std::size_t i = 0 ; i < board.size() ; i++) {
        if(board.at(i) == ' ') {
            return false;
        }
    }
    return true;
}

bool TicTacToe::checkWin() {
    for(std::size_t row = 0 ; row < board.size() ; row+=3) {
        if(isWinningLine(board.at(row), board.at(row + 1), board.at(row + 2), player)
        || isWinningLine(board.at(row), board.at(row + 1), board.at(row + 2), ai))
          {
            winner = board.at(row);
            winningLine = {&board.at(row), &board.at(row + 1), &board.at(row + 2)};
            return true;
        }
    }
    for(std::size_t col = 0 ; col < board.size() / 3 ; col++) {
        if(isWinningLine(board.at(col), board.at(col + 3), board.at(col + 6), player)
        || isWinningLine(board.at(col), board.at(col + 3), board.at(col + 6), ai))
        {
            winner = board.at(col);
            winningLine = {&board.at(col), &board.at(col + 3), &board.at(col + 6)};
            return true;
          }
    }

    if( isWinningLine(board.at(2), board.at(4), board.at(6), player) ||
        isWinningLine(board.at(2), board.at(4), board.at(6), ai))
        {
            winner = board.at(4); //? index 4 is the common of all
            winningLine = {&board.at(2), &board.at(4), &board.at(6)};
            return true;
        }

    if( isWinningLine(board.at(0), board.at(4), board.at(8), player) ||
        isWinningLine(board.at(0), board.at(4), board.at(8), ai))
        {
            winner = board.at(4); //? index 4 is the common of all
            winningLine = {&board.at(0), &board.at(4), &board.at(8)};
            return true;
        }
    return false;
}

void TicTacToe::makeMove()
{
    int move = 0;
    bool validMove = false;
    while(!validMove)
    {
        std::cout << "Enter a number to play (1-9) : ";
        std::cin >> move;

        if(std::cin.fail())
        {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); //! dont uderstand this yet
            std::cout << "Invalid input. ";
        }
        else
        {
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
            validMove = move > 0 && move < 10;
            if (!validMove) {
                std::cout << "Invalid move. Number must be between 1 and 9.\n";
            }
            else
            {
                if(alreadyPlayed.at(static_cast<std::size_t>(move - 1)) == 1)
                {
                    std::cout << "That tile was already played on chose another tile!" << "\n";
                    validMove = false;
                }
            }
        }
    }
    map_move(move);
    board.at(move) = player;
    setPlayed(move);
}

void TicTacToe::AIMove()
{
    int move = 0;
    //! It needs some training
    while(move == 0)
    {
        move = getRandMinMax(1, 9);
        if(alreadyPlayed.at(static_cast<std::size_t>(m


#include <iostream>
#include "raylib.h"
#include <vector>

using namespace std;

struct Point {
	int x, y;

	Point(int _x, int _y)
	{
		x = _x;
		y = _y;
	}
	Point()
	{
		x = 0;
		y = 0;
	}
};

struct Node {
	Point pos;
	int data;
	Node(Point _pos, int _data)
	{
		pos = _pos;
		data = _data;
	}
	Node() { data = 0; }
};

struct Quad {
	Point topLeft;
	Point botRight;

	Node* n;

	Quad* topLeftTree;
	Quad* topRightTree;
	Quad* botLeftTree;
	Quad* botRightTree;

	Quad()
	{
		topLeft = Point(0, 0);
		botRight = Point(0, 0);
		n = NULL;
		topLeftTree = NULL;
		topRightTree = NULL;
		botLeftTree = NULL;
		botRightTree = NULL;
	}
	Quad(Point topL, Point botR)
	{
		n = NULL;
		topLeftTree = NULL;
		topRightTree = NULL;
		botLeftTree = NULL;
		botRightTree = NULL;
		topLeft = topL;
		botRight = botR;
	}
	void insert(Node*);
	bool inBoundary(Point);
};

void Quad::insert(Node* node) {
	if (node == NULL) {
		return;
	}
	if (!inBoundary(node->pos)) {
		return;
	}

	if (abs(topLeft.x - botRight.x) <= 1 && abs(topLeft.y - botRight.y) <= 1) {
		if (n == NULL) {
			n = node;
		}
		return;
	}

	if ((topLeft.x + botRight.x) / 2 >= node->pos.x) {
		if ((topLeft.y + botRight.y) / 2 >= node->pos.y) {
			if (topLeftTree == NULL) {
				topLeftTree = new Quad(
					Point(topLeft.x, topLeft.y),
					Point((topLeft.x + botRight.x) / 2,
						(topLeft.y + botRight.y) / 2));
			}
			topLeftTree->insert(node);
		}
		else {
			if (botLeftTree == NULL) {
				botLeftTree = new Quad(
					Point(topLeft.x,
						(topLeft.y + botRight.y) / 2),
					Point((topLeft.x + botRight.x) / 2,
						botRight.y));
			}
			botLeftTree->insert(node);
		}
	}
	else {
		if ((topLeft.y + botRight.y) / 2 >= node->pos.y	) {
			if (topRightTree == NULL) {
				topRightTree = new Quad(
					Point((topLeft.x + botRight.x) / 2,
						topLeft.y),
					Point(botRight.x,
						(topLeft.y + botRight.y) / 2));
			}
			topRightTree->insert(node);
		}
		else {
			if (botRightTree == NULL) {
				botRightTree = new Quad(
					Point((topLeft.x + botRight.x) / 2,
						(topLeft.y + botRight.y) / 2),
					Point(botRight.x, botRight.y));
			}
			botRightTree->insert(node);
		}

	}
}

bool Quad::inBoundary(Point p)
{
	return (p.x >= topLeft.x && p.x <= botRight.x
		&& p.y >= topLeft.y && p.y <= botRight.y);
}

void drawQuad(Quad* n) {

	if (n == NULL) return;

	if (n->n != NULL) {
		DrawCircle(n->n->pos.x, n->n->pos.y, 3, RED);
	}

	DrawLine(n->topLeft.x, n->topLeft.y, n->topLeft.x, n->botRight.y, WHITE);
	DrawLine(n->topLeft.x, n->topLeft.y, n->botRight.x, n->topLeft.y, WHITE);
	DrawLine(n->topLeft.x, n->botRight.y, n->botRight.x, n->botRight.y, WHITE);
	DrawLine(n->botRight.x, n->topLeft.y, n->botRight.x, n->botRight.y, WHITE);

	int midx = (n->topLeft.x + n->botRight.x) / 2;
	int midy = (n->topLeft.y + n->botRight.y) / 2;
	DrawLine(midx, n->topLeft.y, midx, n->botRight.y, WHITE);
	DrawLine(n->topLeft.x, midy, n->botRight.x, midy, WHITE);

	drawQuad(n->topLeftTree);
	drawQuad(n->topRightTree);
	drawQuad(n->botLeftTree);
	drawQuad(n->botRightTree);
}

int main() {

	Quad center(Point(0, 0), Point(800, 800));
	vector<Node> nodes;

	InitWindow(800, 800, "Quadtree");
	SetTargetFPS(60);

	while (!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(BLACK);
		if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
			nodes.emplace_back(Point(GetMouseX(), GetMouseY()), 0);
			center.insert(&nodes.back());
		}
		Quad* n = &center;
		drawQuad(n);
		EndDrawing();
	}
	CloseWindow();
	return 0;
}


#include "core/infrastructure/http_client/http_client.h"
#include "config/config_loader/config_loader.h"
#include "core/infrastructure/memory_manager/memory_manager.h"
#include "core/infrastructure/logger/logger.h"

HttpClient::HttpClient() {
  lastResponse = "";
  lastHttpCode = -1;
  secureClient = nullptr;
  plainClient = nullptr;
  clientInitialized = false;

  // Initialize metrics
  metrics.totalRequests = 0;
  metrics.successfulRequests = 0;
  metrics.sslErrors = 0;
  metrics.timeoutErrors = 0;
  metrics.lastErrorTime = 0;
  metrics.lastErrorCategory = ErrorCategory::UNKNOWN;

  // Initialize intelligent logging
  metrics.lastLogTime = 0;
  metrics.errorCountSinceLastLog = 0;
  metrics.suppressRepeatedErrors = false;

  initializeClients();
}

HttpClient::~HttpClient() {
  http.end();
  cleanupClients();
}

uint16_t HttpClient::ping(const String& url, uint16_t timeout) {
  // Enhanced safety checks
  if (url.length() > 200) {
    Serial_println("[HTTP] ERROR: URL too long for ping");
    return 0;
  }

  // Calculate intelligent timeout
  uint16_t calculatedTimeout = calculateTimeout(url, timeout);

  return performRequestWithRetry(url, calculatedTimeout, "GET");
}

uint16_t HttpClient::healthCheck(const String& url, const String& endpoint, uint16_t timeout) {
  // Enhanced safety checks
  if (url.length() > 200) {
    Serial_println("[HTTP] ERROR: URL too long for health check");
    return 0;
  }

  // Build full URL efficiently
  String fullUrl = url;
  if (endpoint.length() > 0 && endpoint.length() < 100) {
    if (fullUrl.endsWith("/") && endpoint[0] == '/') {
      fullUrl = fullUrl.substring(0, fullUrl.length() - 1);
    } else if (!fullUrl.endsWith("/") && endpoint[0] != '/') {
      fullUrl += "/";
    }
    fullUrl += endpoint;
  }

  if (fullUrl.length() > 300) {
    Serial_println("[HTTP] ERROR: Full URL too long for health check");
    return 0;
  }

  // Calculate intelligent timeout for health checks
  uint16_t calculatedTimeout = calculateTimeout(fullUrl, timeout);

  uint16_t latency = performRequestWithRetry(fullUrl, calculatedTimeout, "GET");

  if (latency > 0) {
    // Check HTTP status code first
    if (lastHttpCode < 200 || lastHttpCode >= 300) {
      Serial_printf("[HTTP] Health check failed: HTTP %d\n", lastHttpCode);
      return 0;
    }

    // Enhanced health response validation
    if (lastResponse.length() > 0 && lastResponse.length() < 1000) {
      if (!isHealthyResponse(lastResponse)) {
        Serial_printf("[HTTP] Health check failed: Unhealthy response detected (HTTP %d)\n", lastHttpCode);
        return 0;
      }
    }

    // Log successful health check with details
    Serial_printf("[HTTP] Health check successful: %d ms (HTTP %d)\n", latency, lastHttpCode);
  }

  return latency;
}

String HttpClient::get(const String& url, uint16_t timeout) {
  uint16_t calculatedTimeout = calculateTimeout(url, timeout);
  performRequestWithRetry(url, calculatedTimeout, "GET");
  return lastResponse;
}

String HttpClient::post(const String& url, const String& data, uint16_t timeout) {
  uint16_t calculatedTimeout = calculateTimeout(url, timeout);
  performRequestWithRetry(url, calculatedTimeout, "POST", data);
  return lastResponse;
}

bool HttpClient::isHealthyResponse(const String& response) const {
  if (response.length() == 0) return false;

  // Convert to lowercase for case-insensitive comparison
  String lowerResponse = response;
  lowerResponse.toLowerCase();

  // Get configuration patterns
  String unhealthyPatterns = ConfigLoader::getHealthCheckUnhealthyPatterns();
  String healthyPatterns = ConfigLoader::getHealthCheckHealthyPatterns();
  bool strictMode = ConfigLoader::isHealthCheckStrictMode();

  // Check for explicit unhealthy indicators first
  int start = 0;
  while (start < unhealthyPatterns.length()) {
    int end = unhealthyPatterns.indexOf(',', start);
    if (end == -1) end = unhealthyPatterns.length();

    String pattern = unhealthyPatterns.substring(start, end);
    pattern.trim();
    if (pattern.length() > 0 && lowerResponse.indexOf(pattern) >= 0) {
      return false;
    }
    start = end + 1;
  }

  // Check for explicit healthy indicators
  start = 0;
  while (start < healthyPatterns.length()) {
    int end = healthyPatterns.indexOf(',', start);
    if (end == -1) end = healthyPatterns.length();

    String pattern = healthyPatterns.substring(start, end);
    pattern.trim();
    if (pattern.length() > 0 && lowerResponse.indexOf(pattern) >= 0) {
      return true;
    }
    start = end + 1;
  }

  // Check for simple success responses
  if (lowerResponse == "ok" ||
      lowerResponse == "healthy" ||
      lowerResponse == "up" ||
      lowerResponse == "running" ||
      lowerResponse == "{\"ok\":true}" ||
      lowerResponse == "{\"status\":\"ok\"}" ||
      lowerResponse == "{\"health\":\"ok\"}") {
    return true;
  }

  // In strict mode, require explicit health indicators
  if (strictM


#include "Hero.h"
#include <QTimer>
#include <QRandomGenerator>
#include <QDebug>

Hero::Hero(float x, float y, QObject *parent)
    : QObject(parent), coordinateXP(x), coordinateYP(y)
{
    short int initialAmmo = 24; // сразу полный магазин
    weapon = new Weapon(initialAmmo, 80, 6, this);
    connect(weapon, &Weapon::ammoChanged, this, &Hero::ammoChanged);
}

void Hero::shooting() {
    if (reloading || !lifePlayer) return;

    if (weapon->getAmmo() > 0) {
        weapon->shoot();

        int roll = QRandomGenerator::global()->bounded(100);
        int chanceToHit = (accuracy + weapon->getChanceOfHit()) / 2;

        if (roll < chanceToHit) {
            emit hit();
            if (targetEnemy) targetEnemy->takeDamage(weapon->getDamage());
        } else emit miss();

        m_color = "red";
        emit colorChanged();
        QTimer::singleShot(100, this, [this]() {
            m_color = "green";
            emit colorChanged();
        });

    } else if (!reloading && maxBullets > 0) {
        reloading = true;
        QTimer::singleShot(reloadTime, this, [this]() {
            short int toLoad = std::min(maxBullets, weapon->getMagazineSize());
            weapon->setAmmo(toLoad);
            maxBullets -= toLoad;
            reloading = false;
            qDebug() << "Hero reloaded. Ammo:" << weapon->getAmmo();
        });
    }
}

void Hero::stopShooting() {
    m_color = "green";
    emit colorChanged();
}

void Hero::death() {
    lifePlayer = false;
    m_color = "red";
    emit colorChanged();
}

void Hero::animVictory() {}


#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>

#include "flutter_window.h"
#include "utils.h"

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t *command_line, _In_ int show_command) {
  // Attach to console when present (e.g., 'flutter run') or create a
  // new console when running with a debugger.
  if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
    CreateAndAttachConsole();
  }

  // Initialize COM, so that it is available for use in the library and/or
  // plugins.
  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

  flutter::DartProject project(L"data");

  std::vector<std::string> command_line_arguments =
      GetCommandLineArguments();

  project.set_dart_entrypoint_arguments(std::move(command_line_arguments));

  FlutterWindow window(project);
  Win32Window::Point origin(10, 10);
  Win32Window::Size size(1280, 720);
  if (!window.Create(L"reservas", origin, size)) {
    return EXIT_FAILURE;
  }
  window.SetQuitOnClose(true);

  ::MSG msg;
  while (::GetMessage(&msg, nullptr, 0, 0)) {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }

  ::CoUninitialize();
  return EXIT_SUCCESS;
}


#include <SFML/Graphics.hpp>
#include <glm/glm.hpp>
#include <eng/main.hpp>
#include <eng/window.hpp>
#include <eng/vectors.hpp>
#include <filesystem>

#include "textures.hpp"

eng::window_t::window_t():
	m_screen(1920, 16.f/9.f) {
	sf::VideoMode video_mode = sf::VideoMode::getDesktopMode();
	this->create(video_mode, "Raytracer", sf::Style::Fullscreen);
	this->setFramerateLimit(60);

	this->m_load_fonts();

	this->m_load_shader();

}

eng::screen_t::screen_t(unsigned int resolution, float aspect_ratio) {
	this->resolution = sf::Vector2u(resolution, resolution / aspect_ratio);

	this->texture.create(this->resolution.x, this->resolution.y);
	this->texture.setSmooth(true);

	sf::Vector2f true_resolution = (sf::Vector2f)eng::window.getSize();
	sf::Vector2f scale = sf::Vector2f(
			true_resolution.x / this->resolution.x,
			true_resolution.y / this->resolution.y);

	this->sprite.setTexture(this->texture.getTexture());
	this->sprite.setScale(scale);

	this->sprite.setPosition(0, 0);
}

void eng::window_t::m_load_shader() {
        this->m_raytracer.loadFromFile("./shaders/compiled_shader.glsl", sf::Shader::Fragment);

	this->m_raytracer.setUniform("resolution", (sf::Vector2f)this->m_screen.resolution);
}

void eng::window_t::m_load_fonts() {
	this->m_font.loadFromFile("./bin/fonts/clacon2.ttf");
	this->m_fps.setFont(this->m_font);
	this->m_fps.setCharacterSize(24);
	this->m_fps.setFillColor(sf::Color(255, 0, 255));
	this->m_fps.setPosition(10, 10);
}

void render_shader_to(const sf::Shader& raytracer, eng::screen_t& screen) {
	screen.texture.clear(sf::Color(255, 0, 0));
	sf::RectangleShape buffer = sf::RectangleShape((sf::Vector2f)screen.resolution);
	buffer.setPosition(0, 0);
	screen.texture.draw(buffer, &raytracer);
	screen.texture.display();

	float scale_x = eng::window.getSize().x / (float)screen.resolution.x;
	float scale_y = eng::window.getSize().y / (float)screen.resolution.y;
	screen.sprite.setScale(scale_x, scale_y);
	screen.sprite.setPosition(0, 0);
}

void eng::window_t::render() {
	this->clear(this->default_col());

	this->m_raytracer.setUniform("delta_time", eng::delta_time);

	render_shader_to(this->m_raytracer, this->m_screen);
	this->draw(this->m_screen.sprite);

	this->m_fps.setString("fps: " + std::to_string(int(1/eng::delta_time)));
	this->draw(this->m_fps);

	this->display();
}

void eng::window_t::screenshot() {
	namespace fs = std::filesystem;

	unsigned int screenshot_id = 0;
	for (auto file: fs::directory_iterator("./bin/screenshots/")) {
		screenshot_id++;
	}

	sf::Image image = this->m_screen.texture.getTexture().copyToImage();
	image.saveToFile("./bin/screenshots/" + std::to_string(screenshot_id) + ".png");
}


#include <iostream>
#include "stb_image.h"

#ifdef _WIN32
#include <windows.h>
#endif

const std::string RESET_ATTRIBUTES = "\x1b[0m";

void set_fg_color(std::ostream &stream, const unsigned char *pixel) {
    const int red = pixel[0], green = pixel[1], blue = pixel[2];
    stream << "\x1b[38;2;" << red << ";" << green << ";" << blue << "m";
}

void set_bg_color(std::ostream &stream, const unsigned char *pixel) {
    const int red = pixel[0], green = pixel[1], blue = pixel[2];
    stream << "\x1b[48;2;" << red << ";" << green << ";" << blue << "m";
}

int main(const int argc, char *argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
        return 1;
    }

    int w, h, channels;
    unsigned char *data = stbi_load(argv[1], &w, &h, &channels, 3);

    if (!data) {
        std::cerr << "Loading image failed: " << stbi_failure_reason() << std::endl;
        return 1;
    }

#ifdef _WIN32
    HANDLE std_output_handle = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD console_mode;
    GetConsoleMode(std_output_handle, &console_mode);
    SetConsoleMode(std_output_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT);
    UINT encoding = GetConsoleOutputCP();
    SetConsoleOutputCP(CP_UTF8);
#endif

    const unsigned char row_size = w * 3;
    int i = 0;
    for (int y = 0; y < h - 1; y += 2) {
        // draw two rows at a time
        for (int x = 0; x < w; x++) {
            // foreground color; upper row
            set_fg_color(std::cout, data + i);
            // background color; bottom row
            set_bg_color(std::cout, data + i + row_size);
            // draw pixel character (▀)
            std::cout << "▀";

            i += 3;
        }
        std::cout << RESET_ATTRIBUTES;
        if (y < h - 3) {
            std::cout << std::endl;
        }
        // skip bottom row as it's already drawn
        i += row_size;
    }
    // if odd number of rows
    if (h & 0x1) {
        std::cout << std::endl;
        // draw last row
        for (int x = 0; x < w; x++) {
            // foreground color; only upper row
            set_fg_color(std::cout, data + i);
            // draw pixel character (▀)
            std::cout << "▀";

            i += 3;
        }
    }

    stbi_image_free(data);

    // reset colors
    std::cout << RESET_ATTRIBUTES;

#ifdef _WIN32
    SetConsoleMode(std_output_handle, console_mode);
    SetConsoleCP(encoding);
#endif

    return 0;
}


/*
  Stockfish, a UCI chess playing engine derived from Glaurung 2.1
  Copyright (C) 2004-2025 The Stockfish developers (see AUTHORS file)

  Stockfish is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Stockfish 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "movegen.h"

#include <cassert>
#include <initializer_list>

#include "bitboard.h"
#include "position.h"

namespace Stockfish {

namespace {

template<GenType Type, Direction D, bool Enemy>
ExtMove* make_promotions(ExtMove* moveList, [[maybe_unused]] Square to) {

    constexpr bool all = Type == EVASIONS || Type == NON_EVASIONS;

    if constexpr (Type == CAPTURES || all)
        *moveList++ = Move::make<PROMOTION>(to - D, to, QUEEN);

    if constexpr ((Type == CAPTURES && Enemy) || (Type == QUIETS && !Enemy) || all)
    {
        *moveList++ = Move::make<PROMOTION>(to - D, to, ROOK);
        *moveList++ = Move::make<PROMOTION>(to - D, to, BISHOP);
        *moveList++ = Move::make<PROMOTION>(to - D, to, KNIGHT);
    }

    return moveList;
}

template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {

    constexpr Color     Them     = ~Us;
    constexpr Bitboard  TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
    constexpr Bitboard  TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
    constexpr Direction Up       = pawn_push(Us);
    constexpr Direction UpRight  = (Us == WHITE ? NORTH_EAST : SOUTH_WEST);
    constexpr Direction UpLeft   = (Us == WHITE ? NORTH_WEST : SOUTH_EAST);

    const Bitboard emptySquares = ~pos.pieces();
    const Bitboard enemies      = Type == EVASIONS ? pos.checkers() : pos.pieces(Them);

    Bitboard pawnsOn7    = pos.pieces(Us, PAWN) & TRank7BB;
    Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;

    // Single and double pawn pushes, no promotions
    if constexpr (Type != CAPTURES)
    {
        Bitboard b1 = shift<Up>(pawnsNotOn7) & emptySquares;
        Bitboard b2 = shift<Up>(b1 & TRank3BB) & emptySquares;

        if constexpr (Type == EVASIONS)  // Consider only blocking squares
        {
            b1 &= target;
            b2 &= target;
        }

        while (b1)
        {
            Square to   = pop_lsb(b1);
            *moveList++ = Move(to - Up, to);
        }

        while (b2)
        {
            Square to   = pop_lsb(b2);
            *moveList++ = Move(to - Up - Up, to);
        }
    }

    // Promotions and underpromotions
    if (pawnsOn7)
    {
        Bitboard b1 = shift<UpRight>(pawnsOn7) & enemies;
        Bitboard b2 = shift<UpLeft>(pawnsOn7) & enemies;
        Bitboard b3 = shift<Up>(pawnsOn7) & emptySquares;

        if constexpr (Type == EVASIONS)
            b3 &= target;

        while (b1)
            moveList = make_promotions<Type, UpRight, true>(moveList, pop_lsb(b1));

        while (b2)
            moveList = make_promotions<Type, UpLeft, true>(moveList, pop_lsb(b2));

        while (b3)
            moveList = make_promotions<Type, Up, false>(moveList, pop_lsb(b3));
    }

    // Standard and en passant captures
    if constexpr (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS)
    {
        Bitboard b1 = shift<UpRight>(pawnsNotOn7) & enemies;
        Bitboard b2 = shift<UpLeft>(pawnsNotOn7) & enemies;

        while (b1)
        {
            Square to   = pop_lsb(b1);
            *moveList++ = Move(to - UpRight, to);
        }

        while (b2)
        {
            Square to   = pop_lsb(b2);
            *moveList++ = Move(to - UpLeft, to);
        }

        if (pos.ep_square() != SQ_NONE)
        {
            assert(rank_of(pos.ep_square()) == relative_rank(Us, RANK_6));

            // An en passant capture cannot resolve a discovered check
            if (Type == EVASIONS && (target & (pos.ep_square() + Up)))
                return moveList;

            b1 = pawnsNotOn7 & pawn_attacks_bb(Them, pos.ep_square());

            assert(b1);

            while (b1)
                *moveList++ = Move::make<EN_PASSANT>(pop_lsb(b1), pos.ep_square());
        }
    }

    return moveList;
}

template<Color Us, PieceType Pt>
ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {

    static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");

    Bitboard bb = pos.pieces(Us, Pt);

    while (bb)
    {
        Square   from = pop_lsb(bb);
        Bitboard b    = attacks_bb<Pt>(from, pos.pieces()) & target;

        while (b)


/*
 * Copyright (c) 2013,2016,2020 The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define _LARGEFILE64_SOURCE /* enable lseek64() */

/******************************************************************************
 * INCLUDE SECTION
 ******************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/fs.h>
#include <limits.h>
#include <dirent.h>
#include <linux/kernel.h>
#include <asm/byteorder.h>
#include <map>
#include <vector>
#include <string>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>

#define LOG_TAG "gpt-utils"
#include <cutils/log.h>
#include <cutils/properties.h>
#include "gpt-utils.h"
#include <zlib.h>
#include <endian.h>

/******************************************************************************
 * DEFINE SECTION
 ******************************************************************************/
#define BLK_DEV_FILE    "/dev/block/mmcblk0"
/* list the names of the backed-up partitions to be swapped */
/* extension used for the backup partitions - tzbak, abootbak, etc. */
#define BAK_PTN_NAME_EXT    "bak"
#define XBL_PRIMARY         "/dev/block/bootdevice/by-name/xbl"
#define XBL_BACKUP          "/dev/block/bootdevice/by-name/xblbak"
#define XBL_AB_PRIMARY      "/dev/block/bootdevice/by-name/xbl_a"
#define XBL_AB_SECONDARY    "/dev/block/bootdevice/by-name/xbl_b"
/* GPT defines */
#define MAX_LUNS                    26
//This will allow us to get the root lun path from the path to the partition.
//i.e: from /dev/block/sdaXXX get /dev/block/sda. The assumption here is that
//the boot critical luns lie between sda to sdz which is acceptable because
//only user added external disks,etc would lie beyond that limit which do not
//contain partitions that interest us here.
#define PATH_TRUNCATE_LOC (sizeof("/dev/block/sda") - 1)

//From /dev/block/sda get just sda
#define LUN_NAME_START_LOC (sizeof("/dev/block/") - 1)
#define BOOT_LUN_A_ID 1
#define BOOT_LUN_B_ID 2
/******************************************************************************
 * MACROS
 ******************************************************************************/

#define GET_4_BYTES(ptr)    ((uint32_t) *((uint8_t *)(ptr)) | \
        ((uint32_t) *((uint8_t *)(ptr) + 1) << 8) | \
        ((uint32_t) *((uint8_t *)(ptr) + 2) << 16) | \
        ((uint32_t) *((uint8_t *)(ptr) + 3) << 24))

#define GET_8_BYTES(ptr)    ((uint64_t) *((uint8_t *)(ptr)) | \
        ((uint64_t) *((uint8_t *)(ptr) + 1) << 8) | \
        ((uint64_t) *((uint8_t *)(ptr) + 2) << 16) | \
        ((uint64_t) *((uint8_t *)(ptr) + 3) << 24) | \
        ((uint64_t) *((uint8_t *)(ptr) + 4) << 32) | \
        ((uint64_t) *((uint8_t *)(ptr) + 5) << 40) | \
        ((uint64_t) *((uint8_t *)(ptr) + 6) << 48) | \
        ((uint64_t) *((uint8_t *)(ptr) + 7) << 56))

#define PUT_4_BYTES(ptr, y)   *((uint8_t *)(ptr)) = (y) & 0xff; \
        *((uint8_t *)(ptr) + 1) = ((y) >> 8) & 0xff; \
        *((uint8_t *)(ptr) + 2) = ((y) >> 16) & 0xff; \
        *((uint8_t *)(ptr) + 3) = ((y) >> 24) & 0xff;

/******************************************************************************
 * TYPES
 ******************************************************************************/
using namespace std;
enum gpt_state {
    GPT_OK = 0,
    GPT_BAD_SIGNATURE,
    GPT_BAD_CRC
};
//List of LUN's c


#include "tgaimage.h"
#include "geometry.h"
#include "simple_model.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
#include <cmath>

const int width  = 800;
const int height = 800;

// Compute barycentric coordinates
Vec3f barycentric(Vec3f A, Vec3f B, Vec3f C, Vec3f P) {
    Vec3f s[2];
    for (int i = 2; i--; ) {
        s[i][0] = C[i] - A[i];
        s[i][1] = B[i] - A[i];
        s[i][2] = A[i] - P[i];
    }
    Vec3f u = s[0] ^ s[1];
    if (std::abs(u[2]) > 1e-2)
        return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
    return Vec3f(-1, 1, 1);
}

// Triangle rasterization with Z-buffer
void triangle(Vec3f *pts, std::vector<float> &zbuffer, TGAImage &image, TGAColor color) {
    Vec2f bboxmin( std::numeric_limits<float>::max(),  std::numeric_limits<float>::max());
    Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
    Vec2f clamp(image.width() - 1, image.height() - 1);

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 2; j++) {
            bboxmin[j] = std::max(0.f,      std::min(bboxmin[j], pts[i][j]));
            bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts[i][j]));
        }
    }

    Vec3f P;
    for (P.x = bboxmin.x; P.x <= bboxmax.x; P.x++) {
        for (P.y = bboxmin.y; P.y <= bboxmax.y; P.y++) {
            Vec3f bc_screen = barycentric(pts[0], pts[1], pts[2], P);
            if (bc_screen.x < 0 || bc_screen.y < 0 || bc_screen.z < 0) continue;

            P.z = 0;
            for (int i = 0; i < 3; i++) P.z += pts[i][2] * bc_screen[i];

            if (zbuffer[int(P.x + P.y * width)] < P.z) {
                zbuffer[int(P.x + P.y * width)] = P.z;
                image.set(P.x, P.y, color);
            }
        }
    }
}

Vec3f world2screen(Vec3f v) {
    return Vec3f(int((v.x + 1.) * width / 2. + .5), int((v.y + 1.) * height / 2. + .5), v.z);
}

void render_model(SimpleModel* model, Vec3f light_dir, const char* filename, const char* description) {
    TGAImage image(width, height, TGAImage::RGB);
    std::vector<float> zbuffer(width * height, -std::numeric_limits<float>::max());

    std::cout << "Rendering " << description << "..." << std::endl;

    for (int i = 0; i < model->nfaces(); i++) {
        std::vector<int> face = model->face(i);
        Vec3f screen_coords[3];
        Vec3f world_coords[3];

        for (int j = 0; j < 3; j++) {
            Vec3f v = model->vert(face[j]);
            screen_coords[j] = world2screen(v);
            world_coords[j]  = v;
        }

        Vec3f n = (world_coords[2] - world_coords[0]) ^ (world_coords[1] - world_coords[0]);
        n.normalize();
        float intensity = n * light_dir;

        if (intensity > 0) {
            triangle(screen_coords, zbuffer, image, TGAColor{(unsigned char)(intensity * 255), (unsigned char)(intensity * 255), (unsigned char)(intensity * 255), 255});
        }
    }

    image.flip_vertically();
    image.write_tga_file(filename);
    std::cout << "Saved " << filename << std::endl;
}

int main(int argc, char** argv) {
    SimpleModel* model = new SimpleModel("obj/african_head/african_head.obj");

    std::cout << "=== 3D Renderer Demo ===" << std::endl;
    std::cout << "Model loaded: " << model->nverts() << " vertices, " << model->nfaces() << " faces" << std::endl;

    // Test different lighting directions
    render_model(model, Vec3f(0, 0, -1), "demo_front_light.tga", "front lighting");
    render_model(model, Vec3f(1, 0, -1).normalize(), "demo_right_light.tga", "right side lighting");
    render_model(model, Vec3f(-1, 0, -1).normalize(), "demo_left_light.tga", "left side lighting");
    render_model(model, Vec3f(0, 1, -1).normalize(), "demo_top_light.tga", "top lighting");
    render_model(model, Vec3f(0, -1, -1).normalize(), "demo_bottom_light.tga", "bottom lighting");

    delete model;

    std::cout << "Demo completed! Generated 5 different lighting scenarios." << std::endl;
    return 0;
}


#include <catch2/catch_test_macros.hpp>
#include "../src/Calculator.h"
#include <QApplication>

// Фикстура для инициализации Qt один раз
struct QtTestFixture {
    QtTestFixture() {
        static int argc = 1;
        static char* argv[] = {(char*)"test", nullptr};
        app = new QApplication(argc, argv);
    }

    ~QtTestFixture() {
        delete app;
    }

    QApplication* app;
};

TEST_CASE_METHOD(QtTestFixture, "Calculator Logic Tests", "[logic]") {
    Calculator calc;

    SECTION("Initial state should be zero") {
        REQUIRE(calc.getCurrentValue() == 0.0);
        REQUIRE(calc.getStoredValue() == 0.0);
        REQUIRE(calc.getCurrentOperation().isEmpty());
    }

    SECTION("Single digit input") {
        calc.digitPressed(5);
        REQUIRE(calc.getCurrentValue() == 5.0);
    }

    SECTION("Multiple digits input") {
        calc.digitPressed(1);
        calc.digitPressed(2);
        calc.digitPressed(3);
        REQUIRE(calc.getCurrentValue() == 123.0);
    }

    SECTION("Addition: 2 + 3 = 5") {
        calc.digitPressed(2);
        calc.setOperation("+");
        calc.digitPressed(3);
        calc.calculateResult();
        REQUIRE(calc.getCurrentValue() == 5.0);
    }

    SECTION("Subtraction: 5 - 3 = 2") {
        calc.digitPressed(5);
        calc.setOperation("-");
        calc.digitPressed(3);
        calc.calculateResult();
        REQUIRE(calc.getCurrentValue() == 2.0);
    }

    SECTION("Multiplication: 4 * 5 = 20") {
        calc.digitPressed(4);
        calc.setOperation("*");
        calc.digitPressed(5);
        calc.calculateResult();
        REQUIRE(calc.getCurrentValue() == 20.0);
    }

    SECTION("Division: 10 / 2 = 5") {
        calc.digitPressed(1);
        calc.digitPressed(0);
        calc.setOperation("/");
        calc.digitPressed(2);
        calc.calculateResult();
        REQUIRE(calc.getCurrentValue() == 5.0);
    }

    SECTION("Division by zero should return zero") {
        calc.digitPressed(5);
        calc.setOperation("/");
        calc.digitPressed(0);
        calc.calculateResult();
        REQUIRE(calc.getCurrentValue() == 0.0);
    }

    SECTION("Clear should reset everything") {
        calc.digitPressed(7);
        calc.setOperation("+");
        calc.digitPressed(3);
        calc.clear();

        REQUIRE(calc.getCurrentValue() == 0.0);
        REQUIRE(calc.getStoredValue() == 0.0);
        REQUIRE(calc.getCurrentOperation().isEmpty());
    }
}


// QRsync - A simple Qt-based GUI for the rsync command-line tool.
// Copyright (C) 2025 Carlos J. Checo <binarydepth@gmail.com>
//
// This program is licensed under the Community Public Software License (CPSL) v0.1.
// You should have received a copy of this license along with this program.
// If not, please see the LICENSE.md file in the root directory of this project.

#include "MainWindow.hpp"
#include "HelpViewer.hpp"
#include <QtWidgets>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      rsyncProcess(nullptr),
      manualHelpShown(false) // Initialize the flag
{
    setupUI();

    // Set up settings path
    QDir configDir(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation));
    if (!configDir.exists()) {
        configDir.mkpath(".");
    }
    settingsFilePath = configDir.filePath("qrsync_syncsets.json");

    populateSyncsetMenus(); // Initial population of the menus

    rsyncProcess = new QProcess(this);
    connect(rsyncProcess, &QProcess::readyReadStandardOutput, this, &MainWindow::onRsyncOutput);
    connect(rsyncProcess, &QProcess::readyReadStandardError, this, &MainWindow::onRsyncError);
    connect(rsyncProcess, &QProcess::finished, this, &MainWindow::onRsyncFinished);

    // Initial button state
    stopButton->setEnabled(false);

    // Trigger the initial state for the archive options
    onArchiveToggled(archiveCheck->isChecked());
}

MainWindow::~MainWindow() = default;

void MainWindow::setupUI() {
    setWindowTitle("QRsync");
    resize(800, 700);

    setupMenuBar();

    QWidget *centralWidget = new QWidget(this);
    setCentralWidget(centralWidget);
    QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);

    QGroupBox *pathsGroup = new QGroupBox("Paths");
    QGridLayout *pathsLayout = new QGridLayout(pathsGroup);
    pathsLayout->addWidget(new QLabel("Source:"), 0, 0);
    sourceEdit = new QLineEdit();
    pathsLayout->addWidget(sourceEdit, 0, 1);
    QPushButton *browseSourceButton = new QPushButton("Browse...");
    connect(browseSourceButton, &QPushButton::clicked, this, &MainWindow::onBrowseSource);
    pathsLayout->addWidget(browseSourceButton, 0, 2);
    pathsLayout->addWidget(new QLabel("Destination:"), 1, 0);
    destinationEdit = new QLineEdit();
    pathsLayout->addWidget(destinationEdit, 1, 1);
    QPushButton *browseDestinationButton = new QPushButton("Browse...");
    connect(browseDestinationButton, &QPushButton::clicked, this, &MainWindow::onBrowseDestination);
    pathsLayout->addWidget(browseDestinationButton, 1, 2);
    mainLayout->addWidget(pathsGroup);

    QGroupBox *optionsGroup = new QGroupBox("Options");
    QGridLayout *optionsLayout = new QGridLayout(optionsGroup);
    archiveCheck = new QCheckBox("Archive (-a)");
    archiveCheck->setChecked(true);
    connect(archiveCheck, &QCheckBox::toggled, this, &MainWindow::onArchiveToggled);
    optionsLayout->addWidget(archiveCheck, 0, 0, 1, 2);
    recursiveCheck = new QCheckBox("Recursive (-r)");
    symlinksCheck = new QCheckBox("Copy symlinks (-l)");
    permsCheck = new QCheckBox("Preserve permissions (-p)");
    timesCheck = new QCheckBox("Preserve times (-t)");
    groupCheck = new QCheckBox("Preserve group (-g)");
    ownerCheck = new QCheckBox("Preserve owner (-o)");
    QWidget *subOptionsWidget = new QWidget();
    QGridLayout *subOptionsLayout = new QGridLayout(subOptionsWidget);
    subOptionsLayout->setContentsMargins(20, 0, 0, 0);
    subOptionsLayout->addWidget(recursiveCheck, 0, 0);
    subOptionsLayout->addWidget(symlinksCheck, 0, 1);
    subOptionsLayout->addWidget(permsCheck, 1, 0);
    subOptionsLayout->addWidget(timesCheck, 1, 1);
    subOptionsLayout->addWidget(groupCheck, 2, 0);
    subOptionsLayout->addWidget(ownerCheck, 2, 1);
    optionsLayout->addWidget(subOptionsWidget, 1, 0, 1, 4);
    optionsLayout->addWidget(new QFrame(), 2, 0);
    verboseCheck = new QCheckBox("Verbose (-v)");
    verboseCheck->setChecked(true);
    progressCheck = new QCheckBox("Progress (--progress)");
    progressCheck->setChecked(true);
    deleteCheck = new QCheckBox("Delete on destination (--delete)");
    sizeOnlyCheck = new QCheckBox("Size only (--size-only)");
    ignoreExistingCheck = new QCheckBox("Ignore existing (--ignore-existing)");
    skipNewerCheck = new QCheckBox("Skip newer (--update)");
    optionsLayout->addWidget(verboseCheck, 3, 0);
    optionsLayout->addWidget(progressCheck, 3, 1);
    optionsLayout->addWidget(skipNewerCheck, 3, 2);
    optionsLayout->addWidget(deleteCheck, 4, 0);
    optionsLayout->addWidget(sizeOnlyCheck, 4, 1);
    optionsLayout->addWidget(ignoreExistingCheck, 4, 2);
    mainLayout->addWidget(optionsGroup);

    QGroupBox *manualGroup = new QGroupBox("Manual Options");
    QVBoxLayout *manualLayout = new QVBoxLayout(manualGroup);
    manualOptionsEdit = new QLineEdit();
    manualOptionsEdit->setPlaceholderText("--exclude=*.


#include <iostream>

using namespace std;

class pet
{
public:
    string nome, raca;
    int tipo, idade;
    pet *ant, *prox;
    pet **inserir(pet **, string, string, int, int);
    pet **excluir(pet **, string, int);
    void listar(pet **, int);
    bool pesquisar(pet **, string, int);
};

pet **pet::inserir(pet **p, string n, string r, int i, int t)
{
    pet *novo = new pet();
    novo->nome = n;
    novo->raca = r;
    novo->tipo = t;
    novo->idade = i;
    novo->prox = NULL;
    novo->ant = NULL;

    if (p[0] == NULL)
    {
        p[0] = novo;
        p[1] = novo;
        return p;
    }

    pet *aux;
    if (novo->tipo == 1)
    {
        aux = p[0];
        while ((aux != NULL) && (novo->nome > aux->nome) && (aux->tipo == 1))
            aux = aux->prox;
    }
    else
    {
        aux = p[1];
        while ((aux != NULL) && (novo->nome > aux->nome) && (aux->tipo == 2))
            aux = aux->ant;
    }

    if (aux == NULL && novo->tipo == 1)
    {
        p[1]->prox = novo;
        novo->ant = p[1];
        p[1] = novo;
    }
    else if (aux == NULL && novo->tipo == 2)
    {
        novo->prox = p[0];
        p[0]->ant = novo;
        p[0] = novo;
    }
    else if (novo->tipo == 1)
    {
        novo->prox = aux;
        novo->ant = aux->ant;
        if (aux->ant != NULL) {
            aux->ant->prox = novo;
        }
        else {
            p[0] = novo;
        }
        aux->ant = novo;
    }
    else
    {
        novo->prox = aux->prox;
        novo->ant = aux;

        if (aux->prox != NULL)
            aux->prox->ant = novo;
        else
            p[1] = novo;

        aux->prox = novo;
    }

    return p;
}

pet **pet::excluir(pet **p, string n, int t)
{
    pet *aux;
    if (t == 1)
    {
        aux = p[0];
        while (aux->nome != n)
        {
            aux = aux->prox;
        }
    }
    else
    {
        aux = p[1];
        while (aux->nome != n)
        {
            aux = aux->ant;
        }
    }
    if (aux == p[0])
    {
        p[0] = p[0]->prox;
        p[0]->ant = NULL;
    }
    else if (aux == p[1])
    {
        p[1] = p[1]->ant;
        p[1]->prox = NULL;
    }
    else
    {
        aux->ant->prox = aux->prox;
        aux->prox->ant = aux->ant;
        delete (aux);
    };
    return p;
}

void pet::listar(pet **p, int op)
{
    pet *aux;
    if (op == 0)
    {
        aux = p[0];
        while (aux != NULL)
        {
            cout << aux->nome << endl;
            aux = aux->prox;
        }
    }
    else if (op == 1)
    {
        aux = p[0];
        while (aux != NULL && aux->tipo == 1)
        {
            cout << aux->nome << endl;
            aux = aux->prox;
        }
    }
    else
    {
        aux = p[1];
        while (aux != NULL && aux->tipo == 2)
        {
            cout << aux->nome << endl;
            aux = aux->ant;
        }
    }
}

bool pet::pesquisar(pet **p, string n, int t)
{
    pet *aux;
    if (t == 1)
    {
        aux = p[0];
        while (aux != NULL && aux->nome != n && aux->tipo == 1)
        {
            aux = aux->prox;
        }
    }
    else
    {
        aux = p[1];
        while (aux != NULL & aux->nome != n && aux->tipo == 2)
        {
            aux = aux->ant;
        }
    }
    if ((aux == NULL) || (aux != NULL && aux->tipo != t))
    {
        return false;
    }
    return true;
}

void Menu() {
    cout << "1. Cadastrar pet" << endl;
    cout << "2. Excluir" << endl;
    cout << "3. Listagem geral" << endl;
    cout << "4. Listagem de caes" << endl;
    cout << "5. Listagem de gatos" << endl;
    cout << "6. Pesquisar" << endl;
    cout << "7. Finalizar programa" << endl;
}

int main()
{
    pet O, **L, *resp;
    L = new pet*[2];
    L[0] = L[1] = NULL;
    string nome, raca;
    int idade, tipo;
    int op;

    L = O.inserir(L, "Rex", "ViraLata", 3, 1);   // Cachorro
    L = O.inserir(L, "Bolt", "Pastor", 5, 1);    // Cachorro
    L = O.inserir(L, "Mimi", "Siamês", 2, 2);    // Gato
    L = O.inserir(L, "Luna", "Persa", 4, 2);     // Gato

    do
    {
        Menu();
        cin >> op;
        switch (op)
        {
        case 1:
            cout << "Informe o nome, raça, idade e tipo: ";
            cin >> nome;
            cin >> raca;
            cin >> idade;
            cin >> tipo;

            L = O.inserir(L, nome, raca, idade, tipo);
                cout << "Nome inserido" << endl;
            break;

        case 2:
            if (L[0] == NULL)
            {
                cout << "Sem registros!" << endl;
            }
            else
            {
                cout << "Informe o nome e o tipo: ";
                cin >> nome;
                cin >> tipo;
                if (O.pesquisar(L, nome, tipo))
                {
                     L = O.excluir(L, nome, tipo);
                    cout << "Cadastro de pet excluido!" << endl;
                }
                else
                {
                    cout << "Nao existe!" << endl;
                }
            }


/*
 * Copyright (C) 2017 Google Inc.
 *
 * 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.
 *
 * Modifications copyright (C) 2025 William Henning
 * Changes: See header.
 */

#include "swapchain.h"

#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <unordered_set>
#include <algorithm>

#include "callback_swapchain.h"
#include "logger.h"
#include "present_callback.h"

namespace swapchain {

void RegisterInstance(VkInstance instance, InstanceData& data) {
  uint32_t num_devices = 0;
  data.vkEnumeratePhysicalDevices(instance, &num_devices, nullptr);

  data.physical_devices_.resize(num_devices);
  data.vkEnumeratePhysicalDevices(instance, &num_devices,
                                  data.physical_devices_.data());

  auto physical_device_map = GetGlobalContext().GetPhysicalDeviceMap();

  for (VkPhysicalDevice physical_device : data.physical_devices_) {
    PhysicalDeviceData dat{instance};
    data.vkGetPhysicalDeviceMemoryProperties(physical_device,
                                             &dat.memory_properties_);
    data.vkGetPhysicalDeviceProperties(physical_device,
                                       &dat.physical_device_properties_);
    (*physical_device_map)[physical_device] = dat;
  }
}

VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
    VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
    const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
  return CreateSurface(instance,
                       pCreateInfo,
                       VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
                       pAllocator,
                       pSurface);
}

VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
    VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
    const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
  return CreateSurface(instance,
                       pCreateInfo,
                       VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR,
                       pAllocator,
                       pSurface);
}

VKAPI_ATTR VkResult VKAPI_CALL CreateSurface(
    VkInstance instance, const void* pCreateInfo, VkStructureType createType,
    const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
  const auto instance_dat = *GetGlobalContext().GetInstanceData(instance);

  std::string window_name;
  xcb_window_t window;
  xcb_connection_t* connection;
  VkSurfaceKHR backing_surface;

  if (createType == VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
    const VkXlibSurfaceCreateInfoKHR& info = *(VkXlibSurfaceCreateInfoKHR*)pCreateInfo;
    window = (xcb_window_t)info.window;
    connection = XGetXCBConnection(info.dpy);
    instance_dat.vkCreateXlibSurfaceKHR(instance, (VkXlibSurfaceCreateInfoKHR*)pCreateInfo, pAllocator, &backing_surface);
  }
  if (createType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
    const VkXcbSurfaceCreateInfoKHR& info = *(VkXcbSurfaceCreateInfoKHR*)pCreateInfo;
    window = info.window;
    connection = info.connection;
    instance_dat.vkCreateXcbSurfaceKHR(instance, (VkXcbSurfaceCreateInfoKHR*)pCreateInfo, pAllocator, &backing_surface);
  }

  std::ostringstream oss;
  oss << "0x" << std::hex << std::setw(8) << std::setfill('0') << static_cast<std::uint32_t>(window);
  window_name = oss.str();

  *pSurface = reinterpret_cast<VkSurfaceKHR>(
          new CallbackSurface{.window_name=window_name,
                              .window=window,
                              .connection=connection,
                              .backing_surface=backing_surface});
  return VK_SUCCESS;
}

VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
    VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
    VkSurfaceKHR surface, VkBool32* pSupported) {
  const auto instance_dat = *GetGlobalContext().GetInstanceData(
      GetGlobalContext().GetPhysicalDeviceData(physicalDevice)->instance_);

  for (uint32_t i = 0; i <= queueFamilyIndex; ++i) {
    uint32_t property_count = 0;
    instance_dat.vkGetPhysicalDeviceQueueFamilyProperties(
        physicalDevice, &property_count, nullptr);
    assert(property_count > queueFamilyIndex);

    std::vector<VkQueueFamilyProperties> properties(property_count);
    instance_dat.vkGetPhysicalDeviceQueueFamilyProperties(
        physicalDevice, &property_count, prope


/*
NAME: ALEX YAW AGBLEADE
STUDENT ID: 800812955

 */

#include <ctime>
#include <climits>
#include <iostream>
#include <cstdlib>
#include<unordered_map>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;

int main() {

    istringstream isin;
    srand((unsigned)time(NULL));
    unordered_map<int,int>hashtable;
    //creating a map that pairs all possible values from 1-6 to initial count of 0
    hashtable[1]=0;
    hashtable[2]=0;
    hashtable[3]=0;
    hashtable[4]=0;
    hashtable[5]=0;
    hashtable[6]=0;
    int indices[5];//creating an indices of size 5
    int maxValue;//this is to track the integer with the most count (highest maxCount)
    int maxCount =INT_MIN; //creating a tracker called maxCount to help me check the occurences of each integer in the map

    //creating all integers to count all the possible appearances for all the possible outcomes
    int nopaircount=0;
    int onepaircount=0;
    int threecount=0;
    int fourcount=0;
    int yahtzeecount=0;
    int simulationcount=0;
    int attempts;

    //PUTTING THE WHOLE  SIMULATION  INTO A WHILE LOOP 10,000 TIMES

    while (simulationcount < 10000) {
    ostringstream osin; //outputstring stream to help me print out the first attempt with the '*' on the most occuring value
    string firsttry;
    string secondtry;
        cout << "Attempt # " << simulationcount+1 << endl;
    hashtable[1]=0;
    hashtable[2]=0;
    hashtable[3]=0;
    hashtable[4]=0;
    hashtable[5]=0;
    hashtable[6]=0;

      // 3 attempts, whenever the maxCount turns to be 5, you break out of the loop
  //1ST ATTEMPT IS DONE OUTSIDE THE INNER WHILE LOOP
    //for every single simulaiton, the indices is first reset to all 0's
    for (int i=0; i< 5; i++) {
        indices[i]=0;
    }
    maxValue=INT_MIN;//this is to track the max integer
    maxCount =INT_MIN; //creating a tracker called maxCount to help me check the occurences in the hashtable
    for (int i=0; i < 5; i++) {
        indices[i] = (rand()%6)+1;
        hashtable[indices[i]]++;
        maxCount=max(maxCount,hashtable[indices[i]]);

        osin << setw(3) << indices[i];
    }

    firsttry=osin.str();
    if (maxCount > 1) {
        for (auto item:hashtable) {
            if (item.second==maxCount) {
                maxValue=item.first;
                break;
            }
        }
        firsttry=osin.str();

        for (int i=0; i < firsttry.size();i++) {
            if (isdigit(firsttry[i]) and firsttry[i]-'0'== maxValue) {
                secondtry.push_back('*');
                secondtry.push_back(firsttry[i]);

            }
            else {
                secondtry.push_back(firsttry[i]);
            }
        }
        cout  << secondtry;
        secondtry.clear();
        osin.clear();
        firsttry.clear();
        secondtry.clear();
    }
    else {
        cout << setw(3) << firsttry;
        firsttry.clear();

    }
    osin.clear();
    firsttry.clear();
    secondtry.clear();

    cout << endl;
    //now after the first attempt is done, if the maxCount=5; the program would jump out of the inner while loop else, it would go back into it (unless it has exhausted the attempts)
    attempts=0; //for 0 < 2 times
    //REMAINING TWO ATTEMPTS [breaks on its own if the two attempts are reached or Yahtzee acheived]
    while (attempts < 2) {
    if (maxCount==5) {
        break;
    }
    else if (maxCount>1 and maxCount < 5) {

        //loop through it again and reset all values not equal to the maxValue to 0
        for (auto &item: hashtable) { // passing by reference to change it after the loop
            if (item.first != maxValue) {
                item.second=0;
            }
        }
        //loop through the indices array again and print if it the value at that index is maxValue, if it is not find the random and print it
        for (int i=0; i < 5; i++) {
            if (indices[i]==maxValue) {
                cout <<  setw(3)<< "*"<<indices[i];
            }
            else {
                indices[i] = (rand()%6)+1;
                if (indices[i]==maxValue) {
                cout << setw(3) << "*"<< indices[i];
                }
                else {
                    cout << setw(3) << indices[i];
                }
                //since the initial maxValue is being kept, no need to keep track of other values anymore in the hashtable, so only add to the count if the rand is maxValue
                if (indices[i]==maxValue) {
                hashtable[indices[i]]++; //add to the count;
                maxCount = max(maxCount,hashtable[indices[i]]);
                }
            }
        }
        cout << endl;

    }
    else if (maxCount==1) {
        //reset the hashtable to 0
        for (auto& item:hashtable) {
            item.second=0;
        }

        for (int i=0; i< 5; i++) { //reset all the values in the array to 0 before finding random numbers again(throwing d


// dear imgui, v1.92.3 WIP
// (demo code)

// Help:
// - Read FAQ at http://dearimgui.com/faq
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
// - Need help integrating Dear ImGui in your codebase?
//   - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started
//   - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
// Get the latest version at https://github.com/ocornut/imgui

// How to easily locate code?
// - Use Tools->Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
// - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
// - Find a visible string and search for it in the code!

//---------------------------------------------------
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
//---------------------------------------------------
// Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
// Think again! It is the most useful reference code that you and other coders will want to refer to and call.
// Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of your game/app!
// Also include Metrics! ItemPicker! DebugLog! and other debug features.
// Removing this file from your project is hindering access to documentation for everyone in your team,
// likely leading you to poorer usage of the library.
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
// In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
// Thank you,
// -Your beloved friend, imgui_demo.cpp (which you won't delete)

//--------------------------------------------
// ABOUT THE MEANING OF THE 'static' KEYWORD:
//--------------------------------------------
// In this demo code, we frequently use 'static' variables inside functions.
// A static variable persists across calls. It is essentially a global variable but declared inside the scope of the function.
// Think of "static int n = 0;" as "global int n = 0;" !
// We do this IN THE DEMO because we want:
// - to gather code and data in the same place.
// - to make the demo source code faster to read, faster to change, smaller in size.
// - it is also a convenient way of storing simple UI related information as long as your function
//   doesn't need to be reentrant or used in multiple threads.
// This might be a pattern you will want to use in your code, but most of the data you would be working
// with in a complex codebase is likely going to be stored outside your functions.

//-----------------------------------------
// ABOUT THE CODING STYLE OF OUR DEMO CODE
//-----------------------------------------
// The Demo code in this file is designed to be easy to copy-and-paste into your application!
// Because of this:
// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
// - We try to declare static variables in the local scope, as close as possible to the code using them.
// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
//   by imgui.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
//   and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
//   Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.

// Navigating this file:
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
// - You can search/grep for all sections listed in the index to find the section.

/*

Index of this file:

// [SECTION] Forward Declarations
// [SECTION] Helpers
// [SECTION] Demo Window / ShowDemoWindow()
// [SECTION] DemoWindowMenuBar()
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
// [SECTION] DemoWindowWidgetsBasic()
// [SECTION] DemoWindowWidgetsBullets()
// [SECTION] DemoWindowWidgetsCollapsingHeaders()
// [SECTIO


//Use g++ -std=c++11 -o Lab2EX1 Lab2EX1.cpp -lwiringPi

#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <wiringPi.h>
#include <ctime>
#include <ratio>
#include <chrono>
using namespace std;
using namespace std::chrono;

int main(){
	//Set up wiringPi
	int pin = 1;
	wiringPiSetup();
	pinMode(pin, OUTPUT);
	while(true){
		/*Set the pinMode to output and generate a LOW-HIGH-LOW signal using "digitalWrite" to trigger the sensor.
		Use a 2 us delay between a LOW-HIGH and then a 5 us delay between HIGH-LOW. You can use
		the function "usleep" to set the delay. The unit of usleep is microsecond. */
		pinMode(pin, OUTPUT);
		digitalWrite(pin, LOW);
		//cout << digitalRead(pin);
		usleep(2);
		digitalWrite(pin,HIGH);
		//cout << digitalRead(pin);
		usleep(5);
		digitalWrite(pin,LOW);
		//cout << digitalRead(pin);

		/*Echo holdoff delay 750 us*/
		usleep(750);

		/*Switch the pinMode to input*/
		pinMode(pin, INPUT);
		//cout <<"Value: " << digitalRead(pin) << endl;

		/*Get the time it takes for signal to leave sensor and come back.*/

		// 1. defind a varable to get the current time t1. Refer to "High_Resolution_Clock_Reference.pdf" for more information
		high_resolution_clock::time_point t1 = high_resolution_clock::now();
		float pulse_width;
		high_resolution_clock::time_point t2;
		while(digitalRead(pin) == HIGH)
		{
			// 2. defind a varable to get the current time t2.
			t2 = high_resolution_clock::now();
			// 3. calculate the time duration: t2 - t1
			pulse_width = chrono::duration_cast<chrono::microseconds>(t2 - t1).count();
			// 4. if the duration is larger than the Pulse Maxium 18.5ms, break the loop.
			if (pulse_width > 18500) {
				break;
			}
		}

		/*Calculate the distance by using the time duration that you just obtained.*/ //Speed of sound is 340m/s
			float distance = pulse_width / 58;

		/*Print the distance.*/
			cout << "Distance: " << distance << endl;

		/*Delay before next measurement. The actual delay may be a little longer than what is shown is the datasheet.*/

			delay(200);
        }
}


#include "wrench_node.hpp"

namespace ur_admittance_controller {

// Implementation of ToMsg function declared in header
namespace conversions {
    geometry_msgs::msg::WrenchStamped ToMsg(
        const Wrench6d& wrench,
        const std::string& frame_id,
        const rclcpp::Time& stamp) {
        geometry_msgs::msg::WrenchStamped msg;
        msg.header.stamp = stamp;
        msg.header.frame_id = frame_id;
        msg.wrench.force.x = wrench[0];
        msg.wrench.force.y = wrench[1];
        msg.wrench.force.z = wrench[2];
        msg.wrench.torque.x = wrench[3];
        msg.wrench.torque.y = wrench[4];
        msg.wrench.torque.z = wrench[5];
        return msg;
    }
}

Matrix3d CrossMatrix(const Vector3d& v) {
    Matrix3d result;
    result <<     0, -v.z(),  v.y(),
              v.z(),      0, -v.x(),
             -v.y(),  v.x(),      0;
    return result;
}

Wrench6d TransformWrench(const Wrench6d& wrench_A, const Transform& X_BA) {
    Matrix3d R = X_BA.rotation();
    Vector3d p = X_BA.translation();

    Wrench6d wrench_B;
    wrench_B.head<3>() = R * wrench_A.head<3>();
    wrench_B.tail<3>() = R * wrench_A.tail<3>() + p.cross(wrench_B.head<3>());

    return wrench_B;
}

Wrench6d CompensateWrench(
    const Wrench6d& wrench_raw,
    const Transform& X_TB,
    const GravityCompensationParams& params) {

  Force3d f_gravity_S = params.R_SE * X_TB.rotation() * params.f_grav_b;

  Wrench6d wrench_gravity;
  wrench_gravity.head<3>() = f_gravity_S;
  wrench_gravity.tail<3>() = params.p_CoM_s.cross(f_gravity_S);

  Wrench6d wrench_bias;
  wrench_bias.head<3>() = params.f_bias_s;
  wrench_bias.tail<3>() = params.t_bias_s;

  return wrench_raw - wrench_gravity - wrench_bias;
}

Wrench6d TransformWrenchToBase(
    const Wrench6d& wrench_sensor,
    const Transform& X_BS) {
  return TransformWrench(wrench_sensor, X_BS.inverse());
}

WrenchNode::WrenchNode()
    : Node("wrench_node"),
      tf_buffer_(std::make_unique<tf2_ros::Buffer>(get_clock())),
      tf_listener_(std::make_shared<tf2_ros::TransformListener>(*tf_buffer_, this, true)) {

    auto status = LoadCalibrationParams();
    if (!status) {
        RCLCPP_FATAL(get_logger(), "Failed to load calibration: %s - Calibration is required for safety",
                     status.error().message.c_str());
        std::exit(1);
    }

    SetupROSInterfaces();

    ComputeSensorToProbeAdjoint();

    RCLCPP_INFO(get_logger(), "Wrench node initialized with calibration");
}

void WrenchNode::SetupROSInterfaces() {
    wrench_sub_ = create_subscription<WrenchMsg>("/netft/raw_sensor", rclcpp::SensorDataQoS(),
        std::bind(&WrenchNode::WrenchCallback, this, std::placeholders::_1));
    wrench_proc_sensor_pub_ = create_publisher<WrenchMsg>(
        "/netft/proc_sensor", rclcpp::SensorDataQoS());
    wrench_proc_probe_pub_ = create_publisher<WrenchMsg>(
        "/netft/proc_probe", rclcpp::SensorDataQoS());
    wrench_proc_probe_base_pub_ = create_publisher<WrenchMsg>(
        "/netft/proc_probe_base", rclcpp::SensorDataQoS());
}

void WrenchNode::WrenchCallback(const WrenchMsg::ConstSharedPtr msg) {
    if (!tf_buffer_->canTransform(frames::ROBOT_TOOL_FRAME, frames::ROBOT_BASE_FRAME,
                                   tf2::TimePointZero)) {
        RCLCPP_ERROR_THROTTLE(get_logger(), *get_clock(), constants::LOG_THROTTLE_MS,
                             "Transform %s->%s unavailable", frames::ROBOT_BASE_FRAME, frames::ROBOT_TOOL_FRAME);
        return;
    }

    // Step 1: Apply Low-Pass Filter (before compensation)
    Wrench6d f_raw = conversions::FromMsg(*msg);
    if (first_sample_) {
        lpf_state_ = f_raw;
        first_sample_ = false;
    }
    Wrench6d f_filtered = ALPHA * f_raw + (1.0 - ALPHA) * lpf_state_;
    lpf_state_ = f_filtered;
    f_raw_s_ = SanitizeWrench(f_filtered);

    try {
        X_TB_ = tf2::transformToEigen(tf_buffer_->lookupTransform(
            frames::ROBOT_TOOL_FRAME, frames::ROBOT_BASE_FRAME,
            tf2::TimePointZero, std::chrono::milliseconds(50)));
    } catch (const tf2::TransformException& ex) {
        RCLCPP_WARN_THROTTLE(get_logger(), *get_clock(), constants::LOG_THROTTLE_MS,
                             "Transform lookup failed: %s", ex.what());
        return;
    }

    if (!X_TB_.matrix().allFinite()) {
        RCLCPP_WARN_THROTTLE(get_logger(), *get_clock(), constants::LOG_THROTTLE_MS,
                             "Invalid transform (NaN/Inf)");
        return;
    }

    ft_proc_s_ = CompensateWrench(f_raw_s_, X_TB_, calibration_params_);

    // Step 2: Apply Deadband Filter (after compensation)
    for (int i = 0; i < 3; ++i) {
        if (std::abs(ft_proc_s_[i]) <= DEADBAND_FORCE) ft_proc_s_[i] = 0.0;
        if (std::abs(ft_proc_s_[i+3]) <= DEADBAND_TORQUE) ft_proc_s_[i+3] = 0.0;
    }

    wrench_probe_ = adjoint_probe_sensor_ * ft_proc_s_;

    Transform X_BP;
    try {
        X_BP = tf2::transformToEigen(tf_buffer_->lookupTransform(
            frames::ROBOT_BASE_FRAME, frame


#include "config.h"
#include "util.h"

using namespace util;

void check_unknown_keys(const json& j, const set<string>& known_keys) {
  for (auto it = j.begin(); it != j.end(); ++it) {
    if (known_keys.find(it.key()) == known_keys.end()) {
      throw runtime_error("Unknown key: " + it.key());
    }
  }
}

void from_json(const json& j, config_vec2_t& v) {
  if (!j.is_array() || j.size() != 2) {
    throw runtime_error("vec2 must be an array of two numbers");
  }

  if(!j[0].is_number())
    throw runtime_error(xorstr_("\n\"vec2.x\" must be a number"));
  j[0].get_to(v.x);
  if(!j[1].is_number())
    throw runtime_error(xorstr_("\n\"vec2.y\" must be a number"));
  j[1].get_to(v.y);
}

void from_json(const json& j, timer_t& t) {
  set<string> known_keys = {"text", "end_date", "anchor", "font_size",
                            "offset", "margin", "fixed_size", "detailed_time",
                            "text_color", "bg_color"};
  check_unknown_keys(j, known_keys);

  if(!j.contains("text"))
    throw runtime_error(xorstr_("\n\"text\" key required in timer config"));
  if(!j.at("text").is_string())
    throw runtime_error(xorstr_("\n\"text\" must be a string"));

  j.at("text").get_to(t.text);

  if (j.contains("end_date")) {
    if(!j.at("end_date").is_string())
      throw runtime_error(xorstr_("\n\"end_date\" must be a string"));
    string tmp_str;
    j.at("end_date").get_to(tmp_str);
    istringstream ss(tmp_str);
    tm tm = {};
    ss >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
    tm.tm_isdst = 0;
    if (ss.fail())
      throw runtime_error(xorstr_("\nDate in config parsing failed!\nRequired format: \"Y-m-d H:M:S\""));
    t.end_date = mktime(&tm);
  }else{
    throw runtime_error(xorstr_("\n\"end_date\" key required in timer config"));
  }

  if (j.contains("anchor")) {
    if(!j.at("text_color").is_string())
      throw runtime_error(xorstr_("\n\"text_color\" must be a string, and contains one of them\n  (top_left, top_middle, top_right,\n   left_middle, center, right_middle,\n   bottom_left, bottom_middle, bottom_right)"));
    string tmp_str;
    j.at("anchor").get_to(tmp_str);
    if(tmp_str == "top_left"){
      t.anchor = 0;
    }else if(tmp_str == "top_middle"){
      t.anchor = 1;
    }else if(tmp_str == "top_right"){
      t.anchor = 2;
    }else if(tmp_str == "left_middle"){
      t.anchor = 3;
    }else if(tmp_str == "center"){
      t.anchor = 4;
    }else if(tmp_str == "right_middle"){
      t.anchor = 5;
    }else if(tmp_str == "bottom_left"){
      t.anchor = 6;
    }else if(tmp_str == "bottom_middle"){
      t.anchor = 7;
    }else if(tmp_str == "bottom_right"){
      t.anchor = 8;
    }else{
      throw runtime_error(xorstr_("\nAnchor must be equal to one of \n  (top_left, top_middle, top_right,\n   left_middle, center, right_middle,\n   bottom_left, bottom_middle, bottom_right)\n"));
    }
  } else {
    t.anchor = 4;
  }

  if (j.contains("font_size")) {
    if(!j.at("font_size").is_number())
      throw runtime_error(xorstr_("\n\"font_size\" must be a number"));
    j.at("font_size").get_to(t.font_size);
  } else {
    t.font_size = 6;
  }

  if (j.contains("offset")) {
    if(!j.at("offset").is_array())
      throw runtime_error(xorstr_("\n\"offset\" must be an array"));
    j.at("offset").get_to(t.offset);
  } else {
    t.offset = {0, 0};
  }

  if (j.contains("margin")) {
    if(!j.at("margin").is_array())
      throw runtime_error(xorstr_("\n\"margin\" must be an array"));
    j.at("margin").get_to(t.margin);
  } else {
    t.margin = {0, 0};
  }

  if (j.contains("fixed_size")) {
    if(!j.at("fixed_size").is_array())
      throw runtime_error(xorstr_("\n\"fixed_size\" must be an array"));
    j.at("fixed_size").get_to(t.fixed_size);
  } else {
    t.fixed_size = {-1, -1};
  }

  if (j.contains("detailed_time")) {
    if(!j.at("detailed_time").is_boolean())
      throw runtime_error(xorstr_("\n\"detailed_time\" must be a boolean"));
    j.at("detailed_time").get_to(t.detailed_time);
  } else {
    t.detailed_time = false;
  }

  if (j.contains("text_color")) {
    if(!j.at("text_color").is_string())
      throw runtime_error(xorstr_("\n\"text_color\" must be a string"));
    try {
      string tmp_str;
      j.at("text_color").get_to(tmp_str);
      t.text_color = ((uint32_t)stoul(tmp_str, nullptr, 16));
    } catch(const exception& exc) {
      throw runtime_error(xorstr_("\nException caught while parsing \"text_color\" in timer config: ") + string(exc.what()));
    }
  } else {
    t.text_color = 0xffffffff;
  }

  if (j.contains("bg_color")) {
    if(!j.at("bg_color").is_string())
      throw runtime_error(xorstr_("\n\"bg_color\" must be a string"));
    try {
      string tmp_str;
      j.at("bg_color").get_to(tmp_str);
      t.bg_color = ((uint32_t)stoul(tmp_str, nullptr, 16));
    } catch(const exception& exc) {
      throw runtime_error(xorstr_("\nException caught while parsing \"bg_color\" in timer config: ") + string(exc.what()));
    }
  } else {
    t.bg_color =


#include "Platform.h"

// プラットフォームの初期化
void Platform::Initialize(const Vector3& pos, const Vector3& scale, Model* model, Camera* camera) {
	worldTransform_.Initialize();
	worldTransform_.translation_ = pos; // 位置設定
	worldTransform_.scale_ = scale;     // スケール設定
	model_ = model;
	camera_ = camera;
	scale_ = scale;

	// AABB（当たり判定ボックス）初期化
	// 基準サイズにスケールを乗算し半分のサイズを計算
	Vector3 halfSize = (baseSize_ * scale_) * 0.5f;
	aabb_.Set(pos - halfSize, pos + halfSize);
}

// スクロール速度の設定
void Platform::SetScrollSpeed(float speed) { platformScrollSpeed = speed; }

// プラットフォームの現在位置を取得
Vector3 Platform::GetWorldPosition() const { return worldTransform_.translation_; }

// プラットフォームの更新処理
void Platform::Update() {
	// Y軸方向にスクロール速度分移動
	worldTransform_.translation_.y += platformScrollSpeed;

	// AABBを現在の位置・スケールに合わせて更新
	Vector3 pos = worldTransform_.translation_;
	Vector3 halfSize = (baseSize_ * scale_) * 0.5f;
	aabb_.Set(pos - halfSize, pos + halfSize);

	// ワールド行列の更新
	worldTransform_.UpdateMatarix();
}

// プラットフォームの描画
void Platform::Draw() {
	if (model_) {
		model_->Draw(worldTransform_, *camera_);
	}
}


#include <iostream>
using std::cin;
using std::endl;
using std::cout;

#define tab "\t"
#define delimeter "\n----------------------------------------\n"

class List
{
	class Element
	{
		int Data;
		Element* pNext;
		Element* pPrev;
	public:
		Element(int Data, Element* pnext = nullptr, Element* pPrev = nullptr)
			:Data(Data), pNext(pNext), pPrev(pPrev)
		{
			cout << "EConstructor\t" << this << endl;
		}
		~Element()
		{
			cout << "EDestructor:\t" << this << endl;
		}
		friend class List;
	}*Head, *Tail; //Объекты классов и структур и указатели на эти объекты можно объявлять непосредственно после описания классов и структур

	size_t size;   //Размер списка. size_t - это typedef на 'unsigned int.
	class ConstBaseIterator
	{
	protected:
		Element* Temp;
	public:
		ConstBaseIterator(Element* Temp = nullptr) :Temp (Temp){}
		~ConstBaseIterator() {}

		//Comparison operators:
		bool operator == (const ConstBaseIterator& other)const
		{
			return this->Temp == other.Temp;
		}
		bool operator != (const ConstBaseIterator& other)const
		{
			return this->Temp != other.Temp;
		}
		int operator*()const
		{
			return Temp->Data;
		}
	};
public:
	class ConstIterator :public ConstBaseIterator
	{
	public:
		ConstIterator(Element* Temp = nullptr) :ConstBaseIterator(Temp) {}
		~ConstIterator() {}

		ConstIterator& operator++()
		{
			Temp = Temp->pNext;
			return *this;
		}
		ConstIterator operator++(int)
		{
			ConstIterator old = *this;
			Temp = Temp->pNext;
			return old;
		}
		ConstIterator& operator--()
		{
			Temp = Temp->pPrev;
			return *this;
		}
		ConstIterator operator--(int)
		{
			ConstIterator old = *this;
			Temp = Temp->pPrev;
			return old;
		}
	};
	class ConstReverseIterator :public ConstBaseIterator
	{
	public:
		ConstReverseIterator(Element* Temp = nullptr) :ConstBaseIterator(Temp) {}
		~ConstReverseIterator() {}

		//				Increment/Decrement:
		ConstReverseIterator& operator++()
		{
			Temp = Temp->pPrev;
			return *this;
		}
		ConstReverseIterator operator++(int)
		{
			ConstReverseIterator old = *this;
			Temp = Temp->pPrev;
			return old;
		}
		ConstReverseIterator& operator--()
		{
			Temp = Temp->pNext;
			return *this;
		}
		ConstReverseIterator operator--(int)
		{
			ConstReverseIterator old = *this;
			Temp = Temp->pNext;
			return old;
		}
	};
	class Iterator :public ConstIterator
	{
	public:
		Iterator(Element* Temp) :ConstIterator(Temp) {}
		~Iterator() {}
		int& operator*()
		{
			return Temp->Data;
		}
	};
	class ReverseIterator :public ConstReverseIterator
	{
	public:
		ReverseIterator(Element* Temp) :ConstReverseIterator(Temp) {}
		~ReverseIterator() {}
		int& operator*()
		{
			return Temp->Data;
		}
	};
	////////////////////////////////////////////////
	ConstIterator begin()const
	{
		return Head;
	}
	ConstIterator end()const
	{
		return nullptr;
	}
	ConstReverseIterator rbegin()const
	{
		return Tail;
	}
	ConstReverseIterator rend()const
	{
		return nullptr;
	}
	Iterator begin()
	{
		return Head;
	}
	Iterator end()
	{
		return nullptr;
	}
	ReverseIterator rbegin()
	{
		return Tail;
	}
	ReverseIterator rend()
	{
		return nullptr;
	}
	List()
	{
		Head = Tail = nullptr;
		size = 0;
		cout << "LConstructor\t" << this << endl;
	}
	List(const std::initializer_list<int>& il) :List()
	{
		for (int const* it = il.begin(); it != il.end(); ++it)
		{
			push_back(*it);
		}
		cout << "ILConstructor:\t" << this << endl;
	}
	List(const List& other) :List()
	{
		*this = other;
		cout << "LCopyConstructor:\t" << this << endl;
	}
	~List()
	{
		//while (Head)pop_front();
		while (Tail)pop_back();
		cout << "LDestructor\t" << this << endl;
	}
	//Operators:
	List& operator = (const List& other)
	{
		if (this == &other) return *this;
		while (Head)pop_front();
		for (Element* Temp = other.Head; Temp; Temp = Temp->pNext)
			push_back(Temp->Data);
		cout << "LCopyAssignment:\t" << this << endl;
		return *this;
	}

	// Adding elements:
	void push_front(int Data)
	{
		//1) Создаем элемент, в котором будет хранится добавляемое значение:
		Element* New = new Element(Data);

		if (Head == nullptr && Tail == nullptr)
		{
			Head = Tail = New;
		}
		else
		{

			//2) Пристыковываем новый элемент к списку:
			New->pNext = Head;

			//3) Пристыковываем начальный элемент списка к новому элементу:
			Head->pPrev = New;

			//4) Делаем новый элемент начальным элементом списка:
			Head = New;

		}

		size++;
	}
	void push_back(int Data)
	{
		//1) Создаем новый элемент:
		Element* New = new Element(Data);
		if (Head == nullptr && Tail == nullptr)
		{
			Head = Tail = New;
		}
		else
		{
			//2) Цепляем новый элемент за хвост списка:
			New->pPrev = Tail;

			//3) Пристыковываем список к новому элементу:
			Tail->pNext = New;

			//4) Делаем новый элемент хвостом списка:
			Tail = New;
		}
		size++;
	}

	void insert(int Data, int Index)
	{
		if (Index < 0)return;
		if (Index == 0 || size == 0)return push_front(Data);
		if (Index >= size)return push_back(Data);
		//1) Доходим до нужного элемента:
		Element* Temp;
		if (I


#include "../include/locallru/local_lru.hpp"
#include "../src/lock_cache.hpp"

#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#include <vector>
#include <string>
#include <sstream>
#include <filesystem>
#include <algorithm>
#include <mutex>

using namespace locallru;
using namespace lockedlru;

struct PriceData {
    std::vector<double> prices;
};

std::mutex cout_mutex;

PriceData preload_csv(const std::string& filepath, const std::string& sym) {
    PriceData pdata;
    std::ifstream file(filepath);
    if (!file.is_open()) {
        std::lock_guard<std::mutex> lock(cout_mutex);
        std::cerr << "Error opening file: " << filepath << std::endl;
        return pdata;
    }

    std::string line;
    std::getline(file, line); // skip header
    while (std::getline(file, line)) {
        std::stringstream ss(line);
        std::string date, open, high, low, close, adjclose, volume;
        std::getline(ss, date, ',');
        std::getline(ss, open, ',');
        std::getline(ss, high, ',');
        std::getline(ss, low, ',');
        std::getline(ss, close, ',');
        std::getline(ss, adjclose, ',');
        std::getline(ss, volume, ',');

        if (close.empty() || close == "null" || close == "N/A") continue;

        try {
            pdata.prices.push_back(std::stod(close));
        } catch (const std::exception&) {
            std::lock_guard<std::mutex> lock(cout_mutex);
            std::cerr << "Warning: skipping invalid price '" << close << "' for symbol " << sym << std::endl;
        }
    }

    return pdata;
}

int main() {
    std::filesystem::create_directories("../results");

    std::vector<std::string> symbols = {"AAPL", "MSFT", "GOOG", "TSLA"};
    std::vector<PriceData> all_data(symbols.size());

    // Preload CSVs
    for (size_t i = 0; i < symbols.size(); i++) {
        std::string path = "../data/" + symbols[i] + ".csv";
        all_data[i] = preload_csv(path, symbols[i]);
    }

    // Setup caches
    auto lockfree = LocalCache<double>::initialize(1000, 0); // no TTL
    LockCache<std::string, double> locking(1000);

    std::ofstream log_file("../results/trading_benchmark.log");
    log_file << "[Benchmark Start]\nSymbols: ";
    for (auto& s : symbols) log_file << s << " ";
    log_file << "\n---------------------------------\n";

    auto start_total = std::chrono::high_resolution_clock::now();

    for (size_t i = 0; i < symbols.size(); i++) {
        auto& pdata = all_data[i];

        log_file << symbols[i] << " processing " << pdata.prices.size() << " rows\n";

        for (auto price : pdata.prices) {
            // Lock-free
            auto t1_start = std::chrono::high_resolution_clock::now();
            lockfree.add_item(symbols[i], price);
            auto val1 = lockfree.get_item(symbols[i]);
            auto t1_end = std::chrono::high_resolution_clock::now();

            // Locking
            auto t2_start = std::chrono::high_resolution_clock::now();
            locking.put(symbols[i], price);
            auto val2 = locking.get(symbols[i]);
            auto t2_end = std::chrono::high_resolution_clock::now();

            log_file << symbols[i] << " price=" << price
                     << " lockfree_ns="
                     << std::chrono::duration_cast<std::chrono::nanoseconds>(t1_end - t1_start).count()
                     << " locking_ns="
                     << std::chrono::duration_cast<std::chrono::nanoseconds>(t2_end - t2_start).count()
                     << "\n";
        }
    }

    auto end_total = std::chrono::high_resolution_clock::now();
    double elapsed_sec = std::chrono::duration<double>(end_total - start_total).count();
    log_file << "Total elapsed time (s): " << elapsed_sec << "\n";
    log_file << "[Benchmark End]\n";

    std::cout << "Benchmark complete. Results written to ../results/trading_benchmark.log\n";

    return 0;
}