#include <unordered_map>
#include <iostream>
#include <string>
#include "block.h"
#include "transaction.h"
#include "wallet.h"
std::unordered_map<std::string, Block*> blockIndex;
std::vector<Block*> block_chain;

void addBlock(Block* block_to_add){
    // In a real implementation, you would have a more robust way to get the previous block
    if (block_chain.empty() && block_to_add->index == 0) { // Genesis block case
        // Genesis block might have different validation rules
        // For now, we accept it as is.
        balances[block_to_add->pk_miner] += block_to_add->miner_reward;
        block_chain.push_back(block_to_add);
        blockIndex[block_to_add->hash_current] = block_to_add;
        return;
    }

    // Get the previous block for validation
    const Block* previous_block = block_chain.back();

    // === VALIDATION CHECKS ===

    // 1. Check connection to the chain
    if (block_to_add->index != previous_block->index + 1) {
        std::cout << "Validation Failed: Invalid block index." << std::endl;
        return;
    }
    if (block_to_add->hash_previous != previous_block->hash_current) {
        std::cout << "Validation Failed: Previous block hash does not match." << std::endl;
        return;
    }

    // 2. Reconstruct the header string to verify the Proof of Work
    std::string header_to_check = build_header_string(
        block_to_add->index,
        block_to_add->hash_previous,
        block_to_add->pk_miner,
        block_to_add->merkel_root,
        block_to_add->state_root,
        block_to_add->miner_reward,
        block_to_add->timestamp
    );
    // 3. Check Proof of Work
    // We need a check_pow function here. Assuming it exists and works as discussed.
    if (!check_pow(header_to_check, block_to_add->nonce, block_to_add->hash_current)) {
        std::cout << "Validation Failed: Invalid Proof of Work." << std::endl;
        return;
    }

    // 4. Validate Transaction Merkle Root
    std::vector<std::string> tx_hashes;
    for (const auto& tx : block_to_add->transactions_block) {
        tx_hashes.push_back(tx.full_transaction_hash);
    }
    std::string calculated_merkle_root = merkle_hash(tx_hashes);

    if (calculated_merkle_root != block_to_add->merkel_root) {
        std::cout << "Validation Failed: Transaction Merkle Root does not match." << std::endl;
        return;
    }

    std::unordered_map<std::string, uint64_t> temp_balances = balances;
    std::vector<Transaction> valid_txs_for_block;
    for (size_t i = 0; i < block_to_add->transactions_block.size(); i++)
    {
        if(!sign_verifier(block_to_add->transactions_block[i].message,block_to_add->transactions_block[i].signature,block_to_add->transactions_block[i].sender_public_key)){
            std::cout << "Transaction verif failed" << std::endl;
            // If signature verification fails, the transaction is invalid.
            // In a real system, this would likely lead to the block being rejected or the transaction being excluded.
            // For now, we'll just skip it and ensure the block doesn't contain invalid transactions.
            continue;
        };
        if (temp_balances.count(block_to_add->transactions_block[i].sender_public_key) && temp_balances.at(block_to_add->transactions_block[i].sender_public_key) >= block_to_add->transactions_block[i].amount) {
                temp_balances.at(block_to_add->transactions_block[i].sender_public_key) -= block_to_add->transactions_block[i].amount;
                temp_balances[block_to_add->transactions_block[i].reciever_public_key] += block_to_add->transactions_block[i].amount;
                valid_txs_for_block.push_back(block_to_add->transactions_block[i]);
        } else {
                std::cout << "Miner ignoring invalid transaction from: " << block_to_add->transactions_block[i].sender_public_key << std::endl;
                // If balance is insufficient, the transaction is invalid.
                continue;
        }
    }

    // 5. Validate all transactions in the block were valid
    if (valid_txs_for_block.size() != block_to_add->transactions_block.size()) {
        std::cout << "Validation Failed: Block contains invalid transactions." << std::endl;
        return;
    }

    // Now that all transactions are valid, let's add the miner's reward to the temporary balances
    temp_balances[block_to_add->pk_miner] += block_to_add->miner_reward;

    // 6. Validate State Root (after applying all transactions and miner reward)
    if (calculateStateMerkleRoot(temp_balances) != block_to_add->state_root) {
        std::cout << "Validation Failed: State Merkle Root does not match." << std::endl;
        return;
    }

    // === ALL VALIDATION PASSED ===
    // Update the global state with the validated temporary balances
    balances = temp_balances;

    // Add the block to the chain
    block_chain.push_back(block_to_add);
    blockIndex[block_to_add->hash_current] = block_to_add;

    std::cout << "Block successfully adde


/*
 * Bài toán LeetCode: Longest Palindromic Substring (Chuỗi con đối xứng dài nhất - Quy hoạch động)
 *
 * Mô tả bài toán:
 * Cho một chuỗi `s`, trả về chuỗi con đối xứng dài nhất trong `s`.
 *
 * ---
 *
 * Hướng giải quyết: Quy hoạch động (Dynamic Programming)
 *
 * Ý tưởng cốt lõi là xây dựng một bảng boolean 2D `dp[i][j]`, trong đó `dp[i][j]` là true
 * nếu chuỗi con từ chỉ số `i` đến `j` (bao gồm cả hai) là một chuỗi đối xứng, và false nếu ngược lại.
 *
 * 1. Định nghĩa trạng thái DP:
 *    - `dp[i][j]`: Một giá trị boolean cho biết `s.substr(i, j-i+1)` có phải là chuỗi đối xứng hay không.
 *
 * 2. Công thức truy hồi DP:
 *    - Một chuỗi con `s[i..j]` là một chuỗi đối xứng nếu:
 *      a) Các ký tự ở hai đầu giống nhau (`s[i] == s[j]`).
 *      b) Chuỗi con bên trong `s[i+1..j-1]` cũng là một chuỗi đối xứng (`dp[i+1][j-1] == true`).
 *
 * 3. Các trường hợp cơ sở:
 *    - Tất cả các chuỗi con có độ dài 1 đều là chuỗi đối xứng (`dp[i][i] = true`).
 *    - Đối với các chuỗi con có độ dài 2, `dp[i][i+1]` là true nếu `s[i] == s[i+1]`.
 *
 * 4. Điền vào bảng DP:
 *    - Chúng ta có thể điền vào bảng bằng cách lặp qua các độ dài chuỗi con, từ 1 đến
 *      độ dài của chuỗi `n`.
 *    - Với mỗi độ dài `len`, chúng ta lặp qua tất cả các chỉ số bắt đầu có thể `i`. Chỉ số
 *      kết thúc `j` sau đó là `i + len - 1`.
 *    - Chúng ta áp dụng công thức truy hồi để điền vào `dp[i][j]`.
 *
 * 5. Tìm chuỗi đối xứng dài nhất:
 *    - Trong khi điền vào bảng, chúng ta theo dõi chỉ số bắt đầu và độ dài lớn nhất
 *      của chuỗi đối xứng tìm thấy cho đến nay.
 *    - Bất cứ khi nào chúng ta đặt `dp[i][j]` thành true, chúng ta kiểm tra xem độ dài hiện tại (`j - i + 1`)
 *      có lớn hơn độ dài tối đa đã thấy không. Nếu có, chúng ta cập nhật độ dài tối đa và
 *      lưu trữ chỉ số bắt đầu `i`.
 *
 * 6. Trả về kết quả:
 *    - Sau khi bảng được điền đầy, chúng ta có thể xây dựng chuỗi con đối xứng dài nhất
 *      bằng cách sử dụng chỉ số bắt đầu và độ dài tối đa đã lưu.
 *
 * Phân tích độ phức tạp:
 * - Độ phức tạp thời gian: O(N^2), trong đó N là độ dài của chuỗi. Chúng ta cần điền vào
 *   bảng DP N x N, mất O(N^2) thời gian.
 * - Độ phức tạp không gian: O(N^2) để lưu trữ bảng DP.
 *
 * ---
 *
 * Ghi chú về giải pháp đã cài đặt:
 * Giải pháp được cung cấp sử dụng đúng bảng DP. Nó khởi tạo bảng với các trường hợp cơ sở
 * (độ dài 1, 2, 3) và sau đó sử dụng một tập hợp vòng lặp thứ hai để điền vào phần còn lại của bảng dựa trên
 * công thức truy hồi `dp[i][j] = dp[i+1][j-1]`. Mặc dù cách này hoạt động, phương pháp tiêu chuẩn
 * lặp theo độ dài chuỗi con thường dẫn đến một cách cài đặt sạch sẽ và ngắn gọn hơn.
 */
#include <bits/stdc++.h>

using namespace std;

string longestPalindrome(string s)
{
    int size = s.length();

    if (size < 2)
    {
        return s;
    }

    if (size == 2)
    {
        if (s[0] == s[1])
        {
            return s;
        }
        return s.substr(0, 1);
    }

    int dp[1000][1000];
    for (int i = 0; i < size; i++)
    {
        for (int j = i; j < size; j++)
        {
            if (i == j)
            {
                dp[i][j] = 1;
            }
            else if (j == i + 1 && s[i] == s[j])
            {
                dp[i][j] = 1;
            }
            else if (j == i + 2 && s[i] == s[j])
            {
                dp[i][j] = 1;
            }
            else if (s[i] != s[j])
            {
                dp[i][j] = 0;
            }
            else
            {
                dp[i][j] = -1;
            }
        }
    }

    for (int j = 0; j < size; j++)
    {
        for (int i = 0; i < size - j; i++)
        {
            if (dp[i][i + j] > -1)
            {
                continue;
            }
            dp[i][i + j] = dp[i + 1][i + j - 1];
        }
    }

    int maxLength = 0;
    string result;
    for (int i = 0; i < size; i++)
    {
        for (int j = i; j < size; j++)
        {
            if (dp[i][j] == 1 && j - i + 1 > maxLength)
            {
                maxLength = j - i + 1;
                result = s.substr(i, maxLength);
            }
        }
    }
    return result;
}

int main()
{
    string s = "xaabacxcabaaxcabaax";
    string result = longestPalindrome(s);
    cout << "Longest palindrome: " << result << endl;
}


#include<iostream>       // input/output Library
#include<string>        // string Library
#include<cmath>        // cmath Library(Mathematical Calculations) //square
#include<iomanip>     // input/output manipulator Library(Precision Output)
#include<cstdlib>    // c standandard Library(Random Generation)
#include<ctime>     // Time Calculation Library //time
#include<windows.h>// Windows Library(Sound Beeps) // console color
#include <thread> // Sleep Effect
#include <chrono>// Precise Time Intervals
using namespace std;

// These below are the color numbers to display output with colors of your choice

//Number	Color
//---------------
//0   		Black
//1			Blue
//2			Green
//3			Aqua
//4			Red
//5			Purple
//6			Yellow
//7			White (Default)
//8			Gray
//9			Light Blue
//10		Light Green
//11		Light Aqua
//12		Light Red
//13		Light Purple
//14		Light Yellow
//15		Bright White

// Colored + speed + color version (with default params)
void typeEffect(string text, int speed = 5, int color = 7) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, color);

    for (int i = 0; i < text.length(); i++) {
        cout << text[i];
        Sleep(speed);
    }
    SetConsoleTextAttribute(hConsole, 7);
    cout << endl;
}

// Simple delay-only version (no default delay!)
void typeEffect(const string& text, int delayMs) {
    for (char c : text) {
        cout << c << flush;
        this_thread::sleep_for(chrono::milliseconds(delayMs));
    }
    cout << endl;
}

class User{    //Base Class
	protected:
		string userName;

	public:

	void showIntro(){
    typeEffect("************************************\n");
    typeEffect("      10million Productions       ");
    typeEffect("          By: M.Talha              ");
    typeEffect("************************************\n\n");

    this_thread::sleep_for(chrono::seconds(3));
    system("cls");
}

	void title(){
		 typeEffect( "\n***********************************************\n ",40 ,3);
		 typeEffect( "  A Hybrid Quantum-Driven Interstellar System       \n ",40 ,3);
		 typeEffect( "***********************************************\n\n ",40 ,3);
		Beep(500, 700);
	}

	void getUserName(){
		 typeEffect( "Enter your name Quanta-Explorer:  ",40 ,6);
		getline(cin, userName);
	}

	void displayUserName(){
		 typeEffect( "Welcome "+ userName +" to The 10million Hybrid Quantum-Driven Interstellar System, ",40 ,8);
		 typeEffect( " where the future of interstellar exploration and cosmic innovation awaits your command!",40 ,8);
		Beep(800, 500);
	}

	void showSpaceship() {
     typeEffect( "        _   " ,40, 10);
     typeEffect( "       / \" ",40, 10);
     typeEffect( "      / _ \"" ,40, 10);
     typeEffect( "     | (_) |" ,40, 10);
     typeEffect( "     | | | |" ,40, 10);
     typeEffect( "     |_| |_|" ,40, 10);
}

};

class GalacticNexus : public User{   //GalacticNexus Class
public:
    void galacticNexus();
    void planets();
    void stars();
    void celestialBodies();

public:
    // SUBfunctions of Planets
    void planetaryInsight();
    void gravitationalWeightCalculator();
    void orbitalVelocityCalculator();

    // SUBfunctions of Stars
    void stellarChronicle();
    void stellarGravityCalculator();
    void solarFlareIntensityAnalyzer();

    // SUBfunctions of Celestial Bodies
    void cosmicMystery();
    void quantumGravityCalculator();
    void eventHorizonExplorer();
};

    // Function Definitions
void GalacticNexus::galacticNexus(){
     typeEffect( "Welcome " + userName + " in the Galactic Nexus",40 ,8);
     typeEffect( "Here you can access the following options:",40 ,8);
    Beep(1100,500);

    int galactic;
    do{
         typeEffect( "1. Planets\n ",40 ,14);
         typeEffect( "2. Stars\n ",40 ,14);
         typeEffect( "3. Celestial Bodies\n ",40 ,14);
         typeEffect( "4. Exit\n ",40 ,4);
         typeEffect( "\nChoose the option:\n ",40 ,6);
        cin >> galactic;

        switch(galactic)
        {
            case 1: planets(); break;
            case 2: stars(); break;
            case 3: celestialBodies(); break;
            case 4:  typeEffect( "Exiting the Galactic Nexus...\n ",40 ,12); return;
            default:  typeEffect( "Invalid Input!\n ",40 ,4);
        }
    } while(galactic != 4);
}

	 void GalacticNexus::planets(){     // Planet function
        int option;

        do {
             typeEffect( "\nWelcome to the Planets section. Choose an option:\n ",40 ,8);
             typeEffect( "1. Planetary Insight (Basic Information)\n ",40 ,14);
             typeEffect( "2. Gravitational Weight Calculator\n ",40 ,14);
             typeEffect( "3. Orbital Velocity Calculator\n ",40 ,14);
             typeEffect( "4. Go Back\n ",40 ,4);
             typeEffect( "Ente


#include "GameplayTags/CCTags.h"

namespace CCTags
{
	namespace SetByCaller
	{
		UE_DEFINE_GAMEPLAY_TAG_COMMENT(Projectile, "CCTags.SetByCaller.Projectile", "Tag for Set by Caller Magnitude for Projectiles")

	}

	namespace CCAbilities
	{
		UE_DEFINE_GAMEPLAY_TAG_COMMENT(ActivateOnGiven, "CCTags.CCAbilities.ActivateOnGiven", "Tag for Abilities that should activate immediately once given.")

		UE_DEFINE_GAMEPLAY_TAG_COMMENT(Primary, "CCTags.CCAbilities.Primary", "Tag for the Primary Ability")
		UE_DEFINE_GAMEPLAY_TAG_COMMENT(Secondary, "CCTags.CCAbilities.Secondary", "Tag for the Secondary Ability")
		UE_DEFINE_GAMEPLAY_TAG_COMMENT(Tertiary, "CCTags.CCAbilities.Tertiary", "Tag for the Tertiary Ability")

		namespace Enemy
		{
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(Attack, "CCTags.CCAbilities.Enemy.Attack", "Enemy Attack Tag")
		}
	}

	namespace Events
	{
		UE_DEFINE_GAMEPLAY_TAG_COMMENT(KillScored, "CCTags.Events.KillScored", "Tag for the KillScored Event")

		namespace Player
		{
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(HitReact, "CCTags.Events.Player.HitReact", "Tag for the Player HitReact Event")
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(Death, "CCTags.Events.Player.Death", "Tag for the Player Death Event")
		}

		namespace Enemy
		{
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(HitReact, "CCTags.Events.Enemy.HitReact", "Tag for the Enemy HitReact Event")
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(EndAttack, "CCTags.Events.Enemy.EndAttack", "Tag for the Enemy Ending an Attack")
			UE_DEFINE_GAMEPLAY_TAG_COMMENT(MeleeTraceHit, "CCTags.Events.Enemy.MeleeTraceHit", "Tag for the Enemy Melee Trace Hit")
		}
	}
}


////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>

#include <SFML/Audio.hpp>

#include <filesystem>
#include <random>
#include <string>

#include <cmath>
#include <cstdlib>

#ifdef SFML_SYSTEM_IOS
#include <SFML/Main.hpp>
#endif

namespace
{
std::filesystem::path resourcesDir()
{
#ifdef SFML_SYSTEM_IOS
    return "";
#else
    return "resources";
#endif
}
} // namespace

////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
    std::random_device rd;
    std::mt19937       rng(rd());

    // Define some constants
    const float        gameWidth  = 800;
    const float        gameHeight = 600;
    const sf::Vector2f paddleSize(25, 100);
    const float        ballRadius = 10.f;

    // Create the window of the application
    sf::RenderWindow window(sf::VideoMode({static_cast<unsigned int>(gameWidth), static_cast<unsigned int>(gameHeight)}, 32),
                            "SFML Tennis",
                            sf::Style::Titlebar | sf::Style::Close);
    window.setVerticalSyncEnabled(true);

    // Load the sounds used in the game
    const sf::SoundBuffer ballSoundBuffer(resourcesDir() / "ball.wav");
    sf::Sound             ballSound(ballSoundBuffer);

    // Create the SFML logo texture:
    const sf::Texture sfmlLogoTexture(resourcesDir() / "sfml_logo.png");
    sf::Sprite        sfmlLogo(sfmlLogoTexture);
    sfmlLogo.setPosition({170.f, 50.f});

    // Create the left paddle
    sf::RectangleShape leftPaddle;
    leftPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
    leftPaddle.setOutlineThickness(3);
    leftPaddle.setOutlineColor(sf::Color::Black);
    leftPaddle.setFillColor(sf::Color(100, 100, 200));
    leftPaddle.setOrigin(paddleSize / 2.f);

    // Create the right paddle
    sf::RectangleShape rightPaddle;
    rightPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
    rightPaddle.setOutlineThickness(3);
    rightPaddle.setOutlineColor(sf::Color::Black);
    rightPaddle.setFillColor(sf::Color(200, 100, 100));
    rightPaddle.setOrigin(paddleSize / 2.f);

    // Create the ball
    sf::CircleShape ball;
    ball.setRadius(ballRadius - 3);
    ball.setOutlineThickness(2);
    ball.setOutlineColor(sf::Color::Black);
    ball.setFillColor(sf::Color::White);
    ball.setOrigin({ballRadius / 2.f, ballRadius / 2.f});

    // Open the text font
    const sf::Font font(resourcesDir() / "tuffy.ttf");

    // Initialize the pause message
    sf::Text pauseMessage(font);
    pauseMessage.setCharacterSize(40);
    pauseMessage.setPosition({170.f, 200.f});
    pauseMessage.setFillColor(sf::Color::White);

#ifdef SFML_SYSTEM_IOS
    pauseMessage.setString("Welcome to SFML Tennis!\nTouch the screen to start the game.");
#else
    pauseMessage.setString("Welcome to SFML Tennis!\n\nPress space to start the game.");
#endif

    // Define the paddles properties
    sf::Clock      aiTimer;
    const sf::Time aiTime           = sf::seconds(0.1f);
    const float    paddleSpeed      = 400.f;
    float          rightPaddleSpeed = 0.f;
    const float    ballSpeed        = 400.f;
    sf::Angle      ballAngle        = sf::degrees(0); // to be changed later

    sf::Clock clock;
    bool      isPlaying = false;
    while (window.isOpen())
    {
        // Handle events
        while (const std::optional event = window.pollEvent())
        {
            // Window closed or escape key pressed: exit
            if (event->is<sf::Event::Closed>() ||
                (event->is<sf::Event::KeyPressed>() &&
                 event->getIf<sf::Event::KeyPressed>()->code == sf::Keyboard::Key::Escape))
            {
                window.close();
                break;
            }

            // Space key pressed: play
            if ((event->is<sf::Event::KeyPressed>() &&
                 event->getIf<sf::Event::KeyPressed>()->code == sf::Keyboard::Key::Space) ||
                event->is<sf::Event::TouchBegan>())
            {
                if (!isPlaying)
                {
                    // (re)start the game
                    isPlaying = true;
                    clock.restart();

                    // Reset the position of the paddles and ball
                    leftPaddle.setPosition({10.f + paddleSize.x / 2.f, gameHeight / 2.f});
                    rightPaddle.setPosition({gameWidth - 10.f - paddleSize.x / 2.f, gameHeight / 2.f});
                    ball.setPosition({gameWidth / 2.f, gameHeight / 2.f});

                    // Reset the ball angle
                    do
                    {
                        // Make sure the ball initial angle is not too much vertical
                        ballAngle = sf::degrees(std::uniform_real_distribution<float>(0, 360)(rng));
                    } while (std::abs(std::cos(ballAngle.asRadians())


#include "DarkStar/Manager/AssetManager.h"

#include "DarkStar/Manager/LogManager.h"
#include "DarkStar/Utils/AssetUtils.h"

#include "SFML/Graphics/Font.hpp"

#include "nlohmann/json.hpp"

#include <fstream>

namespace DarkStar
{
	void CAssetManager::Startup()
	{
		DS_CORE_TRACE("Asset Manager Startup");

		try
		{
			LoadFromFile("assets/assets.json");
		}
		catch (std::exception error)
		{
			DS_CLIENT_CRITICAL(error.what());
		}
	}

	void CAssetManager::Shutdown()
	{
		DS_CORE_TRACE("Asset Manager Shutdown");
	}

	void CAssetManager::LoadFromFile(const std::string& filePath)
	{
		std::ifstream file(filePath);
		if (!file.is_open())
		{
			throw std::runtime_error("AssetManager::LoadFromFile " + filePath + " could not be opened");
		}

		const nlohmann::json assetTypeData = nlohmann::json::parse(file);
		for (const auto& [assetName, assetFilePath] : assetTypeData[CAssetUtils::m_FontAssetKey].items())
		{
			const auto& fontIterator = std::find_if(
				CAssetUtils::m_FontStringMatchArray.begin(),
				CAssetUtils::m_FontStringMatchArray.end(),
				[assetName](const std::pair<Identifiers::EFonts, std::string>& currentMatch)
			{
				return assetName == currentMatch.second;
			});
			if (fontIterator != nullptr)
			{
				LoadAsset<Identifiers::EFonts, sf::Font>(fontIterator->first, assetFilePath.get<std::string>(), CAssetUtils::m_FontLoaderFunction);
				return;
			}

			DS_CORE_ERROR("AssetManager::LoadFromFile couldn't load asset " + assetName);
		}
	}
}


#include <iostream>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shader.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define CANVAS_HEIGHT 600
#define CANVAS_WIDTH CANVAS_HEIGHT
#define COLOR_WHEEL_SIDE 200

#define HISTORY 16
#define MAX_HIST_MOV HISTORY

#define initialize_quad(x, y, width, height, s1, t1, s2, t2) \
	        x,          y, -1,   0, 0,  s1, t1, \
	x + width,          y, -1,   1, 0,  s2, t1, \
	x + width, y + height, -1,   1, 1,  s2, t2, \
	        x, y + height, -1,   0, 1,  s1, t2

union Vec2 {
	struct { float x, y; };
	struct { float width, height; };
};

union Vec2i {
	struct { int x, y; };
	struct { int width, height; };
};

union Vec3 {
	struct { float x, y, z; };
	struct { float r, g, b; };
	struct { float h, s, v; };
};

struct Vec4uc {
	unsigned char r, g, b, a;
};

struct Color {
	Vec3 rgb, hsv;
};

struct Vertex {
	Vec3 pos;
	Vec2 nor_coord;
	Vec2 tex_coord;
};

struct Quad {
	Vertex v[4];
};

enum UiElement {
	CANVAS,
	COLOR_WHEEL,
	SV_SQUARE,
	BUTTON_CLEAR_CANVAS,
	BUTTON_UNDO,
	BUTTON_REDO,
	BUTTON_BRUSH,
	BUTTON_BUCKET
};

Vec2 window_size = { CANVAS_WIDTH + COLOR_WHEEL_SIDE + 48, CANVAS_HEIGHT + 48 };
Vec2 mouse = { 0.0, 0.0 };
Vec3 wheel_color = { 1.0, 0.0, 0.0 };
Color active_color = { .rgb = wheel_color, .hsv = { 0.0, 1.0, 1.0 } };
int active_ui_element = -1, hot_ui_element = -1;
//Vec2i last_pix = { -1, -1 };
int brush_r = 5;
int active_tool = BUTTON_BRUSH;
Vec4uc first_filled_pix;

struct CanvasHistory {
	int index, past, future;
	Vec4uc *colors[HISTORY];
	Vec2i coords[3];
};

struct Canvas {
	Vec2i size;
	float scale;
	Vec4uc *colors;
	GLuint texture;

	CanvasHistory history;
};

Canvas canvas = {
	.size = { 512, 512 },
	.scale = 1.0,
	.history = { .index = 1, .past = 0, .future = 0 }
};

struct Ui {
	int active, hot;
};

Ui ui = { -1, -1 };

glm::mat4 model, view, projection;
int loc_model, loc_view, loc_projection;
int loc_hot_ui_element, loc_active_tool;
int loc_color_wheel_center, loc_color_wheel_radius;
int loc_wheel_color, loc_active_color, loc_hsv;
int loc_canvas, loc_tex_btn;

void change_canvas_unit(int row, int column) {
	if (row < 0 || row >= canvas.size.height) return;
	if (column < 0 || column >= canvas.size.width) return;
	*(canvas.colors + row*canvas.size.width + column) = {
		active_color.rgb.r * 255,
		active_color.rgb.g * 255,
		active_color.rgb.b * 255,
		255
	};
}

void clear_canvas(bool reset_history) {
	for (int i = 0; i < canvas.size.height; i++) {
		for (int j = 0; j < canvas.size.width; j++) {
			*(canvas.colors + i*canvas.size.width + j) = { 0, 0, 0, 0 };
			*(canvas.history.colors[canvas.history.index] + i*canvas.size.width + j) = { 0, 0, 0, 0 };
		}
	}

	if (reset_history) {
		//canvas.history = { .past = 0, .future = 0 };
		canvas.history.past = 0;
		canvas.history.future = 0;
		canvas.history.index = (canvas.history.index + 1) % HISTORY;
		canvas.history.coords[0] = { -1, -1 };
		canvas.history.coords[1] = { -1, -1 };
		canvas.history.coords[2] = { -1, -1 };
	}

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, canvas.size.width, canvas.size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, canvas.colors);
	glGenerateMipmap(GL_TEXTURE_2D);
}

int clamp(int value, int minimum, int maximum) {
	if (value < minimum) return minimum;
	if (value > maximum) return maximum;
	return value;
}

void join_points(Vec2i start, Vec2i end) {
	//printf("coords0 = (%d, %d)   start = (%d, %d)   end = (%d, %d)\n", canvas.history.coords[0].x, canvas.history.coords[0].y, start.x, start.y, end.x, end.y);
	if (start.x + start.y == -2) return;

	if (start.x == end.x) {
		int dir = end.y > start.y? 1: -1;
		start.y = clamp(start.y, -1, canvas.size.height);
		end.y = clamp(end.y, -1, canvas.size.height);
		for (int y = start.y; y != end.y; y += dir) {
			for (int w = -brush_r; w <= brush_r; w++) {
				int x = start.x + w;
				change_canvas_unit(y, x);
			}
		}
		return;
	}

	if (start.y == end.y) {
		int dir = end.x > start.x? 1: -1;
		start.x = clamp(start.x, -1, canvas.size.width);
		end.x = clamp(end.x, -1, canvas.size.width);
		//printf("after clamp:   start = (%d, %d)   end = (%d, %d)\n", start.x, start.y, end.x, end.y);
		for (int x = start.x; x != end.x; x += dir) {
			for (int h = -brush_r; h <= brush_r; h++) {
				int y = start.y + h;
				change_canvas_unit(y, x);
			}
		}
		return;
	}

	int dy = fabsf(start.y - end.y);
	int dx = fabsf(start.x - end.x);
	Vec2i dir = {
		end.x > start.x ? 1 : -1,
		end.y > start.y ? 1 : -1
	};
	if (dy < dx) {
		float pk = 2*dy - dx;
		int y = start.y;
		for (int x = start.x; x != end.x; x += dir.x) {
			int step_y = pk < 0 ? 0 : 1;
			y += step_y*dir.y;
			pk = pk + 2*dy - 2*dx*step_y;
			for (int h = -brush_r; h <= brush_r; h++) {
				int y2 = y + h;
				change_canvas_unit(y2, x);
			}
		}
	} else {
		float pk = 2*dx - dy;
		int x = start.x;
		for (int y = start.y; y != end.y; y += dir.y) {
 			int step_x = pk < 0 ? 0 : 1;


#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include "../Integer.h"

// Simple workload: compute factorial segments and multiply into a shared result with a mutex-free pattern
// We avoid sharing Integer objects across threads directly to check per-thread safety, and also try a shared structure to stress potential hazards.

struct ThreadResult {
    UnsignedInteger value;
    ThreadResult() : value(1) {}
};

UnsignedInteger factorial_range(unsigned start, unsigned end) {
    UnsignedInteger acc = 1;
    for (unsigned i = start; i <= end; ++i) {
        acc *= i;
    }
    return acc;
}

int main() {
    std::cout << "=== Thread-safety probe for Integer library ===" << std::endl;

    // 1) Per-thread independent use: each thread builds its own numbers and converts to string
    const unsigned num_threads = std::max(4u, std::thread::hardware_concurrency());
    std::cout << "Threads: " << num_threads << std::endl;

    std::atomic<bool> any_exception{false};
    std::vector<std::thread> threads;
    threads.reserve(num_threads);

    auto task_independent = [&](unsigned tid) {
        try {
            // Independent sequences
            UnsignedInteger a = 1;
            for (int r = 0; r < 200; ++r) {
                a *= (r + 11);
                a += r;
                a = a * a % UnsignedInteger(1000003);
                // Exercise conversions (string uses thread_local in library):
                volatile size_t len = static_cast<std::string>(a).size();
                (void)len;
            }

            SignedInteger s = -123456789;
            s *= 3;
            s += 42;
            volatile auto s_str_len = static_cast<std::string>(s).size();
            (void)s_str_len;
        } catch (const std::exception& e) {
            std::cerr << "Thread " << tid << " exception (independent): " << e.what() << std::endl;
            any_exception = true;
        }
    };

    for (unsigned t = 0; t < num_threads; ++t) {
        threads.emplace_back(task_independent, t);
    }
    for (auto& th : threads) th.join();
    threads.clear();

    std::cout << "Phase 1 done. Exceptions: " << std::boolalpha << any_exception.load() << std::endl;

    // 2) Shared stress via thread_local buffers inside conversions. We intentionally share std::string destinations only (safe),
    // but we call static_cast<const char*> on different objects concurrently to stress thread_local correctness.
    std::vector<ThreadResult> partial(num_threads);

    auto task_partial = [&](unsigned tid) {
        try {
            // Each thread computes a partial factorial range
            unsigned total_n = 250; // moderate size to run fast
            unsigned chunk = (total_n + num_threads - 1) / num_threads;
            unsigned start = tid * chunk + 1;
            unsigned end = std::min(total_n, (tid + 1) * chunk);
            if (start <= end) {
                partial[tid].value = factorial_range(start, end);
            } else {
                partial[tid].value = 1;
            }

            // Convert repeatedly to string and C-string to exercise thread_local buffers
            for (int r = 0; r < 200; ++r) {
                std::string s = static_cast<std::string>(partial[tid].value);
                const char* cs = static_cast<const char*>(partial[tid].value);
                // Touch data to avoid optimizing away
                if (!cs || s.empty()) {
                    any_exception = true;
                }
            }
        } catch (const std::exception& e) {
            std::cerr << "Thread " << tid << " exception (partial): " << e.what() << std::endl;
            any_exception = true;
        }
    };

    for (unsigned t = 0; t < num_threads; ++t) {
        threads.emplace_back(task_partial, t);
    }
    for (auto& th : threads) th.join();
    threads.clear();

    // Multiply partials serially to avoid intentional data races on big integers
    UnsignedInteger combined = 1;
    for (unsigned t = 0; t < num_threads; ++t) {
        combined *= partial[t].value;
    }

    std::cout << "Phase 2 done. Combined digits: " << static_cast<std::string>(combined).size() << std::endl;

    // 3) Intentional race test: write to a shared UnsignedInteger without synchronization
    // It is expected to crash or produce inconsistent results, since the library is not thread-safe for shared objects.
    UnsignedInteger shared_val = 1;
    auto task_racy = [&](unsigned tid) {
        try {
            for (int r = 0; r < 1000; ++r) {
                // racy update: not synchronized on purpose
                shared_val *= (tid + 2);
                shared_val += r;
            }
        } catch (const std::exception& e) {
            std::cerr << "Thread " << tid << " exception (racy): " << e.what() << std::endl;
            any_exception = true;
        }
    };

    for (unsigned t = 0; t < num_threads; ++t) {
        threads.emplace_back(task_racy, t);
    }
    for (auto& th : threads) t


#define DUCKDB_EXTENSION_MAIN

#include "cwiqduck_extension.hpp"
#include "duckdb.hpp"
#include "duckdb/common/exception.hpp"
#include "duckdb/common/file_opener.hpp"
#include "duckdb/common/file_system.hpp"
#include "duckdb/common/local_file_system.hpp"
#include "duckdb/common/string_util.hpp"
#include "duckdb/function/scalar_function.hpp"
#include <duckdb/parser/parsed_data/create_scalar_function_info.hpp>

#ifdef __linux__
#include <sys/xattr.h>
#include <sys/stat.h>
#endif

#include <errno.h>
#include <cstring>

namespace duckdb {

// Lazy-load the actual S3 handle when needed
FileHandle &S3RedirectFileHandle::GetS3Handle() {
	if (!s3_handle) {
		// Let DuckDB's httpfs handle the S3 URL
		auto &main_fs = FileSystem::GetFileSystem(db_instance);
		s3_handle = main_fs.OpenFile(s3_url, FileFlags::FILE_FLAGS_READ, nullptr);
	}
	return *s3_handle;
}

idx_t S3RedirectFileHandle::GetFileSize() {
	return known_content_length;
}

void S3RedirectFileHandle::Close() {
	if (s3_handle) {
		s3_handle->Close();
	}
}

void S3RedirectFileHandle::Read(void *buffer, idx_t nr_bytes, idx_t location) {
	return GetS3Handle().Read(buffer, nr_bytes, location);
}

int64_t S3RedirectFileHandle::Read(void *buffer, idx_t nr_bytes) {
	return GetS3Handle().Read(buffer, nr_bytes);
}

bool S3RedirectFileHandle::CanSeek() {
	return true;
}

void S3RedirectFileHandle::Sync() {
	if (s3_handle)
		s3_handle->Sync();
}

FileType S3RedirectFileHandle::GetType() {
	return GetS3Handle().GetType();
}

timestamp_t S3RedirectFileHandle::GetLastModifiedTime() {
	return last_modified_time;
}

void S3RedirectFileHandle::Write(void *buffer, idx_t nr_bytes, idx_t location) {
	GetS3Handle().Write(buffer, nr_bytes);
}

int64_t S3RedirectFileHandle::Write(void *buffer, idx_t nr_bytes) {
	return GetS3Handle().Write(buffer, nr_bytes);
}

void S3RedirectFileHandle::Truncate(int64_t new_size) {
	return GetS3Handle().Truncate(new_size);
}

unique_ptr<FileHandle> S3RedirectProtocolFileSystem::OpenFile(const string &path, FileOpenFlags flags,
                                                              optional_ptr<FileOpener> opener) {
	try {
		auto s3_info = ConvertLocalPathToS3(path);
		return make_uniq<S3RedirectFileHandle>(*this, db_instance, s3_info.s3_url, s3_info.content_length,
		                                       s3_info.last_modified_time, opener);
	} catch (const std::exception &e) {
		throw IOException("Failed to redirect to S3: " + string(e.what()));
	}
}

bool S3RedirectProtocolFileSystem::FileExists(const string &filename, optional_ptr<FileOpener> opener) {
	try {
		ConvertLocalPathToS3(filename);
		return true;
	} catch (...) {
		return false;
	}
}

bool S3RedirectProtocolFileSystem::CanHandleFile(const string &fpath) {
#ifdef __linux__
	if (StringUtil::StartsWith(fpath, "http")) // Check if file is already a URL
		return false;

	// Check if file is in CWIQFS
	const char *xattr_name = "system.cwiqfs.s3_url";
	ssize_t size = getxattr(fpath.c_str(), xattr_name, nullptr, 0);
	return size > 0;
#else
	return false;
#endif
}

void S3RedirectProtocolFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) {
	auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle);
	if (s3_handle) {
		return s3_handle->GetS3Handle().Read(buffer, nr_bytes, location);
	}
	throw InternalException("Invalid handle type in S3RedirectProtocolFileSystem");
}

int64_t S3RedirectProtocolFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) {
	auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle);
	if (s3_handle) {
		return s3_handle->GetS3Handle().Read(buffer, nr_bytes);
	}
	throw InternalException("Invalid handle type in S3RedirectProtocolFileSystem");
}

void S3RedirectProtocolFileSystem::Seek(FileHandle &handle, idx_t location) {
	auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle);
	if (s3_handle) {
		return s3_handle->GetS3Handle().Seek(location);
	}
	throw InternalException("Invalid handle type in S3RedirectProtocolFileSystem");
}

int64_t S3RedirectProtocolFileSystem::GetFileSize(FileHandle &handle) {
	auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle);
	if (s3_handle) {
		return s3_handle->GetFileSize();
	}
	throw InternalException("Invalid handle type in S3RedirectProtocolFileSystem");
}

FileType S3RedirectProtocolFileSystem::GetFileType(FileHandle &handle) {
	return FileType::FILE_TYPE_REGULAR;
}

void S3RedirectProtocolFileSystem::FileSync(FileHandle &handle) {
	if (auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle)) {
		s3_handle->Sync();
	}
}

timestamp_t S3RedirectProtocolFileSystem::GetLastModifiedTime(FileHandle &handle) {
	auto s3_handle = dynamic_cast<S3RedirectFileHandle *>(&handle);
	if (s3_handle) {
		return s3_handle->GetLastModifiedTime();
	}
	throw InternalException("Invalid handle type in S3RedirectProtocolFileSystem");
}

vector<OpenFileInfo> S3RedirectProtocolFileSystem::Glob(const string &path, FileOpener *opener) {
	return LocalFileSystem().Glob(path, n


#include "chacha20.h"

// https://github.com/jedisct1/libsodium/tree/master/src/libsodium/crypto_stream/chacha20

// libsodium chacha20 port for WDK by @Unbonkable, horrible stuff...
// I DID NOT make all of this, i just made it so you can use it in Windows kernel
// only "crypto_stream_chacha20_xor_ic" and "crypto_stream_chacha20_xor" are ported, since these are the only ones i needed.
// dont even try to understand this shit, i promise you'll most likely just waste your time

static void chacha20_encrypt_bytes(chacha_ctx* ctx, const unsigned char* m, unsigned char* c, unsigned long long bytes) {
    UINT32* const x = &ctx->input[0];

    if (!bytes) {
        return; /* LCOV_EXCL_LINE */
    }

    //u8.h  ---------------------------------------------

#define VEC8_ROT(A, IMM) \
    _mm256_or_si256(_mm256_slli_epi32(A, IMM), _mm256_srli_epi32(A, (32 - IMM)))

    /* same, but replace 2 of the shift/shift/or "rotation" by byte shuffles (8 & * 16) (better) */
#define VEC8_QUARTERROUND_SHUFFLE(A, B, C, D)  \
    x_##A = _mm256_add_epi32(x_##A, x_##B);    \
    t_##A = _mm256_xor_si256(x_##D, x_##A);    \
    x_##D = _mm256_shuffle_epi8(t_##A, rot16); \
    x_##C = _mm256_add_epi32(x_##C, x_##D);    \
    t_##C = _mm256_xor_si256(x_##B, x_##C);    \
    x_##B = VEC8_ROT(t_##C, 12);               \
    x_##A = _mm256_add_epi32(x_##A, x_##B);    \
    t_##A = _mm256_xor_si256(x_##D, x_##A);    \
    x_##D = _mm256_shuffle_epi8(t_##A, rot8);  \
    x_##C = _mm256_add_epi32(x_##C, x_##D);    \
    t_##C = _mm256_xor_si256(x_##B, x_##C);    \
    x_##B = VEC8_ROT(t_##C, 7)

#define VEC8_QUARTERROUND(A, B, C, D) VEC8_QUARTERROUND_SHUFFLE(A, B, C, D)

#define VEC8_LINE1(A, B, C, D)              \
    x_##A = _mm256_add_epi32(x_##A, x_##B); \
    x_##D = _mm256_shuffle_epi8(_mm256_xor_si256(x_##D, x_##A), rot16)
#define VEC8_LINE2(A, B, C, D)              \
    x_##C = _mm256_add_epi32(x_##C, x_##D); \
    x_##B = VEC8_ROT(_mm256_xor_si256(x_##B, x_##C), 12)
#define VEC8_LINE3(A, B, C, D)              \
    x_##A = _mm256_add_epi32(x_##A, x_##B); \
    x_##D = _mm256_shuffle_epi8(_mm256_xor_si256(x_##D, x_##A), rot8)
#define VEC8_LINE4(A, B, C, D)              \
    x_##C = _mm256_add_epi32(x_##C, x_##D); \
    x_##B = VEC8_ROT(_mm256_xor_si256(x_##B, x_##C), 7)

#define VEC8_ROUND_SEQ(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, B4, \
                       C4, D4)                                                 \
    VEC8_LINE1(A1, B1, C1, D1);                                                \
    VEC8_LINE1(A2, B2, C2, D2);                                                \
    VEC8_LINE1(A3, B3, C3, D3);                                                \
    VEC8_LINE1(A4, B4, C4, D4);                                                \
    VEC8_LINE2(A1, B1, C1, D1);                                                \
    VEC8_LINE2(A2, B2, C2, D2);                                                \
    VEC8_LINE2(A3, B3, C3, D3);                                                \
    VEC8_LINE2(A4, B4, C4, D4);                                                \
    VEC8_LINE3(A1, B1, C1, D1);                                                \
    VEC8_LINE3(A2, B2, C2, D2);                                                \
    VEC8_LINE3(A3, B3, C3, D3);                                                \
    VEC8_LINE3(A4, B4, C4, D4);                                                \
    VEC8_LINE4(A1, B1, C1, D1);                                                \
    VEC8_LINE4(A2, B2, C2, D2);                                                \
    VEC8_LINE4(A3, B3, C3, D3);                                                \
    VEC8_LINE4(A4, B4, C4, D4)

#define VEC8_ROUND_HALF(A1, B1, C1, D1, A2, B2, C2, D2, A3, B3, C3, D3, A4, \
                        B4, C4, D4)                                         \
    VEC8_LINE1(A1, B1, C1, D1);                                             \
    VEC8_LINE1(A2, B2, C2, D2);                                             \
    VEC8_LINE2(A1, B1, C1, D1);                                             \
    VEC8_LINE2(A2, B2, C2, D2);                                             \
    VEC8_LINE3(A1, B1, C1, D1);                                             \
    VEC8_LINE3(A2, B2, C2, D2);                                             \
    VEC8_LINE4(A1, B1, C1, D1);                                             \
    VEC8_LINE4(A2, B2, C2, D2);                                             \
    VEC8_LINE1(A3, B3, C3, D3);                                             \
    VEC8_LINE1(A4, B4, C4, D4);                                             \
    VEC8_LINE2(A3, B3, C3, D3);                                             \
    VEC8_LINE2(A4, B4, C4, D4);                                             \
    VEC8_LINE3(A3, B3, C3, D3);                                             \
    VEC8_LINE3(A4, B4, C4, D4);                                             \
    VEC8_LINE4(A3, B3, C3, D3);


#include <iostream>
#include <chrono>
#include <iomanip>
#include <vector>
#include <cmath>
#include <random>
#include <algorithm>
#include <Eigen/Dense>
#include <Eigen/IterativeLinearSolvers>
#include "matrix_base.h"
#include "matrix_operations.h"
#include "matrix_decomposition.h"
#include "numerical_optimization.h"
#include "expression_templates.h"

using namespace matrixlib;
using namespace Eigen;
using namespace std;
using namespace chrono;

// 计时工具类
template <typename T>
struct Timer
{
    high_resolution_clock::time_point start;
    string name;
    double duration; // 存储耗时(毫秒)

    Timer(string n) : name(n)
    {
        start = high_resolution_clock::now();
    }

    ~Timer()
    {
        auto end = high_resolution_clock::now();
        duration = duration_cast<microseconds>(end - start).count() / 1000.0;
        cout << left << setw(50) << name << "耗时: " << fixed << setprecision(6) << duration << " ms" << endl;
    }
};

// 结果验证工具
template <typename T>
bool verify_result(const matrixlib::Matrix<T> &our_result, const MatrixXd &eigen_result, double epsilon = 1e-6)
{
    if (our_result.rows() != eigen_result.rows() || our_result.cols() != eigen_result.cols())
        return false;

    for (size_t i = 0; i < our_result.rows(); ++i)
    {
        for (size_t j = 0; j < our_result.cols(); ++j)
        {
            if (fabs(fabs(our_result(i, j)) - fabs(eigen_result(i, j))) > epsilon)
            {
                cerr << "结果不匹配 at (" << i << "," << j << "): 我们的库="
                     << our_result(i, j) << ", Eigen=" << eigen_result(i, j) << endl;
                return false;
            }
        }
    }
    return true;
}

template <typename T>
bool verify_scalar(T our_result, T eigen_result, double epsilon = 1e-6)
{
    if (fabs(our_result - eigen_result) > epsilon)
    {
        cerr << "标量结果不匹配: 我们的库=" << our_result << ", Eigen=" << eigen_result << endl;
        return false;
    }
    return true;
}

// 将自定义矩阵转换为Eigen矩阵
MatrixXd convert_to_eigen(const matrixlib::Matrix<double> &our_mat)
{
    MatrixXd eigen_mat(our_mat.rows(), our_mat.cols());
    for (size_t i = 0; i < our_mat.rows(); ++i)
    {
        for (size_t j = 0; j < our_mat.cols(); ++j)
        {
            eigen_mat(i, j) = our_mat(i, j); // 逐个元素复制
        }
    }
    return eigen_mat;
}

// 基础运算测试
void test_basic_operations(size_t size)
{
    cout << "\n=== 基础运算测试 (" << size << "x" << size << ") ===" << endl;

    // 生成测试矩阵
    auto our_mat1 = random_matrix<double>(size, size, -100, 100);
    auto our_mat2 = random_matrix<double>(size, size, -100, 100);
    auto our_vec = random_matrix<double>(size, 1, -100, 100);

    MatrixXd eigen_mat1 = MatrixXd::Random(size, size) * 100;
    MatrixXd eigen_mat2 = MatrixXd::Random(size, size) * 100;
    VectorXd eigen_vec = VectorXd::Random(size) * 100;

    // 矩阵加法
    {
        Timer<double> t("当前库: 矩阵加法");
        auto result = our_mat1 + our_mat2;
    }
    {
        Timer<double> t("Eigen: 矩阵加法");
        auto result = eigen_mat1 + eigen_mat2;
    }

    // 矩阵数乘
    {
        Timer<double> t("当前库: 矩阵数乘");
        auto result = our_mat1 * 2.5;
    }
    {
        Timer<double> t("Eigen: 矩阵数乘");
        auto result = eigen_mat1 * 2.5;
    }

    // 矩阵向量乘法
    {
        Timer<double> t("当前库: 矩阵向量乘法");
        auto result = our_mat1 * our_vec;
    }
    {
        Timer<double> t("Eigen: 矩阵向量乘法");
        auto result = eigen_mat1 * eigen_vec;
    }

    // 矩阵转置
    {
        Timer<double> t("当前库: 矩阵转置");
        auto result = transpose(our_mat1);
    }
    {
        Timer<double> t("Eigen: 矩阵转置");
        auto result = eigen_mat1.transpose();
    }
}

// 矩阵乘法详细测试
void test_matrix_multiplication(size_t size)
{
    cout << "\n=== 矩阵乘法测试 (" << size << "x" << size << ") ===" << endl;

    // 生成测试矩阵
    auto our_mat1 = random_matrix<double>(size, size, -100, 100);
    auto our_mat2 = random_matrix<double>(size, size, -100, 100);

    MatrixXd eigen_mat1 = convert_to_eigen(our_mat1);

    MatrixXd eigen_mat2 = convert_to_eigen(our_mat2);

    // 普通矩阵乘法
    {
        Timer<double> t("当前库: 普通矩阵乘法");
        auto our_result = our_mat1 * our_mat2;
        Timer<double> t_verify("验证: 当前库 vs Eigen 矩阵乘法");
        MatrixXd eigen_result = eigen_mat1 * eigen_mat2;
        bool valid = verify_result(our_result, eigen_result);
        cout << left << setw(50) << " " << "结果: " << (valid ? "正确" : "错误") << endl;
    }

    // Eigen矩阵乘法（单独计时，排除验证时间）
    {
        Timer<double> t("Eigen: 矩阵乘法");
        auto result = eigen_mat1 * eigen_mat2;
    }
}

// 矩阵分解测试
void test_decompositions(size_t size)
{
    cout << "\n=== 矩阵分解测试 (" << size << "x" << size << ") ===" << endl;

    // 生成对称正定矩阵
    auto our_mat = random_matrix<double>(size, size, -100, 100);
    auto our_sym_mat = our_mat * transpose(our_mat) + identity_matrix<double>(size) * 10.0;

    MatrixXd eigen_mat = convert_to_eigen(our_mat);
    MatrixXd eigen_sym_mat = convert_to_eigen(our_sym_mat);

    // LU分解
    {
        Timer<double> t("当前库: LU分解");


/*
 * Amiga Fuse - FIXED VERSION WITH WRITE SUPPORT for macOS
 * Implements full read/write support for Amiga ADF disk images
 */

#define FUSE_USE_VERSION 26

#ifndef ADF_DEBUG
#define ADF_DEBUG 0
#endif
#define DBG(stmt) do { if (ADF_DEBUG) { stmt; } } while(0)

#ifdef __APPLE__
#ifndef typeof
#define typeof __typeof__
#endif
#endif

#include <fuse.h>
#include <cstdint>
#include <cctype>
#include <algorithm>
#include <array>
#include <bit>
#include <cerrno>
#include <cstring>
#include <ctime>
#include <fcntl.h>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <string_view>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <unordered_map>
#include <vector>
#include <set>
#include <limits>
// #include <csignal>  // not needed if we remove custom handler

namespace amiga_fuse {

// Helper for 32-bit overflow detection
static inline bool add_would_overflow_u32(size_t a, size_t b) {
    return a > std::numeric_limits<uint32_t>::max() - b;
}

// Constants
constexpr size_t BLOCK_SIZE = 512;
constexpr size_t BCPL_STRING_MAX = 30;
constexpr size_t HASH_TABLE_SIZE = 72;

// Block types
constexpr int32_t T_HEADER = 2;
constexpr int32_t T_DATA = 8;
constexpr int32_t ST_ROOT = 1;
constexpr int32_t ST_DIR = 2;
constexpr int32_t ST_FILE = -3;

// DOS types
constexpr uint32_t DOS_FFS = 0x444F5301;
constexpr uint32_t DOS_FFS_INTL = 0x444F5303;
constexpr uint32_t DOS_FFS_DC = 0x444F5305;

// Endian helpers
namespace endian {
    template<typename T>
    constexpr T byteswap(T value) noexcept {
        static_assert(std::is_integral_v<T>, "byteswap requires integral type");

        if constexpr (sizeof(T) == 1) {
            return value;
        } else if constexpr (sizeof(T) == 2) {
            return static_cast<T>(__builtin_bswap16(static_cast<std::uint16_t>(value)));
        } else if constexpr (sizeof(T) == 4) {
            return static_cast<T>(__builtin_bswap32(static_cast<std::uint32_t>(value)));
        } else if constexpr (sizeof(T) == 8) {
            return static_cast<T>(__builtin_bswap64(static_cast<std::uint64_t>(value)));
        } else {
            static_assert(sizeof(T) <= 8, "Unsupported type size for byte swapping");
        }
    }

    template<typename T>
    constexpr T from_big_endian(T value) noexcept {
        if constexpr (std::endian::native == std::endian::big) {
            return value;
        } else {
            return byteswap(value);
        }
    }

    template<typename T>
    constexpr T to_big_endian(T value) noexcept {
        return from_big_endian(value); // Same operation for both directions
    }
}

// BCPL string handling
class BcplString {
public:
    static std::string read(const uint8_t* data, size_t max_len = BCPL_STRING_MAX) {
        if (!data || data[0] == 0) return "";
        size_t len = std::min(static_cast<size_t>(data[0]), max_len);
        return std::string(reinterpret_cast<const char*>(data + 1), len);
    }

    static void write(uint8_t* data, const std::string& str, size_t max_len = BCPL_STRING_MAX) {
        size_t len = std::min(str.length(), max_len);
        data[0] = static_cast<uint8_t>(len);
        if (len > 0) {
            std::memcpy(data + 1, str.data(), len);
        }
        // Clear remaining bytes
        if (len < max_len) {
            std::memset(data + 1 + len, 0, max_len - len);
        }
    }
};

// Block structures
#pragma pack(push, 1)
struct BootBlock {
    uint32_t disk_type;          // 0-3
    uint32_t checksum;           // 4-7
    uint32_t root_block;         // 8-11
    uint8_t boot_code[500];      // 12-511 (500 bytes to total 512)
};

// RootBlock must match exact Amiga spec - do NOT change field sizes
struct RootBlock {
    uint32_t type;                    // 0-3
    uint32_t header_key;              // 4-7
    uint32_t high_seq;                // 8-11
    uint32_t hash_table_size;         // 12-15
    uint32_t first_size;              // 16-19
    uint32_t checksum;                // 20-23
    uint32_t hash_table[HASH_TABLE_SIZE]; // 24-311 (72*4=288 bytes)
    uint32_t bm_flag;                 // 312-315
    uint32_t bm_pages[25];            // 316-415 (25*4=100 bytes)
    uint32_t bm_ext;                  // 416-419
    uint32_t days;                    // 420-423
    uint32_t mins;                    // 424-427
    uint32_t ticks;                   // 428-431
    uint8_t name[32];                 // 432-463
    uint8_t reserved1[8];             // 464-471
    uint32_t days2;                   // 472-475
    uint32_t mins2;                   // 476-479
    uint32_t ticks2;                  // 480-483
    uint32_t created_days;            // 484-487
    uint32_t created_mins;            // 488-491
    uint32_t created_ticks;           // 492-495
    uint32_t next_hash;               // 496-499
    uint32_t parent;                  // 500-503
    uint32_t extension;               // 504-507
    int32_t s


/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 <memory>

#include <gtest/gtest.h>

#include "minikin/Hyphenator.h"

#include "FileUtils.h"
#include "FontTestUtils.h"
#include "HyphenatorMap.h"
#include "LineBreakerTestHelper.h"
#include "LocaleListCache.h"
#include "MinikinInternal.h"
#include "OptimalLineBreaker.h"
#include "UnicodeUtils.h"
#include "WordBreaker.h"

namespace minikin {
namespace {

using line_breaker_test_helper::ConstantRun;
using line_breaker_test_helper::LineBreakExpectation;
using line_breaker_test_helper::RectangleLineWidth;
using line_breaker_test_helper::sameLineBreak;
using line_breaker_test_helper::toString;

// The ascent/descent of Ascii.ttf with text size = 10.
constexpr float ASCENT = -80.0f;
constexpr float DESCENT = 20.0f;

// The ascent/descent of CustomExtent.ttf with text size = 10.
constexpr float CUSTOM_ASCENT = -160.0f;
constexpr float CUSTOM_DESCENT = 40.0f;

class OptimalLineBreakerTest : public testing::Test {
public:
    OptimalLineBreakerTest() {}

    virtual ~OptimalLineBreakerTest() {}

    virtual void SetUp() override {
        mHyphenationPattern = readWholeFile("/system/usr/hyphen-data/hyph-en-us.hyb");
        Hyphenator* hyphenator = Hyphenator::loadBinary(
                mHyphenationPattern.data(), 2 /* min prefix */, 2 /* min suffix */, "en-US");
        HyphenatorMap::add("en-US", hyphenator);
        HyphenatorMap::add("pl", Hyphenator::loadBinary(nullptr, 0, 0, "pl"));
    }

    virtual void TearDown() override { HyphenatorMap::clear(); }

protected:
    LineBreakResult doLineBreak(const U16StringPiece& textBuffer, BreakStrategy strategy,
                                HyphenationFrequency frequency, const std::string& lang,
                                float lineWidth, bool ignoreKerning) {
        MeasuredTextBuilder builder;
        auto family1 = buildFontFamily("Ascii.ttf");
        auto family2 = buildFontFamily("CustomExtent.ttf");
        std::vector<std::shared_ptr<FontFamily>> families = {family1, family2};
        auto fc = FontCollection::create(families);
        MinikinPaint paint(fc);
        paint.size = 10.0f;  // Make 1em=10px
        paint.localeListId = LocaleListCache::getId(lang);
        builder.addStyleRun(0, textBuffer.size(), std::move(paint), 0, 0, false);
        bool computeHyphen = frequency != HyphenationFrequency::None;
        std::unique_ptr<MeasuredText> measuredText =
                builder.build(textBuffer, computeHyphen, false /* compute full layout */,
                              ignoreKerning, nullptr /* no hint */);
        return doLineBreak(textBuffer, *measuredText, strategy, frequency, lineWidth);
    }

    LineBreakResult doLineBreak(const U16StringPiece& textBuffer, const MeasuredText& measuredText,
                                BreakStrategy strategy, HyphenationFrequency frequency,
                                float lineWidth) {
        RectangleLineWidth rectangleLineWidth(lineWidth);
        return breakLineOptimal(textBuffer, measuredText, rectangleLineWidth, strategy, frequency,
                                false /* justified */);
    }

    void expectBreak(const std::vector<LineBreakExpectation>& expect,
                     const U16StringPiece& textBuffer, BreakStrategy strategy,
                     HyphenationFrequency frequency, const std::string& lang, float lineWidth) {
        {
            char msg[256] = {};
            snprintf(msg, 256, "width = %f, lang = %s, strategy = %u, frequency = %u, fullyHyphen",
                     lineWidth, lang.c_str(), (uint32_t)strategy, (uint32_t)frequency);
            SCOPED_TRACE(msg);
            auto actual = doLineBreak(textBuffer, strategy, frequency, lang, lineWidth,
                                      false /* ignoreKerning */);
            EXPECT_TRUE(sameLineBreak(expect, actual)) << toString(expect) << std::endl
                                                       << " vs " << std::endl
                                                       << toString(textBuffer, actual);
        }
        {
            char msg[256] = {};
            snprintf(msg, 256, "width = %f, lang = %s, strategy = %u, frequency = %u, fullyHyphen",
                     lineWidth, lang.c_str(), (uint32_t)strategy, (uint32_t)frequency);
            SCOPED_TRACE(msg);
            auto actual = doLineBreak(textBuffer, strategy, frequency, lang, lineWidth,


#include <iostream>
#include <vector>
#include<regex>
using namespace std;

const char* crt = "\n-------------------------------------------\n";
enum Drzava {
	ENGLESKA, SPANIJA, HOLANDIJA, FRANCUSKA, BOSNA_I_HERCEGOVINA
};
const char* IspisDrzava[] = { "ENGLESKA", "SPANIJA", "HOLANDIJA", "FRANCUSKA", "BOSNA_I_HERCEGOVINA" };
char* GetNizKaraktera(const char* sadrzaj, bool dealociraj = false) {
	if (sadrzaj == nullptr)return nullptr;
	int vel = strlen(sadrzaj) + 1;
	char* temp = new char[vel];
	strcpy_s(temp, vel, sadrzaj);
	if (dealociraj)
		delete[]sadrzaj;
	return temp;
}
char* GenerisiID(const char* imeprezime, int broj)
{
	//prvo uzimamo incijale koji nam trebaju, vidis ovdje s obzirom da je imeprezime niz pokazivaca
	//nas prvi inicijal tj inicjal za ime je nulti clan(prvi)niza logicno
	if (imeprezime == nullptr)
		return nullptr;
	char inicijalIme = imeprezime[0];
	//eh sad ovo ti je u sustini da ti pravi novi niz koji cemo nazvati prezime
	//uzima ti imeprezime i trazi space
	const char* prezime = strchr(imeprezime, ' ');
	//i sad iz tog prezimena uzimamo prvi clan niza ali je nulti koji je tehnicki prvi jer nam krece od spacea
	//znaci da si stavila prezime[0]vratio bi ti space
	char inicijalPrezime = prezime[1];
	//ovo kontas logy
	if (islower(inicijalIme))
		inicijalIme = toupper(inicijalIme);
	if (islower(inicijalPrezime))
		inicijalPrezime = toupper(inicijalPrezime);
	//pravimo obrnuti broj
	int obrnuti = 0, temp = broj;
	while (temp > 0)
	{
		obrnuti = obrnuti * 10 + temp % 10;
		temp /= 10;
	}
	//pravimo niz nula, da bi izracunali koliko nula nam treba logicno da moramo vidjet koliki nam je broj
	//zato prvo trazimo brojcifara
	int brojCifara = 0;
	char nule[5] = "";
	temp = broj;
	while (temp > 0)
	{
		brojCifara++;
		temp /= 10;
	}
	//onda loicno ako je max 4 cifre kao sto jest, bubam ako je broj dvocifren
	//nule ce nam trebati 2 tj 4-2
	int brojNula = 4 - brojCifara;
	for (int i = 0; i < brojNula; i++)
	{
		nule[i] = '0';
	}
	nule[brojNula] = '\0';
	char* ID = new char[15];
	//ovako ti se uvijek pohranjuje vrijednost za ID
	//prvo pises naziv new char sto si napravila, zatim velicinu niza, e onda ovo trece sto vidis pod apostrofina
	//to ti je "poredak" kako se pohranjuju stvari u tvoj ID
	//c-char(inicijalIme), s-string(nule), d-decimal/broj(obrnuti broj)
	sprintf_s(ID, 15, "%c%s%c%d", inicijalIme, nule, inicijalPrezime, obrnuti);
	return ID;
}
bool ValidirajID(string id)
{
	//faking simple
	return regex_match(id, regex("[A-Z][0]{0,3}[A-Z][1-9]{1,4}"));
}
template<class T1, class T2, int max>
class Kolekcija {
	T1 _elementi1[max];
	T2 _elementi2[max];
	int* _trenutno;
public:
	Kolekcija()
	{
		_trenutno = new int(0);
	}
	Kolekcija(const Kolekcija& obj)
	{
		_trenutno = new int(*obj._trenutno);
		for (int i = 0; i < *_trenutno; i++)
		{
			//ovako pohranjujemo jer nemamo pokazivaca, a da imamo bilo bi ono new T1(*obj._elementi1[i])
			//logicno ako nema pokazivana ne treba ti new duuuhh
			_elementi1[i] = obj._elementi1[i];
			_elementi2[i] = obj._elementi2[i];
		}
	}
	Kolekcija& operator=(const Kolekcija& obj)
	{
		if (this != &obj)
		{
			delete _trenutno; _trenutno = nullptr;
			_trenutno = new int(*obj._trenutno);
			for (int i = 0; i < *_trenutno; i++)
			{
				_elementi1[i] = obj._elementi1[i];
				_elementi2[i] = obj._elementi2[i];
			}
		}return *this;
	}
	void AddElement(T1 el1, T2 el2)
	{
		//ista prica ne treba nam new jer nema pokazivaca
		//da je bilo bilo bi = new T1(el1)
		_elementi1[*_trenutno] = el1;
		_elementi2[*_trenutno] = el2;
		(*_trenutno)++;
	}
	Kolekcija<T1, T2, max>InsertAt(T1 el1, T2 el2, int lokacija)
	{
		for (int i = *_trenutno; i > lokacija; i--)
		{
			_elementi1[i] = _elementi1[i - 1];
			_elementi2[i] = _elementi2[i - 1];
		}
		//vidis kako i ovdje nemamo new jer nema pokazivaca
		_elementi1[lokacija] = el1;
		_elementi2[lokacija] = el2;
		(*_trenutno)++;
		Kolekcija<T1, T2, max>novi = *this;
		return novi;
	}
	Kolekcija<T1, T2, max>* RemoveRange(int OD, int DO)
	{
		if (OD < 0 || DO >= *_trenutno)
			throw exception("Nedostizan opseg");
		//pravimo novu kolekciju jer tako se dole trazi, i u njoj ce biti svi elementi OD-DO
		Kolekcija<T1, T2, max>* novi = new Kolekcija();
		for (int i = OD; i <= DO; i++)
		{
			novi->AddElement(_elementi1[i], _elementi2[i]);
		}
		//posto pravis novu kolekciju logicno da is stare moras obrisati ovo sto si gore dodala
		//ide +1 jer npr ako ti je bilo 3 elementa(1,3), kad oduzmes 3 od 1 dobijes 2 a ne 3 logicno
		int kol = DO - OD + 1;
		for (int i = DO + 1; i < *_trenutno; i++)
		{
			_elementi1[i - kol] = _elementi1[i];
			_elementi2[i - kol] = _elementi2[i];
		}
		//smanjis trenutno logicno koliko si oduzela elemenata
		(*_trenutno) -= kol;
		return novi;
	}
	~Kolekcija() {
		delete _trenutno; _trenutno = nullptr;
	}
	T1& getElement1(int lokacija) { return _elementi1[lokacija]; }
	T2& getElement2(int lokacija) { return _elementi2[lokacija]; }
	int getTrenutno() const { return *_trenutno; }
	friend ostream& operator<< (


#include<iostream>
#include<vector>
#include<fstream>
#include<string>
#include<limits>
using namespace std;
class Task
{
public:
string name,dueDate,description;
bool complete;
Task(string n,string d,string desc, bool C= false):name(n),dueDate(d),description(desc),complete(C)
{
}
void display(int index)
const
{
cout<<index+1<<"."<<name<<endl;
cout<<"Due Date:"<<dueDate<<endl;
cout<<"Description:"<<description<<endl;
cout<<"Status:"<<(complete?"Completed":"Pending")<<endl;
}
void save(ofstream &out)
const
{
out<<name<<"\n"<<dueDate<<"\n"<<description<<"\n"<<complete<<"\n";
}
static bool load(ifstream &in,Task &t)
{
string n,d,desc;
bool c;
if(!getline(in,n))return false;
if(!getline(in,d))return false;
if(!(in>>c))return false;
in.ignore();
t=Task(n,d,desc,c);
return true;
}
};
int main()
{
vector<Task>tasks;
int choice;
ifstream infile("TODOLIST.cpp");
if(infile)
{
Task t("","","");
while (Task::load(infile,t))
{
tasks.push_back(t);
}
infile.close();
}
do
{
cout<<"\n--- TO-DO LIST MENU---\n";
cout<<"1.Add Task\n";
cout<<"2.Show Task\n";
cout<<"3.Mark Task Complete\n";
cout<<"4.Save & Exit\n";
cout<<"Enter choice:";
cin>>choice;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
if(choice==1)
{
string name,due,desc;
cout<<"Finish Homeworkd:";
getline(cin,name);
cout<<"25-08-2025:";
getline(cin,due);
cout<<"Maths and Science:";
getline(cin,desc);
tasks.emplace_back(name,due,desc);
cout<<"Task added successfully!\n";
}
else if(choice==2)
{
if (tasks.empty())
{
cout<<"No tasks available.\n";
}
else
{
for(size_t i=0;i<tasks.size();i++)
{
tasks[i].display(i);
cout<<endl;
}
}
}
else if (choice==3)
{
int index;
cout<<"Enter task number to mark complete:";
cin>>index;
cin.ignore(numeric_limits<streamsize>::max(),'\n');
if(index> 0 && index<=(int)tasks.size())
{
tasks[index -1].complete=true;
cout<<" Task marked as complete!\n";
}
else
{
cout<<"Invalid task number.\n";
}
}
}
while(choice!=4);
ofstream outfile("TODOLIST.cpp");
if(!outfile.is_open())
{
cout<<"Error: Cannot open tasks.txt for saving!\n";
}
else
{
for(auto &t:tasks) t.save(outfile);
outfile.close();
cout<<"Tasks saved successfully!\n";
return 0;
}
}


/*++

    Copyright (c) Microsoft Corporation.

    SPDX-License-Identifier: BSD-2-Clause-Patent

Module Name:

    modules.cpp

Abstract:

    This file contains debug commands for enumerating UEFI modules and their
    symbols.

--*/

#include "uefiext.h"

//
// *******************************************************  External Functions
//

HRESULT CALLBACK
protocols (
  PDEBUG_CLIENT4  Client,
  PCSTR           args
  )
{
  ULONG64  HeadAddress;
  ULONG64  Entry;
  GUID     ProtocolID;
  UINT64   Signature;
  UINT64   Index;
  ULONG    ProtListOffset;
  ULONG    NotifyListOffset;

  INIT_API ();

  // enumerate all protocol entries.
  HeadAddress = GetExpression ("&mProtocolDatabase");
  if (HeadAddress == NULL) {
    dprintf ("Failed to find mProtocolDatabase!\n");
    return ERROR_NOT_FOUND;
  }

  GetFieldOffset ("PROTOCOL_ENTRY", "Protocols", &ProtListOffset);
  GetFieldOffset ("PROTOCOL_ENTRY", "Notify", &NotifyListOffset);

  Index = 0;
  Entry = 0;
  while ((Entry = GetNextListEntry (HeadAddress, "PROTOCOL_ENTRY", "AllEntries", Entry)) != 0) {
    GetFieldValue (Entry, "PROTOCOL_ENTRY", "Signature", Signature);
    GetFieldValue (Entry, "PROTOCOL_ENTRY", "ProtocolID", ProtocolID);
    g_ExtControl->ControlledOutput (
                    DEBUG_OUTCTL_AMBIENT_DML,
                    DEBUG_OUTPUT_NORMAL,
                    "<exec cmd=\"dt (PROTOCOL_ENTRY)%I64x\">[%d]</exec> "
                    "%s "
                    "<exec cmd=\"!linkedlist %I64x PROTOCOL_INTERFACE ByProtocol\">Protocols</exec> "
                    "<exec cmd=\"!linkedlist %I64x PROTOCOL_NOTIFY Link\">Notify</exec>\n",
                    Entry,
                    Index++,
                    GuidToString (&ProtocolID),
                    Entry + ProtListOffset,
                    Entry + NotifyListOffset
                    );
  }

  EXIT_API ();
  return S_OK;
}

HRESULT CALLBACK
handles (
  PDEBUG_CLIENT4  Client,
  PCSTR           args
  )
{
  ULONG64  HeadAddress;
  ULONG64  Entry;
  UINT64   Signature;
  ULONG    ProtListOffset;

  INIT_API ();

  UNREFERENCED_PARAMETER (args);

  HeadAddress = GetExpression ("&gHandleList");
  if (HeadAddress == NULL) {
    dprintf ("Failed to find gHandleList!\n");
    return ERROR_NOT_FOUND;
  }

  GetFieldOffset ("IHANDLE", "Protocols", &ProtListOffset);
  Entry = 0;
  while ((Entry = GetNextListEntry (HeadAddress, "IHANDLE", "AllHandles", Entry)) != 0) {
    GetFieldValue (Entry, "IHANDLE", "Signature", Signature);

    g_ExtControl->ControlledOutput (
                    DEBUG_OUTCTL_AMBIENT_DML,
                    DEBUG_OUTPUT_NORMAL,
                    "<exec cmd=\"dt (IHANDLE)%I64x\">%16I64x</exec> "
                    "<exec cmd=\"!linkedlist %I64x PROTOCOL_INTERFACE ByProtocol\">Protocols</exec>\n",
                    Entry,
                    Entry,
                    Entry + ProtListOffset
                    );
  }

  EXIT_API ();
  return S_OK;
}


#include "Splitting.h"

#include <float.h>

Splitting::Splitting(bool isOpticalPath)
{
    m_isOpticalPath = isOpticalPath;
}

void Splitting::ComputeRiParams(const complex &ri)
{
    m_ri = ri;
    double re = real(m_ri);
    double im = imag(m_ri);
    m_cRiRe = re*re - im*im;
    m_cRiRe2 = m_cRiRe * m_cRiRe;
    m_cRiIm = 4*re*re*im;
}

void Splitting::ComputeSplittingParams(const Point3f &dir, const Point3f &normal)
{
    r = dir/cosA - normal;
    reRiEff = ComputeEffectiveReRi();
#ifdef _DEBUG
    // double x = r.cx;
    // double xx = x*x;
    // double y = r.cy * r.cy;
    // double z = r.cz * r.cz;
    // double n = (double)r.cx * (double)r.cx
    //         + (double)r.cy * (double)r.cy
    //         + (double)r.cz * (double)r.cz;
    // double rr = reRiEff*cosA*cosA;
    // double ss = s = 1.0/rr - n;
#endif
    s = 1.0/(reRiEff*cosA*cosA) - Norm(r);
}

bool Splitting::IsCompleteReflection()
{
    return s <= DBL_EPSILON;
}

bool Splitting::IsNormalIncidence()
{
    return cosA >= EPS_COS_00;
}

bool Splitting::IsIncident()
{
    return cosA >= EPS_COS_90;
}

double Splitting::ComputeSegmentOpticalPath(const Beam &beam, const Point3f &facetPoint) const
{
    double tmp = DotProductD(beam.direction, facetPoint);
#ifdef _DEBUG // DEB
//	if (tmp + beam.front < 0)
//		int fff = 0;
    Point3f dd = beam.Center();
    Point3f pd = beam.Center() + (beam.direction * 10);
#endif

    double path = fabs(tmp + beam.front); // refractive index of external media = 1

    /* ПРоверка на нахождения плоскости за пучком
     * REF: вынести в случай невыпуклых частиц, т.к. характерно только для них */
    double cosB = DotProductD(NormalizeD(facetPoint - beam.Center()), beam.direction);

    if (cosB < 0)
    {
        path = -path;
    }

    if (beam.location == Location::In)
    {
        path *= sqrt(reRiEff);
    }

    return path;
}

// REF: создать отдельные классы RegularSplitting, CRSplitting, NormalSplitting

void Splitting::ComputeCRBeamParams(const Point3f &normal, const Beam &incidentBeam,
                                    Beam &inBeam)
{
    Point3f reflDir = r - normal;
    Normalize(reflDir);
    inBeam.SetLight(reflDir, incidentBeam.polarizationBasis);

    complex cv, ch;
    ComputeCRJonesParams(cv, ch);

    inBeam.J = incidentBeam.J;
    inBeam.MultiplyJonesMatrix(cv, ch);

    if (m_isOpticalPath)
    {
        double path = ComputeSegmentOpticalPath(incidentBeam, inBeam.Center());
#ifdef _DEBUG // DEB
        inBeam.ops = incidentBeam.ops;
        inBeam.ops.push_back(path);
#endif
        path += incidentBeam.opticalPath;
        inBeam.AddOpticalPath(path);
    }
}

void Splitting::ComputeRegularJonesParams(const Point3f &normal, const Beam &incidentBeam, Beam &inBeam, Beam &outBeam)
{
    inBeam.J = incidentBeam.J;
    outBeam.J = incidentBeam.J;

    double cosG = DotProduct(normal, outBeam.direction);

    complex tmp0 = m_ri * cosA;
    complex tmp1 = m_ri * cosG;
    complex Tv0 = tmp1 + cosA;
    complex Th0 = tmp0 + cosG;

    complex tmp = 2.0 * tmp0;
    outBeam.MultiplyJonesMatrix(tmp/Tv0, tmp/Th0);

    complex Tv = cosA - tmp1;
    complex Th = tmp0 - cosG;
    inBeam.MultiplyJonesMatrix(Tv/Tv0, Th/Th0);
}

void Splitting::ComputeInternalRefractiveDirection(const Vector3f &r,
                                                   const Vector3f &normal,
                                                   Vector3f &dir)
{
    double cosA2 = cosA * cosA;
    double tmp = m_cRiRe + cosA2 - 1.0;

    if (m_cRiIm > FLT_EPSILON)
    {
        tmp = sqrt(tmp*tmp + m_cRiIm);
    }

    tmp = (m_cRiRe + 1.0 - cosA2 + tmp)/2.0;
    tmp = (tmp/cosA2);
    tmp -= Norm(r);
    tmp = sqrt(tmp);
    dir = (r/tmp) - normal;
    Normalize(dir);
}

void Splitting::ComputeCRJonesParams(complex &cv, complex &ch)
{
    const double bf = reRiEff*(1.0 - cosA*cosA) - 1.0;
    double im = (bf > 0) ? sqrt(bf) : 0;

    const complex sq(0, im);
    complex tmp0 = m_ri * cosA;
    complex tmp1 = m_ri * sq;

    cv = (cosA - tmp1)/(tmp1 + cosA);
    ch = (tmp0 - sq)/(tmp0 + sq);
}

void Splitting::ComputeCosA(const Point3f &normal, const Point3f &incidentDir)
{
    cosA = DotProduct(normal, incidentDir);
}

void Splitting::ComputeRegularBeamsParams(const Point3f &normal,
                                          const Beam &incidentBeam,
                                          Beam &inBeam, Beam &outBeam)
{
    Point3f reflDir = r - normal;
    Normalize(reflDir);
    inBeam.SetLight(reflDir, incidentBeam.polarizationBasis);

    Point3f refrDir = r/sqrt(s) + normal;
    Normalize(refrDir);
    outBeam.SetLight(refrDir, incidentBeam.polarizationBasis);

    ComputeRegularJonesParams(normal, incidentBeam, inBeam, outBeam);

    if (m_isOpticalPath)
    {
        double path = ComputeSegmentOpticalPath(incidentBeam, inBeam.Center());
#ifdef _DEBUG // DEB
        inBeam.ops = incidentBeam.ops;
        outBeam.ops = incidentBeam.ops;
        inBeam.ops.push_back(path);
        outBeam.ops.push_back(path);
#e


#include "omp.h"
#include "./Eigen/Eigen"
#include <string>
#include <iostream>
#include <fstream>
#include <vector>

void ReadBinAndOutputJacobianVec(const std::string& directory, Eigen::VectorXd& sigma, Eigen::VectorXd& data, Eigen::VectorXd& loss, Eigen::VectorXd& grad) {
    // **************************************************
    int num_ind_meas, num_param, temp;
    double temp_d;
    Eigen::MatrixXi elec;
    Eigen::VectorXd fcalc;
    Eigen::MatrixXd Jacobian;
    Eigen::VectorXd loss_sig2;
    // Open the binary file and read the data
    std::ifstream inputFile(directory+"/R2_forward.bin", std::ios::binary);
    if (!inputFile) {
        std::cout << "Failed to open R2_forward.bin" << std::endl;
        return;
    }
    // Read num_ind_meas and num_param
    inputFile.read(reinterpret_cast<char*>(&temp), sizeof(temp));
    inputFile.read(reinterpret_cast<char*>(&num_ind_meas), sizeof(num_ind_meas));
    inputFile.read(reinterpret_cast<char*>(&num_param), sizeof(num_param));
    // std::cout << num_ind_meas << "    " << num_param << std::endl;
    // Resize vectors
    fcalc.resize(num_ind_meas);
    elec.resize(4, num_ind_meas);
    Jacobian.resize(num_param, num_ind_meas);
    // Read the data into arrays
    for (int j = 0; j < 4; ++j) {
        inputFile.read(reinterpret_cast<char*>(&temp), sizeof(temp));
        inputFile.read(reinterpret_cast<char*>(&temp), sizeof(temp));
        for(int jj = 0 ; jj < num_ind_meas; jj++ ) {
            inputFile.read(reinterpret_cast<char*>(&elec(j,jj)), sizeof(int));
        }
    }
    // read data
    inputFile.read(reinterpret_cast<char*>(&temp_d), sizeof(temp_d));
    for(int jj = 0 ; jj < num_ind_meas; jj++ ) {
        inputFile.read(reinterpret_cast<char*>(&fcalc(jj)), sizeof(double));
    }
    // read Jacobian
    for (int j = 0; j < num_param; ++j) {
        inputFile.read(reinterpret_cast<char*>(&temp_d), sizeof(temp_d));
        for(int jj = 0 ; jj < num_ind_meas; jj++ ) {
            inputFile.read(reinterpret_cast<char*>(&Jacobian(j,jj)), sizeof(double));
        }
    }
    inputFile.close();

    // delete
    std::string command = "cd " + directory + "&& rm R2_forward.bin";
    int result = system(command.c_str());
    // **************************************************
    // Write the data to R2_forward.dat
    // std::ofstream outputFile1(directory + "/R2_forward.dat");
    // if (!outputFile1) {
    //     std::cerr << "Failed to open R2_forward.dat" << std::endl;
    //     return;
    // }
    // for (int i = 0; i < num_ind_meas; ++i) {
    //     outputFile1 << i + 1 << "\t\t";
    //     for (int j = 0; j < 4; ++j) {
    //         outputFile1 << elec(j,i) <<"\t\t";
    //     }
    //     outputFile1  << fcalc(i) << std::endl;
    // }
    // outputFile1.close();
    // // Write the data to R2_Jacobian.dat
    // std::ofstream outputFile2(directory +"/R2_Jacobian.dat");
    // if (!outputFile2) {
    //     std::cerr << "Failed to open R2_Jacobian.dat" << std::endl;
    //     return;
    // }
    // for (int j = 0; j < num_param; ++j) {
    //     outputFile2 << j + 1 << std::endl;
    //     for (int i = 0; i < num_ind_meas; ++i) {
    //         outputFile2 << Jacobian(j,i) << std::endl;
    //     }
    // }
    // outputFile2.close();
    // std::cout << "all ok" << std::endl;
    // **************************************************
    // caluate d(Resistance)/dlog(sigma) from dlog(Resistance)/dlog(sigma)

    for (int j = 0; j < num_param; ++j) {
        for(int jj = 0 ; jj < num_ind_meas; jj++ ) {
            Jacobian(j,jj) = Jacobian(j,jj) * fcalc(jj);
        }
    }
    loss.resize(num_ind_meas);
    loss_sig2.resize(num_ind_meas);
    for(int i = 0 ; i < num_ind_meas ; i++) {
        // loss(i) = ( log(fcalc(i)) - data(i) ) / sigma(i) ;
        loss(i) = ( fcalc(i) - data(i) ) / sigma(i) ;
        loss_sig2(i) = loss(i) / sigma(i);
        // loss(i) = ( log_res(i) - data(i) );
    }
    grad = Jacobian * loss_sig2 ;

    // loss.resize(num_ind_meas);
    // loss_sig2.resize(num_ind_meas);
    // for(int i = 0 ; i < num_ind_meas ; i++) {
    //     // loss(i) = ( log_res(i) - data(i) ) / sigma(i) ;
    //     loss(i) = ( log(fcalc(i)) - data(i) ) / sigma(i) ;
    //     loss_sig2(i) = loss(i) / sigma(i);
    //     // loss(i) = ( log_res(i) - data(i) );
    // }
    // grad = Jacobian * loss_sig2 ;
}

void RunAndCalc(const std::string& directory, Eigen::VectorXd& sigma, Eigen::VectorXd& data, Eigen::VectorXd& loss, Eigen::VectorXd& grad) {
    // 构造命令
    std::string command = "cd " + directory + "&& sh run.sh";
    // std::cout << command << std::endl;
    // 执行命令
    int result = system(command.c_str());
    // result = system(std::string("ls").c_str());
    // if (result == 0) {
    //     std::cout << "Program " << directory << "is successfully." << std::endl;
    // } else {


#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <geometry_msgs/msg/pose.hpp>
#include <ament_index_cpp/get_package_share_directory.hpp>
#include "gazebo_utils_client.hpp"
#include <random>
#include <fstream>
#include <sstream>
#include <filesystem>
#include <vector>
#include <memory>
#include <chrono>

/**
* @class ModelSpawnerNode
* @brief ROS2 node that manages spawning/deleting models and capturing camera images
*/
class ModelSpawnerNode : public rclcpp::Node
{
public:
    ModelSpawnerNode() : Node("model_spawner_node"),
                        current_model_index_(0),
                        image_counter_(0),
                        model_spawned_(false),
                        operation_in_progress_(false),
                        spawn_delay_timer_(nullptr)
    {
        model_names_ = {
            "battery_9v_leader",
            "battery_energizer",
            "battery_varita",
            "lipo_battery"
        };

        loadModelSDFs();
        initializeRandomGenerators();

        camera_sub_ = this->create_subscription<sensor_msgs::msg::Image>(
            "/camera/image_raw",
            1,
            std::bind(&ModelSpawnerNode::cameraCallback, this, std::placeholders::_1)
        );

        std::filesystem::create_directories("captured_images");
        RCLCPP_INFO(this->get_logger(), "ModelSpawnerNode initialized and ready");
    }

    void start()
    {
        auto node_ptr = this->rclcpp::Node::shared_from_this();
        gazebo_client_ = std::make_unique<GazeboUtilsClient>(node_ptr);

        timer_ = this->create_wall_timer(
            std::chrono::seconds(5),
            std::bind(&ModelSpawnerNode::timerCallback, this)
        );

        RCLCPP_INFO(this->get_logger(), "ModelSpawnerNode started");
    }

private:
    void loadModelSDFs()
    {
        std::string package_path = ament_index_cpp::get_package_share_directory("ros2_eval_task");

        for (const auto& model_name : model_names_) {
            std::string sdf_path = package_path + "/models/" + model_name + "/model.sdf";

            std::ifstream file(sdf_path);
            if (file.is_open()) {
                std::stringstream buffer;
                buffer << file.rdbuf();
                model_sdfs_[model_name] = buffer.str();
                RCLCPP_INFO(this->get_logger(), "Loaded SDF for model: %s", model_name.c_str());
            } else {
                RCLCPP_ERROR(this->get_logger(), "Failed to load SDF for model: %s", model_name.c_str());
            }
        }
    }

    void initializeRandomGenerators()
    {
        random_engine_ = std::default_random_engine(
            std::chrono::system_clock::now().time_since_epoch().count()
        );
        x_distribution_ = std::uniform_real_distribution<double>(-0.21, 0.21);
        y_distribution_ = std::uniform_real_distribution<double>(-0.43, 0.43);
    }

    void timerCallback()
    {
        if (operation_in_progress_) {
            RCLCPP_WARN(this->get_logger(), "Previous operation still in progress, skipping this cycle");
            return;
        }

        std::string model_name = model_names_[current_model_index_];

        if (model_sdfs_.find(model_name) == model_sdfs_.end()) {
            RCLCPP_ERROR(this->get_logger(), "SDF not loaded for model: %s", model_name.c_str());
            current_model_index_ = (current_model_index_ + 1) % model_names_.size();
            return;
        }

        geometry_msgs::msg::Pose pose;
        pose.position.x = x_distribution_(random_engine_);
        pose.position.y = y_distribution_(random_engine_);
        pose.position.z = 1.1;
        pose.orientation.x = 0.0;
        pose.orientation.y = 0.0;
        pose.orientation.z = 0.0;
        pose.orientation.w = 1.0;

        operation_in_progress_ = true;
        model_spawned_ = false;

        RCLCPP_INFO(this->get_logger(), "Starting spawn cycle for: %s", model_name.c_str());

        std::string new_instance_name = model_name + "_instance_" + std::to_string(image_counter_);
        startSpawnSequence(model_name, new_instance_name, pose);
    }

    void startSpawnSequence(const std::string& model_base_name, const std::string& new_instance_name, const geometry_msgs::msg::Pose& pose)
    {
        auto sdf_xml = model_sdfs_[model_base_name];

        auto it = existing_model_instances_.find(model_base_name);
        if (it != existing_model_instances_.end()) {
            std::string old_instance_to_delete = it->second;
            RCLCPP_INFO(this->get_logger(), "Found existing model instance: %s, deleting it first", old_instance_to_delete.c_str());

            gazebo_client_->delete_model_async(old_instance_to_delete,
                [this, model_base_name, new_instance_name, pose, sdf_xml, old_instance_to_delete](GazeboUtilsClient::DeleteFuture future) {
                    auto response = future.get();
                    if (response->su


// Copyright Epic Games, Inc. All Rights Reserved.

#include "ShippingToolStyle.h"
#include "Styling/SlateStyleRegistry.h"
#include "Framework/Application/SlateApplication.h"
#include "Slate/SlateGameResources.h"
#include "Interfaces/IPluginManager.h"
#include "Styling/SlateStyleMacros.h"

#define RootToContentDir Style->RootToContentDir

TSharedPtr<FSlateStyleSet> FShippingToolStyle::StyleInstance = nullptr;

void FShippingToolStyle::Initialize()
{
	if (!StyleInstance.IsValid())
	{
		StyleInstance = Create();
		FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
	}
}

void FShippingToolStyle::Shutdown()
{
	FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
	ensure(StyleInstance.IsUnique());
	StyleInstance.Reset();
}

FName FShippingToolStyle::GetStyleSetName()
{
	static FName StyleSetName(TEXT("ShippingToolStyle"));
	return StyleSetName;
}

const FVector2D Icon16x16(16.0f, 16.0f);
const FVector2D Icon20x20(20.0f, 20.0f);

TSharedRef< FSlateStyleSet > FShippingToolStyle::Create()
{
	TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("ShippingToolStyle"));
	Style->SetContentRoot(IPluginManager::Get().FindPlugin("ShippingTool")->GetBaseDir() / TEXT("Resources"));

	Style->Set("ShippingTool.OpenPluginWindow", new IMAGE_BRUSH_SVG(TEXT("PlaceholderButtonIcon"), Icon20x20));

	return Style;
}

void FShippingToolStyle::ReloadTextures()
{
	if (FSlateApplication::IsInitialized())
	{
		FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
	}
}

const ISlateStyle& FShippingToolStyle::Get()
{
	return *StyleInstance;
}


#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <FastLED.h>

#define NUM_LEDS_STRIP1 20
#define NUM_LEDS_STRIP2 20
#define NUM_LEDS_STRIP3 20

#define DATA_PIN1 23
#define DATA_PIN2 22
#define DATA_PIN3 21

CRGB strip1[NUM_LEDS_STRIP1];
CRGB strip2[NUM_LEDS_STRIP2];
CRGB strip3[NUM_LEDS_STRIP3];

/*
  ESP32 MQTT LED Controller
  - Connects to WiFi
  - Subscribes to topic "IoT_Undip_ESP32"
  - Turns LED ON when receiving "1"
  - Turns LED OFF when receiving "0"
*/

// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";

// MQTT broker
const char* mqtt_server = "broker.hivemq.com";
const char* mqtt_topic = "IoT_Undip_ESP32";

WiFiClient espClient;
PubSubClient client(espClient);

// Pattern Procedure

char current_pattern = '0';

void turnOff(CRGB* strip, int numLeds){
    for(int i = 0; i < numLeds; i++) {
        strip[i] = CHSV(0,0,0);
    }
}

void rainbowPattern(CRGB* strip, int numLeds) {
    static uint8_t startHue = 0;
    startHue += 2;

    for(int i = 0; i < numLeds; i++) {
        strip[i] = CHSV(startHue + (i * 10), 255, 255);
    }
}

void snakePattern(CRGB* strip1, int numLeds1, CRGB* strip2, int numLeds2, CRGB* strip3, int numLeds3) {
    static int head = 0;
    static int totalLeds = numLeds1 + numLeds2 + numLeds3;
    const int SNAKE_LENGTH = 8;

    // Clear all strips
    for(int i = 0; i < numLeds1; i++){strip1[i] = CRGB::Black;}
    for(int i = 0; i < numLeds2; i++){strip2[i] = CRGB::Black;}
    for(int i = 0; i < numLeds3; i++){strip3[i] = CRGB::Black;}

    for(int i = 0; i < SNAKE_LENGTH; i++) {
        int pos = (head - i + totalLeds) % totalLeds;
        if(pos < numLeds1) {
            // LED is on strip 1
            strip1[pos] = CRGB(255, 0, 0);
        }
        else if(pos < numLeds1 + numLeds2) {
			 // LED is on strip 2
            int strip2_pos = (numLeds2 - 1) - (pos - numLeds1);
            strip2[strip2_pos] = CRGB(255, 0, 0);
        }
        else {
			 // LED is on strip 3
            strip3[pos - numLeds1 - numLeds2] = CRGB(255, 0, 0);
        }
    }
    head = (head + 1) % totalLeds;
}

void fastPattern(CRGB* strip1, int numLeds1, CRGB* strip2, int numLeds2, CRGB* strip3, int numLeds3) {
	static int head1 = 0;
	static int head2 = 0;
	static int head3 = 0;

    for(int i = 0; i < numLeds1; i++){strip1[i] = CRGB::Black;}
    for(int i = 0; i < numLeds2; i++){strip2[i] = CRGB::Black;}
    for(int i = 0; i < numLeds3; i++){strip3[i] = CRGB::Black;}

    for(int i = 0; i <= 5; i++) {
        int pos = (head1 - i + numLeds1) % numLeds1;
        strip1[pos] = CRGB(0,0,255);
    }
	for(int i = 0; i <= 5; i++) {
        int pos = (head2 - i + numLeds2) % numLeds2;
        strip2[pos] = CRGB(0,0,255);
    }
	for(int i = 0; i <= 5; i++) {
        int pos = (head3 - i + numLeds3) % numLeds3;
        strip3[pos] = CRGB(0,0,255);
    }
    head1 = (head1 + 1) % numLeds1;
	head2 = (head2 + 1) % numLeds2;
	head3 = (head3 + 1) % numLeds3;
}

void arrowPattern(CRGB* strip1, int numLeds1, CRGB* strip2, int numLeds2, CRGB* strip3, int numLeds3){
	static int head1 = 0;
	static int head2 = 0;
	static int head3 = 0;

    for(int i = 0; i < numLeds1; i++){strip1[i] = CRGB::Black;}
    for(int i = 0; i < numLeds2; i++){strip2[i] = CRGB::Black;}
    for(int i = 0; i < numLeds3; i++){strip3[i] = CRGB::Black;}

    for(int i = 2; i <= 7; i++) {
        int pos = (head1 - i + numLeds1) % numLeds1;
        strip1[pos] = CRGB(0,255,0);
    }
	for(int i = 0; i <=5; i++) {
        int pos = (head2 - i + numLeds2) % numLeds2;
        strip2[pos] = CRGB(0,255,0);
    }
	for(int i = 2; i <= 7; i++) {
        int pos = (head3 - i + numLeds3) % numLeds3;
        strip3[pos] = CRGB(0,255,000);
    }
    head1 = (head1 + 1) % numLeds1;
	head2 = (head2 + 1) % numLeds2;
	head3 = (head3 + 1) % numLeds3;
}

// connect to WiFi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

// handle incoming MQTT messages
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(" | Message: ");

  String messageTemp;
  for (unsigned int i = 0; i < length; i++) {
    messageTemp += (char)message[i];
  }
  Serial.println(messageTemp);

  if (messageTemp == "1") {
    current_pattern = '1';
    Serial.println("LED ON");
  } else if (messageTemp == "0") {
    current_pattern = '0';
    Serial.println("LED OFF");
  } else if (messageTemp == "2") {
    current_pattern = '2';
    Serial.println("RAINBOW PATTERN");
  } else if (messageTemp == "3") {
    current_pattern = '3';
    Serial.println("SNAKE PATTERN");
  } else if (messageTemp == "4") {
    current_pattern = '4';


// AES Key Scanner (Experimental)
// -------------------------------------------------
// Purpose:
//   Detects Type-2 AES key patterns used in Unreal Engine.
//
// Method:
//   Identifies functions that store 8 immediate constants
//   into stack locals — a common signature for Type-2
//   AES encryption keys in UE4/UE5 binaries.
//
// Compatibility:
//   Expected to work across Unreal Engine versions
//   4.19 through 5.6.
//
// Author:
//   GHFear

#include <capstone/capstone.h>
#include <cstdint>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
#include <deque>
#include <algorithm>
#include <iomanip>
#include <unordered_set>
#include <chrono>

struct Config {
    size_t minUniqueStores = 8;
    bool   requirePrologue  = true;
    size_t maxFuncBytes     = 2048;
    size_t maxInstrs        = 512;
    size_t backtrackBytes   = 64;
    size_t overlapBytes     = 128;
    size_t chunkSize        = 1 << 20;
    size_t progressPeriodMs = 200;
};

struct Match {
    size_t offset;
    size_t length;
    size_t funcStart;
};

struct MatchWithValues : public Match {
    std::vector<uint8_t> values;
};

static std::vector<uint8_t> readFile(const std::string& path) {
    std::ifstream f(path, std::ios::binary);
    if (!f) return {};
    return { std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>() };
}

#pragma pack(push,1)
struct IMAGE_DOS_HEADER_MIN { uint16_t e_magic; uint16_t _pad[29]; int32_t e_lfanew; };
struct IMAGE_FILE_HEADER_MIN { uint16_t Machine, NumberOfSections; uint32_t TimeDateStamp, PointerToSymbolTable, NumberOfSymbols; uint16_t SizeOfOptionalHeader, Characteristics; };
struct IMAGE_DATA_DIRECTORY_MIN { uint32_t VirtualAddress, Size; };
struct IMAGE_OPTIONAL_HEADER64_MIN {
    uint16_t Magic; uint8_t _pad1[14];
    uint64_t ImageBase;
    uint32_t SectionAlignment, FileAlignment; uint8_t _pad2[56];
    uint32_t NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY_MIN DataDirectory[16];
};
struct IMAGE_NT_HEADERS64_MIN { uint32_t Signature; IMAGE_FILE_HEADER_MIN FileHeader; IMAGE_OPTIONAL_HEADER64_MIN OptionalHeader; };
struct IMAGE_SECTION_HEADER_MIN { uint8_t Name[8]; union { uint32_t PhysicalAddress; uint32_t VirtualSize; } Misc; uint32_t VirtualAddress, SizeOfRawData, PointerToRawData, PointerToRelocations, PointerToLinenumbers; uint16_t NumberOfRelocations, NumberOfLinenumbers; uint32_t Characteristics; };
#pragma pack(pop)

static bool get_executable_regions_PE(const std::vector<uint8_t>& file, std::vector<std::pair<size_t,size_t>>& regions) {
    regions.clear();
    if (file.size() < sizeof(IMAGE_DOS_HEADER_MIN)) return false;
    auto* dos = reinterpret_cast<const IMAGE_DOS_HEADER_MIN*>(file.data());
    if (dos->e_magic != 0x5A4D) return false;
    size_t nt_off = static_cast<size_t>(dos->e_lfanew);
    if (nt_off + sizeof(IMAGE_NT_HEADERS64_MIN) > file.size()) return false;
    auto* nt = reinterpret_cast<const IMAGE_NT_HEADERS64_MIN*>(file.data() + nt_off);
    if (nt->Signature != 0x00004550) return false;
    const auto& fh = nt->FileHeader;
    size_t sec_off = nt_off + sizeof(uint32_t) + sizeof(IMAGE_FILE_HEADER_MIN) + fh.SizeOfOptionalHeader;
    if (sec_off + static_cast<size_t>(fh.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER_MIN) > file.size()) return false;
    auto* sh = reinterpret_cast<const IMAGE_SECTION_HEADER_MIN*>(file.data() + sec_off);
    for (int i = 0; i < fh.NumberOfSections; ++i) {
        const bool exe = (sh[i].Characteristics & 0x20000000) != 0;
        if (exe && sh[i].PointerToRawData && sh[i].SizeOfRawData) {
            size_t off = sh[i].PointerToRawData;
            size_t sz  = sh[i].SizeOfRawData;
            if (off + sz <= file.size()) regions.emplace_back(off, sz);
        }
    }
    return !regions.empty();
}

static inline bool bytes_have_prologue(const std::vector<uint8_t>& buf, size_t off, size_t end) {
    if (off + 4 > end) return false;
    return buf[off] == 0x55 && buf[off+1] == 0x48 && buf[off+2] == 0x8B && buf[off+3] == 0xEC;
}

static inline bool safe_has_detail(const cs_insn* insn) { return insn && insn->detail; }

static inline bool is_stack_imm_dword_store(const cs_insn* insn) {
    if (!safe_has_detail(insn)) return false;
    if (insn->id != X86_INS_MOV) return false;
    const cs_x86& x = insn->detail->x86;
    if (x.op_count != 2) return false;
    const cs_x86_op& dst = x.operands[0];
    const cs_x86_op& src = x.operands[1];
    if (dst.type != X86_OP_MEM) return false;
    if (dst.size != 4) return false;
    if (dst.mem.base != X86_REG_RBP) return false;
    if (dst.mem.index != X86_REG_INVALID) return false;
    if (src.type != X86_OP_IMM) return false;
    if (src.size != 4) return false;
    return true;
}

static size_t find_prologue(const std::vector<uint8_t>& buf, size_t fileEnd, size_t matchOff, size_t backtrackLimit) {
    if (matchOff == 0) return 0;
    size_t start = (matchOff > backtrackLimit) ? (matchOff - backtrackLimit)


/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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 "apexservice.h"

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/result.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/apex/BnApexService.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
#include <binder/LazyServiceRegistrar.h>
#include <binder/ProcessState.h>
#include <binder/Status.h>
#include <dirent.h>
#include <private/android_filesystem_config.h>
#include <stdio.h>
#include <stdlib.h>
#include <utils/String16.h>

#include "apex_constants.h"
#include "apex_file.h"
#include "apex_file_repository.h"
#include "apexd.h"
#include "apexd_metrics.h"
#include "apexd_session.h"
#include "string_log.h"

using android::base::Join;
using android::base::Result;

namespace android {
namespace apex {
namespace binder {
namespace {

using BinderStatus = ::android::binder::Status;

BinderStatus CheckCallerIsRoot(const std::string& name) {
  uid_t uid = IPCThreadState::self()->getCallingUid();
  if (uid != AID_ROOT) {
    std::string msg = "Only root is allowed to call " + name;
    return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
                                           String8(msg.c_str()));
  }
  return BinderStatus::ok();
}

BinderStatus CheckCallerSystemOrRoot(const std::string& name) {
  uid_t uid = IPCThreadState::self()->getCallingUid();
  if (uid != AID_ROOT && uid != AID_SYSTEM) {
    std::string msg = "Only root and system_server are allowed to call " + name;
    return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
                                           String8(msg.c_str()));
  }
  return BinderStatus::ok();
}

BinderStatus CheckCallerSystemKsOrRoot(const std::string& name) {
  uid_t uid = IPCThreadState::self()->getCallingUid();
  if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_KEYSTORE) {
    std::string msg =
        "Only root, keystore, and system_server are allowed to call " + name;
    return BinderStatus::fromExceptionCode(BinderStatus::EX_SECURITY,
                                           String8(msg.c_str()));
  }
  return BinderStatus::ok();
}

class ApexService : public BnApexService {
 public:
  using BinderStatus = ::android::binder::Status;
  using SessionState = ::apex::proto::SessionState;

  ApexService(){};

  BinderStatus stagePackages(const std::vector<std::string>& paths) override;
  BinderStatus unstagePackages(const std::vector<std::string>& paths) override;
  BinderStatus submitStagedSession(const ApexSessionParams& params,
                                   ApexInfoList* apex_info_list) override;
  BinderStatus markStagedSessionReady(int session_id) override;
  BinderStatus markStagedSessionSuccessful(int session_id) override;
  BinderStatus getSessions(std::vector<ApexSessionInfo>* aidl_return) override;
  BinderStatus getStagedSessionInfo(
      int session_id, ApexSessionInfo* apex_session_info) override;
  BinderStatus getStagedApexInfos(const ApexSessionParams& params,
                                  std::vector<ApexInfo>* aidl_return) override;
  BinderStatus getActivePackages(std::vector<ApexInfo>* aidl_return) override;
  BinderStatus getAllPackages(std::vector<ApexInfo>* aidl_return) override;
  BinderStatus abortStagedSession(int session_id) override;
  BinderStatus revertActiveSessions() override;
  BinderStatus resumeRevertIfNeeded() override;
  BinderStatus snapshotCeData(int user_id, int rollback_id,
                              const std::string& apex_name) override;
  BinderStatus restoreCeData(int user_id, int rollback_id,
                             const std::string& apex_name) override;
  BinderStatus destroyDeSnapshots(int rollback_id) override;
  BinderStatus destroyCeSnapshots(int user_id, int rollback_id) override;
  BinderStatus destroyCeSnapshotsNotSpecified(
      int user_id, const std::vector<int>& retain_rollback_ids) override;
  BinderStatus recollectPreinstalledData() override;
  BinderStatus markBootCompleted() override;
  BinderStatus calculateSizeForCompressedApex(
      const CompressedApexInfoList& compressed_apex_info_list,
      int64_t* required_size) override;
  BinderStatus reserveSpaceForCompressedApex(
      const CompressedApexInfoList& compressed_apex_info_list) override;
  BinderStatus inst